5 ms·
> if you want to write something that is GC-less, you're on your own GC allocations only harm performance when they happen often. It’s totally fine to allocate
by Const-me 2y ago
> if you want to write something that is GC-less, you're on your own
GC allocations only harm performance when they happen often. It’s totally fine to allocate stuff on managed heap on startup, initialization, re-initialization, or similar.
Another thing, modern C# is very usable even without GC allocations. Only some pieces of the standard library allocate garbage (most notably LINQ), the majority of the standard library doesn’t create garbage. Moreover, I believe that percentage grows over time as the standard library adds API methods operating on modern things like Span<byte> in addition to the managed arrays. Spans can be backed by stack memory, or unmanaged heap, or even weird stuff like the pointers received from mmap() Linux kernel call to a device driver.
> I'm not talking HFT here, I'm talking about performance intensive games.
You want to minimize and ideally eliminate the garbage created by `operator new` during gameplay of a C# game. But it’s exactly the same in C++, you want to minimize and ideally eliminate the malloc / free runtime library calls during gameplay of a C++ game.
In practice, games use pools, per-frame arena allocators, and other tricks to achieve that. This is language agnostic, C++ standard library doesn’t support any of these things either.
- Ygg2 2y ago> most notably LINQ That's the culprit and most libraries use the hell out of it. I mean it's a widely touted feature of C#, it makes sense to use it. Which is a problem once it becomes one of your dependencies and starts hogging your memory. What to do to offending library: A) Rewrite it? B) Work around it? C) Cry?
- neonsunset 2y agoTransient allocations that do not outlive Gen0 collections are fine. Hell, they are mostly a problem in games that want to reach very high frequency main loop, like Osu! which runs at 1000hz. There are also multiple sets of libraries that target different performance requirements - there are numerous libraries made specifically for gamedev that are allocation-aware. The performance culture in general has significantly improved within recent years. But you wouldn't know that as you don't actively use C#. Please put your FUD elsewhere.
- Ygg2 2y ago> Transient allocations that do not outlive Gen0 collections are fine. Depends on the game. What if you have huge numbers of entities (100k), pulling huge numbers of fields from yaml (hundreds if not thousands) that live almost as long as the game (unless you use hot reload, or run admin commands)? This is problem SS14 (multiple simulation game with ~100-200 players) had with YamlDotNet. To quote devs: it's slow to parse and allocates out of the ass.
- neonsunset 2y agoI think I found the issue you are referring to: https://github.com/space-wizards/RobustToolbox/issues/891 https://github.com/space-wizards/RobustToolbox/issues/891 (2019) and PRs that address it https://github.com/space-wizards/RobustToolbox/pull/1606 https://github.com/space-wizards/RobustToolbox/pull/1606 (2021), https://github.com/space-wizards/space-station-14/pull/3491 https://github.com/space-wizards/space-station-14/pull/3491 (2021) What I don't understand is what makes you think it's an issue with .NET or its ecosystem: if you continuously re-parse large amount of entities defined in YAML, then any remotely naive approach is going to be expensive regardless of the underlying stack. Rust, C++ or C#, and respective serialization libraries only can do as much as define the threshold beyond which the scaling becomes impossible, hell, there's a good change that .NET's SRV GC could have been mitigating otherwise even worse failure mode caused by high allocation traffic, and if the data was shared, you'd hate to see the flamegraphs of entities shared through Arc or shared_ptr. SS14 seems to have quite complex domain problem to solve, so a requirement for an entirely custom extensive (and impressive) implementation might seem unfortunate but not uncharacteristic.
- Ygg2 2y ago> What I don't understand is what makes you think it's an issue with .NET or its ecosystem. AFAIK the issue remains unsolved to this day I've seen them complain about YamlDotNet as early as a couple of months ago. But shouldn't there be a zero-copy solution? Dotnet is way older than Rust, has the necessary tools but no libs. Hell Java oftentimes has better maintained libs. I recall looking for Roaring Bitmaps implementation and the Java one was both a port, rather than wrapper, and much better maintained. > SS14 seems to have quite complex domain problem to solve > Please put your FUD elsewhere Sure I agree on some level that domain is complex, but in context of your previous messages it's not FUD. If you intend to work on a game that pushes boundaries in complexity and you pick C#, you're going to have a bad time. Like sure you can write Cookie clicker in Python, but that doesn't mean you can write Star Citizen 3 in it. Problem is can you tell at start of project how complex will it be?
- Const-me 2y ago> most libraries use the hell out of it Most libraries used in a typical LoB or web apps — yeah, probably. However, in performance-critical C# LINQ ain’t even applicable because Span<T> and ReadOnlySpan<T> collections don’t implement the IEnumerable<T> interface required by the LINQ functions. Here’s couple examples of relatively complicated logic which uses loops instead of LINQ: https://github.com/Const-me/Vrmac/blob/master/VrmacVideo/Audio/ALSA/AlsaPlayer.cs#L121-L143 https://github.com/Const-me/Vrmac/blob/master/VrmacVideo/Aud... https://github.com/Const-me/Vrmac/blob/master/VrmacVideo/Containers/MP4/Readers/SampleReader.seek.cs#L34-L52 https://github.com/Const-me/Vrmac/blob/master/VrmacVideo/Con...