6 ms·
I came into the comments to say basically what you said here. Trying to avoid GC? Preallocate! For context, I'm a game developer working in Unity. We do basica
by Kapura 9y ago
I came into the comments to say basically what you said here. Trying to avoid GC? Preallocate!
For context, I'm a game developer working in Unity. We do basically all of our dev in C#, which is a language I love. But because it's garbage collected, and you can see performance hits when the GC runs. In VR dev especially (targeting 90 FPS) this is unacceptable.
So we profile, look to see where we're allocating anything onto the heap and figure out a way to cache it or re-implement it in a way that makes no garbage. We recently shipped a mobile VR experience and one of the best parts was being able to profile my gameplay code and seeing the '0B's next to its allocations every frame.
I understand that this may not work for everyone, and I fully believe that CloudFlare's got some talented engineers on the team, but there are ways to think about and structure programs in a C-like fashion so that you're more cognizant of the memory you are allocating and using from the heap.
- corndoge 9y agoPlease stop prefacing comments with phrases to the effect of "I came here to say this", it is already obnoxious on Reddit and is getting annoyingly frequent on HN as well. No added meaning. I care what you have to say; that you came here to say it is irrelevant. https://news.ycombinator.com/item?id=15683745 https://news.ycombinator.com/item?id=15683745 https://news.ycombinator.com/item?id=15590466 https://news.ycombinator.com/item?id=15590466 https://news.ycombinator.com/item?id=13614442 https://news.ycombinator.com/item?id=13614442 https://news.ycombinator.com/item?id=14306868 https://news.ycombinator.com/item?id=14306868 https://news.ycombinator.com/item?id=14327156 https://news.ycombinator.com/item?id=14327156 https://news.ycombinator.com/item?id=14532140 https://news.ycombinator.com/item?id=14532140 https://news.ycombinator.com/item?id=14531421 https://news.ycombinator.com/item?id=14531421
- always_good 9y agoYour criticism only applies if they had said nothing beyond their first sentence. Sure, their first sentence is irrelevant, but it's forgivable since they elaborate beyond it.
- corndoge 9y agoIt annoys me personally therefore nobody should do it.
- staticassertion 9y agoIt's a statement of agreement, followed by an elaboration on their point. Seems completely fine.
- fasquoika 9y agoIs it just me, or is this kind of gatekeeping becoming increasingly common on HN? I'm really not a fan
- reificator 9y agoDon't go gatekeeping the gatekeepers, it creates a hostile environment for the people creating a hostile environment.
- fasquoika 9y ago> Don't go gatekeeping the gatekeepers I realize you're joking, but I didn't think I was. It's not like I said "HN is no place for this type of comment". I just stated my opinion
- merb 9y agocan you even do that? In Java you can't allocate any List like data strucutre (LinkedList, ArrayList, arrays (Maps of course)) on the heap. Escape analysis might do it, but there is no way to force it. per my knowledge this is not even possible in C#, I mean you can drop to c way easier there or use (stackalloc) (same as Unsafe usages in Java) But I doubt that is not a good idea?
- DougBTX 9y agoA key idea is reducing churn, not simply avoiding allocation at all. For example, if the code which renders a frame always needs a four byte array each time it runs, it could reuse the same array each time, rather than allocating then garbage collecting each time.
- Kapura 9y agoSo, I'm not sure what the situation is with Java, but I suspect there might be some confusion in what you're reading. In C#, anything instantiated as part of a class goes onto the heap. Value types that are declared and used only within the function are allocated onto the stack. For example: public class Example { public int a; // Allocated onto the heap when Example is instanced public int b; // Allocated onto the heap when Example is instanced public int c; // Allocated onto the heap when Example is instanced public void CycleValues() { int temp = a; // Allocated onto the stack when function is called a = b; // a, b, and c are already allocated b = c; c = temp; // temp goes away when the function finishes executing } public int SumPositiveValues() { List<int> positiveList = new List(); // Not a value type: allocates onto the heap if (a > 0) valueList.Add(a); if (b > 0) valueList.Add(b); if (c > 0) valueList.Add(c); int sum = 0; // Allocated onto the stack foreach (int i in valueList) { sum += i; } return sum; // sum goes away when the function finishes executing // positiveList was allocated onto the heap, so it persists (although inaccessible) until garbage collection } } In the example above, space on the heap is allocated when you create a new Example(). Calling CycleValues() doesn't allocate anything new onto the heap, so it isn't creating any garbage. Calling SumPositiveValues() creates a new List(), which, not being a value type, is allocated onto the heap. When the function finishes, that memory isn't automatically freed; it creates garbage. Optimising for heap performance relies a lot on removing New calls to classes when it is possible and makes sense to do so.
- bulldoa 9y agothat is interesting, I wonder if its easier to just write idiomatic code in language that does not have gc like rust or c++
- Kapura 9y agoIt is not easier to write code in C++ (but it can be optimised further). I cannot speak to using rust in production.
- bulldoa 9y agothats fair, can you point to some example of non idiomatic c# code that you spoke about? I would love to read the code just for learning purpose.
- Kapura 9y agoMost of what I'm doing isn't writing non-idiomatic code, but following different idioms. Avoid instantiating classes (including Dictionaries and Lists) with new every frame, cache data you know you'll need to use again, avoid boxing/unboxing (casting to and from the 'object' type). I can't share any of my own code, but the sort of things that I'm doing can be exemplified by these two functions from Unity's physics API: [1][2]. The first returns a newly allocated array of the data, while the second takes, as a parameter, the array to populate and returns only the number of elements that it populated. If I know I'm going to be doing a big raycast each frame, I can instantiate the output array to a reasonable size in my class declaration not have to pay the price of the garbage created by allocating a new array every frame. [1] https://docs.unity3d.com/ScriptReference/Physics.RaycastAll.html https://docs.unity3d.com/ScriptReference/Physics.RaycastAll.... [2] https://docs.unity3d.com/ScriptReference/Physics.RaycastNonAlloc.html https://docs.unity3d.com/ScriptReference/Physics.RaycastNonA...
- IshKebab 9y agoYeah when I was doing Android development they have a lint that tells you not to allocate in `onDraw()`. I always thought.. what's the point of a garbage collected language if you then have to carefully avoid allocation?
- shabbyrobe 9y agoSo that you can mostly avoid having to carefully avoid allocation!
- renox 9y agoUh? You should also avoid memory (de)allocation in 'realtime' part of your code even in languages without GCs!