It's a lost cause: there's no such thing as "sane" or "orthodox" C++. Instead, use something actually sane like Go. Or Rust, if you really must (first bad pun is free, then it's 50 cents each).
Is there not a point where GC overhead becomes negligible? There have been production examples of Go maintaining sub-millisecond GC pauses with a multi-GB heap under a server workload.
https://twitter.com/brianhatfield/status/804355831080751104
Surely there are better reasons to disregard Go for gamedev by now.
I've dipped my toes into using OpenGL and Go a few times and it seems pretty nice. But I'm entry level graphics programming and so it scares me off to go further (surely someone would have used Go by now in a 3d game, if you can do Minecraft on the JVM, why not Go)?
I keep wondering if it's not possible or if there's just not a lot of overlap between Go programmers and gamedevs? Wish someone knew.
I wouldn't predict a lot of overlap. On the game dev side, Go offers nothing new, and the forced untuneable gc will be an instant turnoff for the usual reasons. On the Go side, my outside perspective is most of its users seem to be focused on web server backends, trying to justify async everywhere, and/or rewriting slow Python or Perl or Bash scripts and assuming that makes it a systems language.
Go users interested in diving in to SDL or OpenGL bindings to make a game shouldn't be discouraged. Lots of games are made in all sorts of high level languages, the heavy lifting is put onto a few native libraries. But if the goal is to make a general engine, I'd question its utility apart from fun/learning. Again there are game engines in high level languages (with dark native-level secrets in any that try to be performant) but they don't seem to get traction. Even an engine in e.g. C++ doesn't necessarily help your performance goals (http://www.yosoygames.com.ar/wp/2013/11/on-mike-actons-revie...) if your plan is to make it general instead of make it just support whatever sorts of games you're making and planning to make.
The vast majority of memory in a modern game stores data for the GPU. On a game console the game manages this data itself. If you ever want to ship on a console you better be sure Go can handle the memory visible from the GPU correctly e.g. keep the necessary alignment, ensure the GPU is not reading/writing the memory it's going to modify, do not charge address of anything, preserve layout of structures etc. I never used Go so I don't know if it already does this. But I would be considering these things way before I'd even started looking into performance.
I agree, but the GP comment was in the context of Go. Nim is a newer option I'd like to see tried more, its GC is optional and swappable.
If you never run out of memory you'll also never need to GC. ;) Or even free(), just let the program finish and reset the machine. (Actually not too weird in some embedded systems...) Some languages make it easier to not heap allocate than others, or notice when you are heap allocating. I hear Go does better than Java in this regard. But if you're facing a performance issue at the level where you're fighting the GC as the biggest barrier, and the language doesn't give you much assistance (like being able to choose latency/throughput tradeoffs or controls on non-determinism), that's a sign the language isn't that suitable for that performance problem domain. With performance sensitive games, you're already in the corner of having to worry about hardware details, so there's a strong incentive to just start the fight at the beginning without your hands tied by some language's static GC.
If fact, the majority of them gets abandoned even before memory pressure starts to be a relevant issue.
Even if Go isn't at the same level of D or Modula-3 in regards to memory management (heap, stack, global), it is already quite usable for many types of games.
The important difference is that not everything in Unreal is GC'd, only UObjects. Internally the rendering, animation, networking and other high-performance subsystems don't use GC because they can't afford the overhead. Being able to opt in to GC where it's useful is great, being forced to use it everywhere can be a hassle.
If you're gonna bother with orthodox C++, or Go (suited to 3d games? nobody seems to have tried or lived to tell the tale), or Rust (no libraries anyway, so you may as well use something which wraps C easily and is higher level), why not try Nim?
I think if you were writing C, then Nim might be a good alternative. If you're writing C++, then Nim offers a lot of similar metaprogramming features; but it lacks RAII, which IMO is a monumental drawback. People may dislike C++ for many reasons, but RAII is a killer feature -- there's no question why languages like D and Rust adopted it.
Disclaimer: Not a go apologist, I admire it, but don't use it.
With Go you get a compiler error if you don't do something with that error. You have to explicitly decide to ignore it with `_`. As far as I remember that's quite different from C where you can get an error code, ignore it, and never realize you've missed it.
import "os"
func main() {
os.Open("this file does not exist")
}
This will compile just fine, producing no compiler error or warnings whatsoever. The error is just silently ignored.
Compare to Rust:
use std::fs::File;
fn main() {
File::open("this file does not exist");
}
This will produce the following warning:
warning: unused result which must be used
--> test.rs:14:5
|
14 | File::open("this file does not exist");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: #[warn(unused_must_use)] on by default
This example is a bit contrived, because if you open a file you probably want to do something with it. But imagine something where the only return value you care about is the error, like say "txn.commit()"
A slightly related note: you can get similar behavior in C (and C++) with compiler extensions. In GCC and clang marking function with '__attribute__((warn_unused_result))' will produce a warning if function is called without using the result. Equivalent for MSVC is '_Check_return_'.
Obviously this is not nearly as convenient as your Rust example, but enables some of its the benefits.
Anyways, C++ is much easier to manage than any GC language for a real time application such as this. And your Rust "pun" is a rhyme.