Live data from Hacker News

Why I Write Games in C (yes, C)

jonathanwhiting.com

221–230 of 556 posts

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

#221
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…

Well, most game engines tend to have a scripting language of some sort and that's usually GC'd. The reason that works ok is usually if you're embedding a language you can control how much time is spent on GC (and in the language itself). Doing an entire game from scratch in a memory managed language, it's not so much that GC is slow, it's that it lacks adequate control. (I don't think it's a coincidence that a lot of the popular runtimes -- python for instance -- tend to be reference counted with GC mostly reserved for cleaning up cycles.) If you're concerned with performance, it's not so much that GC _can't_ be fast, it's that you really don't want to give up control on that sort of thing because GC spikes are really annoying to fix.

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

#222

Earlier quoted context omitted.

> but when the program compiles, it works That's not even true for languages with dependent types, which Rust lacks.

And at the same time, I've heard people say "when it compiles, it works" about much weaker type systems, like Go's. It just seems to mean "this language catches more errors at compile time than the previous language I used."

> It just seems to mean "this language catches more errors at compile time than the previous language I used."

That is a fair interpretation. I've programmed mostly in C# and Java because that's what was required at the time. I also know enough C and C++ to aim at my toes instead of the entire foot. So the comparison is between strongly typed imperative programming languages which are syntactically close to Rust.

Also, I like that Rust isn't OoP, but try to not get baited into that discussion.

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

#223

Earlier quoted context omitted.

I know this subject quite well and I will later publish a detailed article. The real run-time cost of memory management done well in a modern game engine written without OOP features is extremely low. We usually use a few very simple specialized memory allocators, you'd probably be surprised by how simple memory management can be. The trick is to not use the same allocator when the lifetime is different. Some resourc…

+1. We have a large Rust code base, and we forbid Vec and the other collections. Instead, we have different types of global arenas, bump allocators, etc. that you can use. These all pre-allocate memory once at start up, and... that's it. When you have well defined allocation patterns, allocating a new "object" is just a "last += 1;` and once you are done you deallocate thousands of objects by just doing `last -= size…

Do you use any public available crate for those allocators? Would love to take a look. I'm currently trying to write a library for no-std which requires something like that. I currently have written a pool of bump allocators. For each transaction you grab an allocator from the pool, allocate as many objects from it as necessary, and then everything gets freed back to the pool. However it's a bit hacky right now, so I'm wondering whether there is already something better out there.

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

#224
post #129
post #32

Earlier quoted context omitted.

I'm not sure C is that much closer to the hardware, nowadays.

C is closer to the hardware in the sense that with any given C code, I can pretty much predict what the generated assembly will look like. You cannot say the same for, say, Python.

> pretty much

Not really... Not only the generated assembly code heavily depends on the compiler (LLVM, gcc, Intel, MSVC...) and the optimization settings, you cannot be completely sure what the machine code generated by the assembler even looks like these days.

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

#225
Anyone who is interested in secure, plain, well-written C-code should checkout the OpenBSD project. I've just been browsing through the code to brush-up on my C as it's been a few years since I've had to use C in anger, and it's a joy to read.

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

#226
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…

The problem with GC is that releasing memory is not deterministic. With a tracing GC, you don't know exactly when a pause will happen, and you don't know how long it will take.

Static lifetime management, by contrast, gives the same benefits to memory errors that static typing does to type-mismatch errors: you know, at compile time, how long an object will live and when it will be released. And armed with this knowledge, you can then more effectively profile and optimize.

There are, however, much better ways to go about it than C provides. RAII in C++ and Rust and even ARC in the iOS runtimes allow you to get most of the benefits of automatic memory management while still providing strict, deterministic lifetime guarantees.

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

#227
post #86

Earlier quoted context omitted.

> and the times you find yourself "at the mercy" of the garbage collector is pretty damn frustrating. You're still at the mercy of the malloc implementation. I've seen some fairly nasty behaviour involving memory leaks and weird pauses on free coming from a really hostile allocation pattern causing fragmentation in jemalloc's internal data.

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 writing custom allocation and cleanup in e.g. Cython. Probably similar in many different managed environment languages.

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

#228
post #132

Earlier quoted context omitted.

Disclaimer: I'm not a game developer; but, I've worked on a lot of projects with tight frame time requirements in my time at Netflix on the TVUI team. I also have no experience in Go so I can't comment on the specifics of that garbage collector vs. V8. I don't think it's necessarily that it "can't" work as much as it takes away a critical element of control from the game developers and the times you find yourself "at…

With JS the trick is to avoid creating new objects and instead have a pool of objects that are always referenced.

But then that damages performance because your objects are always globally visible rather than being able to be optimised away.

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

#229
post #170
post #132

Earlier quoted context omitted.

With JS the trick is to avoid creating new objects and instead have a pool of objects that are always referenced.

Once I wrote a very small vector library in JS for this very reason: almost all JS vector libraries out there tend to dynamically create new vectors for every vector binary operation, this makes JS GC go nuts. It's also prohibitively expensive to dynamically instantiate typedarray based vectors on the fly, even though they are generally faster to operate on... most people focus on fixing the latter in order to be abl…

This kind of place orientated programming can make the actual algorithm very hard to follow. I really hope that JS gets custom value types in the future.

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

#230
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…

I just want to say that no, you don’t need to free the resources. It's very possible to use a fix amount of heap memory during the whole lifecycle of your game. In fact I think that’s what people should aim for in 90% of the cases.
Post reply on HN