Live data from Hacker News

Why I Write Games in C (yes, C)

jonathanwhiting.com

381–390 of 556 posts

Re: Why I Write Games in C (yes, C)

#381
post #318

Earlier quoted context omitted.

Why even define a malloc() in this environment if it always returns NULL?

So you crash immediately if someone tries to use it or a library gets added that does? Never experienced the malloc() thing but do throw exceptions and fail fast under conditions like these so they're caught in testing.

Like sibling commenter says, a compile/link error is even better and faster than finding out at runtime with a crash.

Re: Why I Write Games in C (yes, C)

#382

Earlier quoted context omitted.

Doesn’t this just change semantics? Whatever custom handlers you wrote for manipulating that big chunk of memory are now the garbage collector. You’re just asking for finer grained control than what the native garbage collection implementation supports, but you are not omitting garbage collection. Ostensibly you could do the exact same thing in e.g. Python if you wanted, by disabling with the gc module and just writi…

C's free() gives memory back to the operating system(1), whereas, as a performance optimization, many GCd languages don't give memory back after they run a garbage collection (see https://stackoverflow.com/questions/324499/java-still-uses-s... ). Every Python program is using a "custom allocator," only it is built in to the Python runtime. You may argue that this is a dishonest use of the term custom allocator, but c…

It's not a performance optimisation not to give space back. GCs could easily give space back after a GC if they know a range (bigger than a page) is empty, it's just that they rarely know it is empty unless they GC everything, and even then there is likely to be a few bytes used. Hence the various experiments with generational GC, to try to deal with fragmentation.

Many C/C++ allocators don't release to the OS often or ever.

Re: Why I Write Games in C (yes, C)

#383
post #278

Earlier quoted context omitted.

I have actually worked on a system where malloc() was forbidden. In fact it always returned null. Buffers were all statically allocated and stack usage was kept to a minimum (it was only a few kB anyways). The software was shipped with a memory map file so you know exactly what each memory address is used for. A lot of test procedures involved reading and writing at specific memory locations. It was for avionics BTW.…

I’d be interested in knowing more if you care to write more about this. I’m currently costing/scoping out what’s required in writing software at that level but don’t really have some real industry insight into what other people do Static memory is something we already do but we’re pretty interested whether industry actually adopts redundant code paths, monitors, to what extent watchdogs (how many cycles can be missed…

I suggest you take a look at the books by Michael Pont and the offerings through his company "SafeTTy Systems". His/Company's work deals with hard real-time systems with all the associated standards.

Re: Why I Write Games in C (yes, C)

#384
post #192
post #167

Earlier quoted context omitted.

this is exactly the kind of dismissive hand-waving that is frustrating. The 18gb heap example is from data collected on production servers at Twitter. Go servers routinely juggle tens of thousands of connections, tens of thousands of simultaneous user sessions, or hundreds of thousands of concurrently running call stacks. We're essentially never talking about 100mb objects since the vast majority of what Go applicati…

I'm not a game developer, just a programming language enthusiast with probably above average understanding of how difficult the problem this is. Can you point out in the post where they expand on my point? The only this I see is this: > Again we kept knocking off these O(heap size) stop the world processes. We are talking about an 18Gbyte heap here. which is exactly my point - even if you remove all O(heap size) lock…

There are plenty of known GC algorithms with arbitrarily bounded pause times. They do limit the speed at which the mutator threads can allocate, but per-frame allocations can be done the same way they are done in a non-GC'd environment (just allocate a pool and return everything to it at the end of each frame), and any allocations that are less frequent will likely be sufficiently rare for such algorithms.

I know people who have written games in common-lisp despite no implementations having anything near a low-latency GC. They do so by not using the allocator at all during the middle of levels (or using it with the GC disabled, then manually GCing during level-load times).

Re: Why I Write Games in C (yes, C)

#385
post #342

Earlier quoted context omitted.

Go has many advantages over C that are not related to GC.

Go was pushed as a C replacement, but very few C programmers switched to it, it seems like it took hearts of some of Python, Ruby, Java etc programmers.

Nonetheless, Go has many advantages over C that are not related to GC.

Re: Why I Write Games in C (yes, C)

#388

Earlier quoted context omitted.

Which is why you generally almost never use the standard malloc to do your piecemeal allocations. A fair number of codebases I've seen allocate their big memory pools at startup, and then have custom allocators which provide memory for (often little-'o') objects out of that pool. You really aren't continually asking the OS for memory on the heap. In fact, doing that is often a really bad idea in general because of th…

Doesn’t this just change semantics? Whatever custom handlers you wrote for manipulating that big chunk of memory are now the garbage collector. You’re just asking for finer grained control than what the native garbage collection implementation supports, but you are not omitting garbage collection. Ostensibly you could do the exact same thing in e.g. Python if you wanted, by disabling with the gc module and just writi…

Getting rid of this buffer is literally nothing. There is no free upon the individual objects needed. You just forget there was anything there and use the same buffer for the next frame. Vs. Waiting for a GC to detect thousands of unused objects in that buffer and discard them, meanwhile creating a new batch of thousands of objects and having to figure out where to put those.

Re: Why I Write Games in C (yes, C)

#389
post #376

Earlier quoted context omitted.

> If you have a garbage collector that runs in 200us The problem is GCs for popular languages are nowhere near this good. People will claim their GC runs in 200us, but it's misleading. For example, they'll say they have a 200us "stop the world" time, but then individual threads can still be blocked for 10ms+. Or they'll quote an average or median GC time, when what matters is the 99.9th percentile time. If you run GC…

Benchmarking a full sweep with 0 objects to free in Julia: julia> @benchmark GC.gc() BenchmarkTools.Trial: memory estimate: 0 bytes allocs estimate: 0 -------------- minimum time: 64.959 ms (100.00% GC) median time: 66.848 ms (100.00% GC) mean time: 67.062 ms (100.00% GC) maximum time: 73.149 ms (100.00% GC) -------------- samples: 75 evals/sample: 1 Julia's not a language normally used for real time programs (and it…

Yep. (You know this, but) just as another data point, an incremental pass takes more like 75 microseconds, and a 'lightly' allocating program probably won't trigger a full sweep (no guarantees though).

Re: Why I Write Games in C (yes, C)

#390
post #46

> The stop-the-world garbage collection is a big pain for games, stopping the world is something you can't really afford to do. I love this opinion from games programmers because they never qualify it and talk about what their latency budgets are and what they do in lieu of a garbage collector. They just hand wave and say "GC can't work". The reality is you still have to free resources, so it's not like the garbage c…

> what I find so deeply frustrating is that the argument that GC can't work in a game engine is never qualified

The program having a say in how the GC behaves would be one requirement IMO.

> you could run a GC on every single frame and use less than 3% of your frame budget on the GC pause

Could I? In what languages?

Post reply on HN