Live data from Hacker News

Why I Write Games in C (yes, C)

jonathanwhiting.com

371–380 of 556 posts

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

#371
post #288

Earlier quoted context omitted.

you can turn off the gc in Go and run it manually. you can also write cache-aligned arrays of structs in Go if you want to. you can allocate a slab and pull from it if you want to. the existence of a GC doesn't preclude these possibilities.

Why pick a language that has a feature you need to immediately turn off? Some people probably want to, but ... why?

Many programmers are very emotional about their language of choice, especially if it is their only one.

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

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

> latency budgets The problem with gc is that it can blow out a frame's budget, and perhaps extend for more than one frame, taking away precious nanosecs, dropping a 60fps down to 15. > what they do in lieu of a garbage collector. Use reference counting. If in the rare case you need circular references then you use a weak pointer, or reclassify your structure so that it's not circular. That said, where and how you ma…

Reference counting is a form of gc though. It even comes with some nondeterminism in the form of release cascades. Usually performs worse than heap analyzers too, due to hitting atomic counters a lot. The lack of heap overhead and simplicity of implementation are the strong points.

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

#373
post #59
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…

In particular I know that Go's GC is optimized for very low latency (rather than throughput), and is not a stop the world GC. So I'm wondering why it doesn't work for games? Are the pauses still too high for games, or is he missing something? Benchmarks or concrete results in Go would be great here. Edit: specifics from https://blog.golang.org/ismmkeynote - Go hugely improved GC latency from 300ms before version 1.5,…

Short stop the world is well and good, but some of the performance impact is pushed to the mutator via write barriers. That can be another can of worms.

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

#374
post #258

I have similar frustrations using C++, but don't feel using C or even Rust would be an improvement, more of "side-grade" due to various tradeoffs those languages have for game development compared to C++. I am excited about the development of both Zig and Jai since they both are trying to fill what I believe is a much needed role of a C-like language with a few more nice language features like better compile-time cod…

imo it's worth pointing out that it's not called "Jai"

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

#375

Earlier quoted context omitted.

Because c++ without OOP still gives you RAII (which is neutered a bit if you don't write your own classes but still), safe pointers, references, lambda, and an immense standard library, to name a few.

C++ RAII is completely gone without the use of classes; it requires something with a destructor.

I guess the OP means pod types (plain Cish structs) where dtors are implicit.

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

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

> 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 is common to work around the GC / avoid allocating), but it is the language I'm most familiar with.

Julia's GC is generational; relatively few sweeps will be full. But seeing that 65ms -- more than 300 times slower than 200us -- makes me wonder.

Test was on an i9 7900X.

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

#377

"This is just an opinion but, it's also objective truth, you'll be a superior human in everyway to lesser mud-blood human's who never managed to release anything. Everyday they'll continue to toil away in the fields like Russia serfs, while you can skip past them like a wise and jolly Rasputin. (I've released exactly zero games independently, so I am too one of the serfs, with only homemade vodka and sweet dreams of…

That’s the exact tone I got from the first words in.

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

#378
post #318

Earlier quoted context omitted.

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

Because even if you don't use it directly, you might use some code that uses it. And even then, it might not ever be called given the way you are reusing the code, so...a dynamic check is the best way to ensure it never actually gets used.

> Because even if you don't use it directly, you might use some code that uses it.

It seems extremely unlikely that any general purpose code you might adopt, which happens to invoke malloc() at all, would be fit for purpose in such a restricted environment without substantial modification; in which case you would just remove the malloc() calls as well.

> And even then, it might not ever be called given the way you are reusing the code, so...a dynamic check is the best way to ensure it never actually gets used.

In such a restricted environment, it is unlikely you just have unknown deadcode in your project. "Oh, those parts that call malloc()? They're probably not live code and we'll find out via a crash at runtime." That's like the opposite of what you want in a hard realtime system.

So, no — a static, compile/link time check is a strictly superior way to ensure it never gets used.

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

#379
post #318

Earlier quoted context omitted.

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

Some things are okay to allocate at some point in time. So you can disable malloc later when you no longer want it to provide memory.

That's plausible, but not how OP defined it:

> a system where malloc() was forbidden. In fact it always returned null.

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

#380
post #327
post #182

Earlier quoted context omitted.

Almost a decade ago I was writing a desktop toolkit in Lua 5.1 and gdk/cairo bindings. Let’s say for fun, because it never seen the light in planned business. But it had animations and geometry dynamics (all soft, no hw accel). While GC seems to be fast and data/widget count was small, it suddenly froze every dozen of seconds for a substantial amount of time. First thing I tried was to trigger a [partial] collection…

>worst side of gc is that it is unpredictable This is simply not the case. Its still just code after all. The problem was you were fighting the GC but that's just the symptom. The clear problem was leaking something every frame. With all the tooling these days its pretty easy to see exactly what is getting allocated and garbage collected so you know where to focus your efforts.

I started with C actually, but good ui is hard, and I decided to use Lua for a reason of not writing it all in C and hand-optimized style. I was forced to write ugly non-allocating code anyway, which defeated that idea completely. To focus your efforts, there must be a reason for these efforts in the first place.
Post reply on HN