digitalmars.D - Do you use D's GC?
- Kirill (8/8) Aug 01 2021 It's interesting to hear do you use D's GC? Or do you use your
- JN (14/22) Aug 01 2021 I think both approaches are viable. I am making a small 3D game
- Dukc (24/32) Aug 01 2021 Often. I could avoid it but it's rarely worth it. Well, I do try
- IGotD- (6/14) Aug 01 2021 There is one question I have, let's say you have a big game that
- Mike Parker (9/14) Aug 01 2021 If it needs to. Not every allocation will trigger a collection.
- Adam D Ruppe (12/13) Aug 01 2021 the GC will only scan blocks that might have pointers in them. so
- Mike Parker (44/52) Aug 01 2021 In short, treat GC allocated memory *the same way* you would
- =?UTF-8?B?0JLQuNGC0LDQu9C40Lkg0KTQsNC0?= =?UTF-8?B?0LXQtdCy?= (11/15) Aug 01 2021 It doesn't matter to me.
- Dylan Graham (25/33) Aug 01 2021 It entirely depends on the scope of the problem. For a script or
- zjh (3/5) Aug 01 2021 If `D` can provide more infrastructure for `non-GC`, I believe
- max haughton (17/25) Aug 01 2021 I use the GC. The GC is an extremely powerful tool for
- evilrat (15/30) Aug 01 2021 Just to add, from my rough tests it shows that you can have
- russhy (13/13) Aug 01 2021 I only use GC for process that doesn't need to be realtime
- russhy (12/16) Aug 01 2021 16ms per frame at 60FPS, anything above will introduce frame
- russhy (16/16) Aug 01 2021 Generally GC is not an issue, until it becomes an issue
- IGotD- (17/22) Aug 02 2021 I'm kind of skeptical towards tracing GC for games. Think of
- evilrat (3/27) Aug 02 2021 Of course, that's why I mentioned that, even if GC performance is
- Paulo Pnito (6/30) Aug 02 2021 It is more than enough for Flash like games, honestly plenty of
- IGotD- (7/13) Aug 02 2021 Depends on what you are aiming for, for smaller games GC is
- H. S. Teoh (23/27) Aug 02 2021 [...]
- Guillaume Piolat (15/23) Aug 02 2021 For Vibrant which is a very simple game
- Guillaume Piolat (6/8) Aug 02 2021 GC performance has been much improved since.
- Joakim =?UTF-8?B?QnLDpG5uc3Ryw7Zt?= (6/16) Aug 02 2021 The fork based GC is merged
- evilrat (3/7) Aug 02 2021 In gamedev context probably not, unless there is already some
- rikki cattermole (3/5) Aug 02 2021 There is snapshoting which is essentially a fork without any threads
- JN (6/14) Aug 02 2021 Here's a counterpoint article about D's GC being a nuisance in
- workman (8/16) Aug 02 2021 The D language claim support NOGC Programming, but there is no
- Mike Parker (8/11) Aug 02 2021 That's just not true. The language does not *force* you to use
- russhy (8/27) Aug 03 2021 WHY DO YOU LIE?!
- Gregor =?UTF-8?B?TcO8Y2ts?= (11/19) Aug 03 2021 The D garbage collector seems reasonable for applications with
- Steven Schveighoffer (12/36) Aug 03 2021 Is that repro case doing what you think it is doing? It appears to keep
- =?UTF-8?Q?Ali_=c3=87ehreli?= (3/5) Aug 03 2021 You didn't reply in the bug thread. ;)
- Gregor =?UTF-8?B?TcO8Y2ts?= (14/39) Aug 14 2021 I apologize for not replying earlier. I was very busy with real
- Steven Schveighoffer (3/3) Aug 14 2021 Don't feel bad, we've ALL done something like this!
- H. S. Teoh (37/46) Aug 03 2021 [...]
- =?UTF-8?Q?Ali_=c3=87ehreli?= (28/33) Aug 03 2021 That's engineering! :)
- Steven Schveighoffer (22/52) Aug 03 2021 Let's rewrite this into appending to see why this doesn't work:
- jfondren (6/14) Aug 03 2021 All of the buffer-stomping "must reallocate" cases are preserved
- Steven Schveighoffer (4/20) Aug 03 2021 There is not a reallocation on shrinking of length. Or am I
- jfondren (18/39) Aug 03 2021 I think you're understanding it but not believing it. Again:
- jfondren (4/19) Aug 03 2021 ah. No, I get it: this was probably shrinking and then regrowing
- Steven Schveighoffer (3/25) Aug 03 2021 Yep, correct! Sorry I didn't see this before I did the other reply.
- Steven Schveighoffer (34/75) Aug 03 2021 The allocation doesn't happen on the shrinking, it happens on the regrow...
- jfondren (8/10) Aug 03 2021 Aye, I had some kind of sleep deprivation mental block on this
- =?UTF-8?Q?Ali_=c3=87ehreli?= (4/7) Aug 03 2021 Makes sense. Yes, I use assumeSafeAppend mostly on function-local-static...
- John Colvin (10/18) Aug 03 2021 I think GC fear is massively overblown, but I would be quite
- Walter Bright (5/5) Aug 03 2021 There's some good replies here.
- Walter Bright (3/3) Aug 03 2021 BTW, regardless of what language you use, or use GC or not, there's no w...
- Brian Tiffin (7/10) Aug 04 2021 Hear, hear.
- Guillaume Piolat (19/21) Aug 04 2021 On bugs vs input errors:
- H. S. Teoh (16/29) Aug 04 2021 Here the ones I've added to my own quotes file:
- IGotD- (3/5) Aug 05 2021 Ok, let's not get too OT here. Subject is still about the GC and
It's interesting to hear do you use D's GC? Or do you use your own custom memory management structure? How performant is GC? The reason I'm asking is I'm planning to dive into 3D game dev with D as a hobby in an attempt to create a game I dreamed of since I was a kid. I'd like to know if GC is worth using at all, or should I go with 100% manual memory management. Any opinion is appreciated. Thanks in advance.
Aug 01 2021
On Sunday, 1 August 2021 at 08:54:05 UTC, Kirill wrote:It's interesting to hear do you use D's GC? Or do you use your own custom memory management structure? How performant is GC? The reason I'm asking is I'm planning to dive into 3D game dev with D as a hobby in an attempt to create a game I dreamed of since I was a kid. I'd like to know if GC is worth using at all, or should I go with 100% manual memory management. Any opinion is appreciated. Thanks in advance.I think both approaches are viable. I am making a small 3D game engine in D and I never had many issues with GC performance. In a game, you shouldn't be allocating a lot of stuff on the heap anyway. Most of big objects like buffers, textures should be initialized once during startup anyway. Things like matrices and vectors which you'll be using often are value types so they won't be going through GC anyway. Just avoid things like particle emitter having 10000 particles which are GC-allocated whenever they spawn. Just make an 10000-sized array of particle structs and do the swap-with-last then reduce count by 1 trick. But if you want to go manual memory management, D will allow you to do it.
Aug 01 2021
On Sunday, 1 August 2021 at 08:54:05 UTC, Kirill wrote:It's interesting to hear do you use D's GC? Or do you use your own custom memory management structure?Often. I could avoid it but it's rarely worth it. Well, I do try to avoid heap usage in general when I can easily do so, but I don't often use RAII, let alone `malloc`/`free`. And even when I have done so, it's not so much for performance, it's for portability (through with Dylan Graham's LWDR I'm not sure I have to avoid GC for portability anymore).How performant is GC? The reason I'm asking is I'm planning to dive into 3D game dev with D as a hobby in an attempt to create a game I dreamed of since I was a kid. I'd like to know if GC is worth using at all, or should I go with 100% manual memory management. Any opinion is appreciated. Thanks in advance.Most people nowadays use an already made game 3D engine - You may well have heard of Unity and Unreal engine. While they do not let a game to be as performant as with a purpose-built engine, the fact that reasonably light 3D games have been made with them for ages speaks a lot. Godot game engine is a great choice IMO, especially with D. It's fully open source, has a good D binding, and it has a better object model than Unity does. Binding here: https://github.com/godot-d/godot-d. And yes, D GC is available with Godot. It's unlikely you'll have problems with it, as the game engine takes care of the heavy crunching - you generally write only the scripts. You may also consider Dagon (https://code.dlang.org/packages/dagon). As a much smaller project it's going to be harder to use it than Godot, but if you want a pure D game engine you might consider it. It's still definitely an easier route than writing your own engine.
Aug 01 2021
On Sunday, 1 August 2021 at 08:54:05 UTC, Kirill wrote:It's interesting to hear do you use D's GC? Or do you use your own custom memory management structure? How performant is GC? The reason I'm asking is I'm planning to dive into 3D game dev with D as a hobby in an attempt to create a game I dreamed of since I was a kid. I'd like to know if GC is worth using at all, or should I go with 100% manual memory management. Any opinion is appreciated. Thanks in advance.There is one question I have, let's say you have a big game that uses several gigabytes of RAM. The objects are just allocated once with the GC but once you touch the GC like doing a new (which can be done by a library function), will the GC then start to scan all those gigabytes of data?
Aug 01 2021
On Sunday, 1 August 2021 at 10:36:52 UTC, IGotD- wrote:There is one question I have, let's say you have a big game that uses several gigabytes of RAM. The objects are just allocated once with the GC but once you touch the GC like doing a new (which can be done by a library function), will the GC then start to scan all those gigabytes of data?If it needs to. Not every allocation will trigger a collection. You can play around with something like appending items to an array in a loop and passing `--DRT-gcopt=profile:1` to the program when you run it. This will spit out a report telling you how many collections were run, along with some timing statistics. There's an example here: https://dlang.org/blog/2017/06/16/life-in-the-fast-lane/ It's one of the tools available to make the best use of the GC.
Aug 01 2021
On Sunday, 1 August 2021 at 10:36:52 UTC, IGotD- wrote:will the GC then start to scan all those gigabytes of data?the GC will only scan blocks that might have pointers in them. so let's say you have objects like class Thing { ubyte[] imageData; this() { imageData = new ubyte[](10_000_000); } } A GC scan of that is actually only like 64 bytes since it knows it doesn't need to look at the image data, only the class and the stack which can actually hold pointers.
Aug 01 2021
On Sunday, 1 August 2021 at 08:54:05 UTC, Kirill wrote:It's interesting to hear do you use D's GC? Or do you use your own custom memory management structure? How performant is GC? The reason I'm asking is I'm planning to dive into 3D game dev with D as a hobby in an attempt to create a game I dreamed of since I was a kid. I'd like to know if GC is worth using at all, or should I go with 100% manual memory management. Any opinion is appreciated. Thanks in advance.In short, treat GC allocated memory *the same way* you would treat memory allocated and deallocated with malloc and free. For example, in C++ would someone who knows what they're doing allocate memory for large numbers of individual entities, like particles, in inner loops? No. They would preallocate. Do the same in D. The GC isn't going to run a collection behind your back. It's only going to run if you do something that triggers an allocation. ` nogc` on the functions that are called in your inner loops will make sure you don't trigger a collection at the wrong moment. You have other tools if you need them (emphasis on *if you need them*), like pausing the GC, or invoking collection runs manually at specific points. This is the sort of thing you dig into *if* you find the GC is problematic. I'm going to go out on a limb and say the odds are low that the GC will be a problem for you, and lower still if you are smart about using it. There is a class of games and other applications for which GC is certainly going to be problematic no matter how smart the developer is about using it, but I doubt anyone working on a hobby 3D is going to be anywhere near there. Even going full-on GC and being dumb about using it is going to be just fine for many kinds of games. It's all about the scope of the project and your allocations patterns. I mean, you can be less smart about it for games like Pac-Man, Galaga, etc, but you'll need to think about it more for something like Skyrim. Plan your allocation patterns in a way that makes sense for the game you are making. To do that, just follow some simple rules. If it doesn't need to be a class, make it a struct. If it can be allocated on the stack, then don't use `new`. If there's something that needs heap allocation but you can see a way to easily manage it deterministically, then allocate with malloc instead of the GC. Don't do any allocations, including malloc, in your inner loop. Preallocate arrays for things like particles, or use free lists when you need large numbers of GC-managed objects (not good advice for Java anymore, but almost certainly useful in D). And so on. In short, the less pressure you put on the GC, the less impactful its collections. The less often you allocate from the GC, the fewer collections it will run. So use it for the things you need it for, but be strategic about when you call the allocations. This may help you get started: https://dlang.org/blog/the-gc-series/
Aug 01 2021
On Sunday, 1 August 2021 at 08:54:05 UTC, Kirill wrote:It's interesting to hear do you use D's GC? Or do you use your own custom memory management structure?do you use D's GC?Yes.How performant is GC?It doesn't matter to me. I don't see the difference. While teething an idea, I don't look at performance. Then when the idea is finalized, I improve performance. And here I sometimes prefer nogc nothrow functions. I love D for fast compilation and for the gerbage collector. Without the GC, it would be tedious to programing with keep pointers in mind. For GUI library I prefer nogc + BetterC.
Aug 01 2021
On Sunday, 1 August 2021 at 08:54:05 UTC, Kirill wrote:It's interesting to hear do you use D's GC? Or do you use your own custom memory management structure?It entirely depends on the scope of the problem. For a script or tool, absolutely yes. Game development? Yes. Embedded? Maybe. I implemented a voxel game (similar to [Blockscape around 2012](https://images.app.goo.gl/7yJAfnUu9wa7A74fA)) and the GC was largely not a problem. The underlying array for a chunk of voxels (chunks come in and out of scope very frequently as the player moves), was `malloc`ed to reduce pressure on the GC (and to enable on-the-fly RLE compression). Otherwise, everything else was GC dependent and I did not have performance problems.How performant is GC?Some people complain about it, but I haven't had an issue. I think my usage of it was before they introduced the parallel-sweep GC. I don't recall GC pauses any longer than 4-5ms, and there was no stutter. D's GC is significantly easier to manage than something like fighting .NET's GC. It always seemed to run, no matter how much I tried to stop allocations (while you can can *temporarily* stop the GC, it wasn't a solution). D's GC only runs *when you allocate with* `new`.The reason I'm asking is I'm planning to dive into 3D game dev with D as a hobby in an attempt to create a game I dreamed of since I was a kid. I'd like to know if GC is worth using at all, or should I go with 100% manual memory management. Any opinion is appreciated. Thanks in advance.We might be able to give a more informed answer with some of your planned technical details. As is, I'd advise you use the GC. D is in a very good position to become a gamedev language. The GC is very helpful, but when you really need, it's super easy to opt out. D is about giving *you* power.
Aug 01 2021
On Sunday, 1 August 2021 at 08:54:05 UTC, Kirill wrote:It's interesting to hear do you use D's GC? Or do you use your own custom memory management structure?If `D` can provide more infrastructure for `non-GC`, I believe `D` will develop `better and faster`.
Aug 01 2021
On Sunday, 1 August 2021 at 08:54:05 UTC, Kirill wrote:It's interesting to hear do you use D's GC? Or do you use your own custom memory management structure? How performant is GC? The reason I'm asking is I'm planning to dive into 3D game dev with D as a hobby in an attempt to create a game I dreamed of since I was a kid. I'd like to know if GC is worth using at all, or should I go with 100% manual memory management. Any opinion is appreciated. Thanks in advance.I use the GC. The GC is an extremely powerful tool for productivity. For a game your issue will be non-deterministic latency i.e. GC pauses. For this, I would recommend having a strategy for avoiding the GC - other people will write here and have written extensively before on how to do this, so I won't repeat all of those points and points to be. It may be worth a warning here: If you are going into a new field, you probably want to learn that field *then* try and do that field well rather than trying to learn how to make a good game engine and any game engine at the same time. A small tip for any memory allocation: Before being clever and thinking about the internals of your memory allocator (which is important, to be clear), try to allocate less memory first - sounds simple but memory you never allocate has a cost of exactly zero. Enjoy.
Aug 01 2021
On Sunday, 1 August 2021 at 14:02:46 UTC, max haughton wrote:On Sunday, 1 August 2021 at 08:54:05 UTC, Kirill wrote:Just to add, from my rough tests it shows that you can have unnoticeable collections for up to 300MB heap size depending on CPU/RAM specs, after that there is clearly perceivable stutter that drags FPS down esp. with loop allocations. What this means in practice - it should be possible to go full OOP crap for game simulation using lightweight classes without any hiccups even with GC enabled, but all asset data should be handled differently and taken out of GC scannable heap to avoid long pauses. But in reality one would probably choose another allocation strategy that will probably accounts for disabling GC until certain point later in time when collection pauses won't matter and do manual collect there (on pause menu, respawn, level change, etc...)It's interesting to hear do you use D's GC? Or do you use your own custom memory management structure? How performant is GC? The reason I'm asking is I'm planning to dive into 3D game dev with D as a hobby in an attempt to create a game I dreamed of since I was a kid. I'd like to know if GC is worth using at all, or should I go with 100% manual memory management. Any opinion is appreciated. Thanks in advance.I use the GC. The GC is an extremely powerful tool for productivity. For a game your issue will be non-deterministic latency i.e. GC pauses.
Aug 01 2021
I only use GC for process that doesn't need to be realtime For anything else (including my game engine) i don't use GC at all, instead i use allocators (malloc/free most of the time) If you plan to make a game, try to avoid the GC as much as possible, it's not incremental, so whever it needs to do a collection, it'll pause all the threads, depending on the structure of the heap memory it can take multiple frames But that's also a valid concern if you misuse malloc/free, so it's not an issue with the GC But with games, you want to make sure you control the memory allocation strategy, and GC doesn't help with that You can always GC.disable() and call GC.collect() during loading screens, but again, control your allocation strategy!
Aug 01 2021
Just to add, from my rough tests it shows that you can have unnoticeable collections for up to 300MB heap size depending on CPU/RAM specs, after that there is clearly perceivable stutter that drags FPS down esp. with loop allocations.16ms per frame at 60FPS, anything above will introduce frame stutters Even if it's one every minutes, user will notice, games need predictable performance, you don't want to miss a combo because your GC decided to collect this frame for up to 3 frames GC is not an issue if you manually manage it GC.disable() then GC.collect() during loading screen But if your game never has loading screens, or if they are spaced out for way too long, then it's preferable to manage everything without it at all Pool entities, use arena allocators, GC only introduce issues that you have to workaround (threading for ex)
Aug 01 2021
Generally GC is not an issue, until it becomes an issue Use it with caution or manage things by yourself The most important thing to do is to know exactly what you need, and when Avoid heap allocation during hot loops at all cost, no matter if it's GC or malloc, they both slow Remember frame budget is only 16ms per frame for 60FPS, stutters are not an option if you want a smooth user experience And if people use 120HZ monitors, or 144HZ, then the frame budget becomes even lower GC is faster at allocating memory, but collections induces pauses As other said D is great at providing tools to avoid GC, so use that at your benefit And as i said in other posts above, control your memory allocation strategy from the start, and things will be easier to manage
Aug 01 2021
On Sunday, 1 August 2021 at 14:43:47 UTC, evilrat wrote:What this means in practice - it should be possible to go full OOP crap for game simulation using lightweight classes without any hiccups even with GC enabled, but all asset data should be handled differently and taken out of GC scannable heap to avoid long pauses.I'm kind of skeptical towards tracing GC for games. Think of thousands of objects, usually of the same type. These objects are often full of references to other objects and they often points to each other as there might be some relation. This is a lot of memory, that is also scattered around in the memory. Scanning these will take time. For this type of objects I would go for a pool that is outside GC. Also how the reference each other could be solved by reference counting in order to minimize memory leaks. Other suggestions is that object references each other using a hash table. This rolling identifier/hash lookup is often used in operating systems (file handles for example) as pointers cannot be used in order to distinguish a resource. Often memory management in games kind of falls outside the convenience of GC as the demand is so special, not only because of performance but also when it comes to data structures.
Aug 02 2021
On Monday, 2 August 2021 at 15:43:24 UTC, IGotD- wrote:On Sunday, 1 August 2021 at 14:43:47 UTC, evilrat wrote:Of course, that's why I mentioned that, even if GC performance is OK it is still better to design with what you've said in mind.What this means in practice - it should be possible to go full OOP crap for game simulation using lightweight classes without any hiccups even with GC enabled, but all asset data should be handled differently and taken out of GC scannable heap to avoid long pauses.I'm kind of skeptical towards tracing GC for games. Think of thousands of objects, usually of the same type. These objects are often full of references to other objects and they often points to each other as there might be some relation. This is a lot of memory, that is also scattered around in the memory. Scanning these will take time. For this type of objects I would go for a pool that is outside GC. Also how the reference each other could be solved by reference counting in order to minimize memory leaks. Other suggestions is that object references each other using a hash table. This rolling identifier/hash lookup is often used in operating systems (file handles for example) as pointers cannot be used in order to distinguish a resource. Often memory management in games kind of falls outside the convenience of GC as the demand is so special, not only because of performance but also when it comes to data structures.
Aug 02 2021
On Monday, 2 August 2021 at 15:43:24 UTC, IGotD- wrote:On Sunday, 1 August 2021 at 14:43:47 UTC, evilrat wrote:It is more than enough for Flash like games, honestly plenty of indies will never make it beyond that, so why bother for the ultimate weapon if they they on the first day on the battlefield? Don't dismiss languages on how well they can achieve Fortnight, when not even able to beat Stardew Valley or Bastion sales.What this means in practice - it should be possible to go full OOP crap for game simulation using lightweight classes without any hiccups even with GC enabled, but all asset data should be handled differently and taken out of GC scannable heap to avoid long pauses.I'm kind of skeptical towards tracing GC for games. Think of thousands of objects, usually of the same type. These objects are often full of references to other objects and they often points to each other as there might be some relation. This is a lot of memory, that is also scattered around in the memory. Scanning these will take time. For this type of objects I would go for a pool that is outside GC. Also how the reference each other could be solved by reference counting in order to minimize memory leaks. Other suggestions is that object references each other using a hash table. This rolling identifier/hash lookup is often used in operating systems (file handles for example) as pointers cannot be used in order to distinguish a resource. Often memory management in games kind of falls outside the convenience of GC as the demand is so special, not only because of performance but also when it comes to data structures.
Aug 02 2021
On Monday, 2 August 2021 at 18:10:03 UTC, Paulo Pnito wrote:It is more than enough for Flash like games, honestly plenty of indies will never make it beyond that, so why bother for the ultimate weapon if they they on the first day on the battlefield? Don't dismiss languages on how well they can achieve Fortnight, when not even able to beat Stardew Valley or Bastion sales.Depends on what you are aiming for, for smaller games GC is probably enough. Let's not forget this interesting D conf seminar. https://www.youtube.com/watch?v=7YjLW7anNfc Where the solution was to disable the GC collecting. For people who haven't seen it this could be interesting as it is the only what I know of example where D is used in a high budget game.
Aug 02 2021
On Mon, Aug 02, 2021 at 03:43:24PM +0000, IGotD- via Digitalmars-d wrote: [...]I'm kind of skeptical towards tracing GC for games. Think of thousands of objects, usually of the same type. These objects are often full of references to other objects and they often points to each other as there might be some relation.[...] I don't have that much experience with game programming, but have experimented with things like ECS, which kinda solves this problem at least partially, by keeping everything in arrays. References between objects are represented by entity IDs rather than straight pointers, and arrays can be allocated in large blocks at a time instead of one allocation per object, so there's much less GC pressure. ECS is also more conducive to representing in-game objects than OO-style objects IMO, especially in games where objects can undergo extensive changes that aren't easily mapped to the OO paradigm. Of course, an ECS implementation could also just manage its own memory instead of relying on GC. In any case, high performance + frequent allocation of small objects == trouble (even if you manually manage memory with malloc/free). If you find yourself in that situation, you inevitably have to address a lot of the same kind of issues that ECS addresses anyway. So this problem isn't necessarily GC-specific (though it tends to become more evident in GC environments), but a more general problem of memory management and object representation in games. T -- MASM = Mana Ada Sistem, Man!
Aug 02 2021
On Sunday, 1 August 2021 at 08:54:05 UTC, Kirill wrote:It's interesting to hear do you use D's GC? Or do you use your own custom memory management structure? How performant is GC? The reason I'm asking is I'm planning to dive into 3D game dev with D as a hobby in an attempt to create a game I dreamed of since I was a kid. I'd like to know if GC is worth using at all, or should I go with 100% manual memory management. Any opinion is appreciated. Thanks in advance.For Vibrant which is a very simple game (https://store.steampowered.com/app/712430/Vibrant/) I did get some GC pauses so the mitigation I used in the end was: - memory pools - deregistering audio thread, using core.atomic for game => audio communication - minimize GC heap size. In particular, a GC void[] will be scanned but an ubyte[] won't IIRC. All in all any time spent with GC optimization is well compensated by all the time the GC (and D) gives you in tooling, and non-realtime stuff. Don't go with 100% manual memory management if you can avoid it! But you can go deterministic destruction with https://dlang.org/library/core/memory/gc.in_finalizer.html
Aug 02 2021
On Monday, 2 August 2021 at 08:25:28 UTC, Guillaume Piolat wrote:On Sunday, 1 August 2021 at 08:54:05 UTC, Kirill wrote: I did get some GC pausesGC performance has been much improved since. It would be great to have new guidelines about "how much GC heap will scan in <1ms" because at one point the research by Infognition said it was only 100kb. http://www.infognition.com/blog/2014/the_real_problem_with_gc_in_d.html
Aug 02 2021
On Monday, 2 August 2021 at 08:27:51 UTC, Guillaume Piolat wrote:On Monday, 2 August 2021 at 08:25:28 UTC, Guillaume Piolat wrote:The fork based GC is merged https://github.com/dlang/druntime/pull/3514 :) It would be interesting to read an article about it. Maybe it improves the use case discussed in this thread? // JoakimOn Sunday, 1 August 2021 at 08:54:05 UTC, Kirill wrote: I did get some GC pausesGC performance has been much improved since. It would be great to have new guidelines about "how much GC heap will scan in <1ms" because at one point the research by Infognition said it was only 100kb. http://www.infognition.com/blog/2014/the_real_problem_with_gc_in_d.html
Aug 02 2021
On Monday, 2 August 2021 at 08:49:36 UTC, Joakim Brännström wrote:The fork based GC is merged https://github.com/dlang/druntime/pull/3514 :) It would be interesting to read an article about it. Maybe it improves the use case discussed in this thread?In gamedev context probably not, unless there is already some fork mechanism on Windows that i'm not aware of.
Aug 02 2021
On 02/08/2021 9:32 PM, evilrat wrote:unless there is already some fork mechanism on Windows that i'm not aware of.There is snapshoting which is essentially a fork without any threads that you can introspect from your host process.
Aug 02 2021
On Sunday, 1 August 2021 at 08:54:05 UTC, Kirill wrote:It's interesting to hear do you use D's GC? Or do you use your own custom memory management structure? How performant is GC? The reason I'm asking is I'm planning to dive into 3D game dev with D as a hobby in an attempt to create a game I dreamed of since I was a kid. I'd like to know if GC is worth using at all, or should I go with 100% manual memory management. Any opinion is appreciated. Thanks in advance.Here's a counterpoint article about D's GC being a nuisance in the context of game development: https://www.benjamin-thaut.de/archives/20 be aware though the article is from 2012, so there may have been many improvements to the GC since that time.
Aug 02 2021
On Sunday, 1 August 2021 at 08:54:05 UTC, Kirill wrote:It's interesting to hear do you use D's GC? Or do you use your own custom memory management structure? How performant is GC? The reason I'm asking is I'm planning to dive into 3D game dev with D as a hobby in an attempt to create a game I dreamed of since I was a kid. I'd like to know if GC is worth using at all, or should I go with 100% manual memory management. Any opinion is appreciated. Thanks in advance.The D language claim support NOGC Programming, but there is no ecosystem for this. It force people to use GC if they want use library. D GC is not good as any other popular language. You will find there is a lot library author abandoned they projects in last decade, people just leave after invest a lot time and resource.
Aug 02 2021
On Tuesday, 3 August 2021 at 05:36:12 UTC, workman wrote:The D language claim support NOGC Programming, but there is no ecosystem for this. It force people to use GC if they want use library.That's just not true. The language does not *force* you to use the GC. But it *is* a language that was designed with the GC in mind, so if you want to cut it out completely then you are going to have to do some things yourself that you otherwise wouldn't have to. It's all about tradeoffs. But that's entirely your choice, just as it is for library authors who can choose to use the GC or not. The language does it force it either way.
Aug 02 2021
On Tuesday, 3 August 2021 at 05:36:12 UTC, workman wrote:On Sunday, 1 August 2021 at 08:54:05 UTC, Kirill wrote:WHY DO YOU LIE?! there is a strong ecosystem for system libraries and nogc libraries in D and you can plug in what ever C libraries you want, so you already can consume the WHOLE C ecosystem, out of the box saying there is no ecosystem is plain and simple dishonest and a PURE LIEIt's interesting to hear do you use D's GC? Or do you use your own custom memory management structure? How performant is GC? The reason I'm asking is I'm planning to dive into 3D game dev with D as a hobby in an attempt to create a game I dreamed of since I was a kid. I'd like to know if GC is worth using at all, or should I go with 100% manual memory management. Any opinion is appreciated. Thanks in advance.The D language claim support NOGC Programming, but there is no ecosystem for this. It force people to use GC if they want use library. D GC is not good as any other popular language. You will find there is a lot library author abandoned they projects in last decade, people just leave after invest a lot time and resource.
Aug 03 2021
On Tuesday, 3 August 2021 at 12:26:14 UTC, russhy wrote:WHY DO YOU LIE?! there is a strong ecosystem for system libraries and nogc libraries in D and you can plug in what ever C libraries you want, so you already can consume the WHOLE C ecosystem, out of the box saying there is no ecosystem is plain and simple dishonest and a PURE LIEI am sorry if I use the wrong words that hurt you feeling, but that is just my opinion.
Aug 03 2021
On Tuesday, 3 August 2021 at 15:28:57 UTC, workman wrote:On Tuesday, 3 August 2021 at 12:26:14 UTC, russhy wrote:Don't make it personal, i talk about the lies you spread, it has nothing to do with feelingsWHY DO YOU LIE?! there is a strong ecosystem for system libraries and nogc libraries in D and you can plug in what ever C libraries you want, so you already can consume the WHOLE C ecosystem, out of the box saying there is no ecosystem is plain and simple dishonest and a PURE LIEI am sorry if I use the wrong words that hurt you feeling, but that is just my opinion.
Aug 03 2021
On Sunday, 1 August 2021 at 08:54:05 UTC, Kirill wrote:It's interesting to hear do you use D's GC? Or do you use your own custom memory management structure? How performant is GC? The reason I'm asking is I'm planning to dive into 3D game dev with D as a hobby in an attempt to create a game I dreamed of since I was a kid. I'd like to know if GC is worth using at all, or should I go with 100% manual memory management. Any opinion is appreciated. Thanks in advance.The D garbage collector seems reasonable for applications with small (object sized) allocations. But that changes when you allocate large blocks of memory: due to a bug internal to the tracking of allocated pages, performance gradually degrades over time. So if you have to allocate large(ish) buffers regularly, it'll show over time. I reported that bug here with a repro case, but it didn't get any attention yet: https://issues.dlang.org/show_bug.cgi?id=20434 I haven't managed to understand thag part of the GC enough to submit a patch myself :(.
Aug 03 2021
On 8/3/21 5:15 AM, Gregor Mückl wrote:On Sunday, 1 August 2021 at 08:54:05 UTC, Kirill wrote:Is that repro case doing what you think it is doing? It appears to keep adding more and more larger allocations to the mix. It seems you are calculating a `size` variable and never using it. I think possibly you meant to use `size * 1024 * 1024` instead of `i * 1024 * 1024`. In regards to the conservative nature of the GC, the larger the blocks get, the more chances they get "accidentally" pointed at by the stack (or some other culprit). 64-bit memory space should alleviate a lot of this, but I think there are still cases where it can pin data unintentionally. -SteveIt's interesting to hear do you use D's GC? Or do you use your own custom memory management structure? How performant is GC? The reason I'm asking is I'm planning to dive into 3D game dev with D as a hobby in an attempt to create a game I dreamed of since I was a kid. I'd like to know if GC is worth using at all, or should I go with 100% manual memory management. Any opinion is appreciated. Thanks in advance.The D garbage collector seems reasonable for applications with small (object sized) allocations. But that changes when you allocate large blocks of memory: due to a bug internal to the tracking of allocated pages, performance gradually degrades over time. So if you have to allocate large(ish) buffers regularly, it'll show over time. I reported that bug here with a repro case, but it didn't get any attention yet: https://issues.dlang.org/show_bug.cgi?id=20434 I haven't managed to understand thag part of the GC enough to submit a patch myself :(.
Aug 03 2021
On 8/3/21 7:34 AM, Steven Schveighoffer wrote:Is that repro case doing what you think it is doing? It appears to keep adding more and more larger allocations to the mix.You didn't reply in the bug thread. ;) Ali
Aug 03 2021
On Tuesday, 3 August 2021 at 14:34:19 UTC, Steven Schveighoffer wrote:On 8/3/21 5:15 AM, Gregor Mückl wrote:I apologize for not replying earlier. I was very busy with real life stuff since I posted this. Also, I feel REALLY embarrassed. You are right. I am sorry for wasting time with this. I was 100% certain that my code was right when I opened the bug report and I am sure that I checked it multiple times. But going back to the example program I have locally, it clearly contains this stupid bug. I fixed the allocation size as you said and now I can't reproduce the behavior I remember. I've checked several dmd builds between 2.088 and 2.096 again and it doesn't show. So the GC is just fine after all - and I've made an idiot of myself. Again.The D garbage collector seems reasonable for applications with small (object sized) allocations. But that changes when you allocate large blocks of memory: due to a bug internal to the tracking of allocated pages, performance gradually degrades over time. So if you have to allocate large(ish) buffers regularly, it'll show over time. I reported that bug here with a repro case, but it didn't get any attention yet: https://issues.dlang.org/show_bug.cgi?id=20434 I haven't managed to understand thag part of the GC enough to submit a patch myself :(.Is that repro case doing what you think it is doing? It appears to keep adding more and more larger allocations to the mix. It seems you are calculating a `size` variable and never using it. I think possibly you meant to use `size * 1024 * 1024` instead of `i * 1024 * 1024`. In regards to the conservative nature of the GC, the larger the blocks get, the more chances they get "accidentally" pointed at by the stack (or some other culprit). 64-bit memory space should alleviate a lot of this, but I think there are still cases where it can pin data unintentionally. -Steve
Aug 14 2021
Don't feel bad, we've ALL done something like this! Cheers! -Steve
Aug 14 2021
On Sun, Aug 01, 2021 at 08:54:05AM +0000, Kirill via Digitalmars-d wrote:It's interesting to hear do you use D's GC? Or do you use your own custom memory management structure? How performant is GC? The reason I'm asking is I'm planning to dive into 3D game dev with D as a hobby in an attempt to create a game I dreamed of since I was a kid. I'd like to know if GC is worth using at all, or should I go with 100% manual memory management.[...] My approach to D's GC is: (1) Use it by default until it starts showing up as a bottleneck in your profiler. (2) When it does show up as a bottleneck, the fix is often simple and yields good benefits. E.g., in one of my projects, after the GC showed up as a bottleneck, I quickly pinpointed the problem to a function in an inner loop that was allocating a new array every iteration. Fixing that to reuse a previously-allocated array (maybe about 5 lines' change) immediately gave me 20-30% performance boost. There were a couple of other similar small code changes to reduce GC pressure, and replace some small bits of GC code in inner loops where performance matters the most. (3) If performance is still not good enough, there are other ways of controlling the GC. In the aforementioned project, for example, after the array optimization I found that GC collections were taking place too often. So I added GC.stop to the start of my program, and scheduled my own calls to GC.collect at a lower frequency, and got about another 20-30% performance improvement. Overall, I think I got about 50-60% performance improvement just by several small code changes to an essentially GC-centric codebase. By writing GC code I saved countless days of writing code for manually managing memory (and weeks of pulling out my hair to debug said code). Only in actual hotspots where the GC becomes a hindrance, I spent some focused effort to either optimize GC usage, or replace small parts of the code (in inner loops and other bottlenecks) with manually-managed memory. Much faster development time than if I had written *everything* to be nogc. Most of that effort would have been wasted on code that doesn't even lie in the bottleneck and therefore doesn't actually matter to performance. tl;dr: don't fear the GC, just use it freely until your profiler has actually identified the GC as the bottleneck. Then strategically optimize those hotspots, optionally replace them with nogc code, etc., with much less effort than writing your entire application with nogc. T -- "Hi." "'Lo."
Aug 03 2021
On 8/3/21 9:31 AM, H. S. Teoh wrote:(1) Use it by default until it starts showing up as a bottleneck in your profiler. (2) When it does show up as a bottleneck, [...]That's engineering! :) However, dmd's -profile=gc switch seems to have a bug reported by multiple people where one may get a segmentation fault (or was it -profile?). Even though I've seen it as well, it is not clear whether it's my own code causing errors in a destructor.Overall, I think I got about 50-60% performance improvement just by several small code changes to an essentially GC-centric codebase.Same here. One surprising pessimization which I have not mentioned publicly before was with assigning to the .length property of a buffer. Was it supposed to allocate? I had the following function: void ensureHasRoom(ref ubyte[] buffer, size_t length) { buffer.length = length; } My idea was I would blindly assign and even if the length was reduced, the *capacity* would not change and memory would *not* be allocated by a later assignment. Unfortunately, that function was causing GC allocations at least with 2.084.1 perhaps in the presence of other slices to the same elements in my program. Changing it to the following more sensible approach reduced the allocations a lot: void ensureHasRoom(ref ubyte[] buffer, size_t length) { if (buffer.length < length) { buffer.length = length; } } I can't be sure now whether it was related to the presence of other slices. Possible... Anyway, that quick fix was a huge improvement. Ali
Aug 03 2021
On 8/3/21 1:53 PM, Ali Çehreli wrote:On 8/3/21 9:31 AM, H. S. Teoh wrote: > (1) Use it by default until it starts showing up as a bottleneck in your > profiler. > > (2) When it does show up as a bottleneck, [...] That's engineering! :) However, dmd's -profile=gc switch seems to have a bug reported by multiple people where one may get a segmentation fault (or was it -profile?). Even though I've seen it as well, it is not clear whether it's my own code causing errors in a destructor. > Overall, I think I got about 50-60% performance improvement just by > several small code changes to an essentially GC-centric codebase. Same here. One surprising pessimization which I have not mentioned publicly before was with assigning to the .length property of a buffer. Was it supposed to allocate? I had the following function: void ensureHasRoom(ref ubyte[] buffer, size_t length) { buffer.length = length; } My idea was I would blindly assign and even if the length was reduced, the *capacity* would not change and memory would *not* be allocated by a later assignment.Let's rewrite this into appending to see why this doesn't work: ```d buffer = new int[100]; // start with some data; auto buffer2 = buffer; // keep a reference to it (to give us a reason to keep the data) buffer = buffer[0 .. 50]; // "shrink" the length buffer ~= 10; // appending, will reallocate because otherwise we stomp on buffer2 ``` It's no different for length setting: ```d buffer = new int[100]; auto buffer2 = buffer; buffer.length = 50; buffer.length = 51; // must reallocate buffer[$-1] = 10; ``` In order for a length change to *not* reallocate, you have to call `assumeSafeAppend` on that adjusted buffer, to let the runtime know that we don't care about any existing data that might be referenced by others. -Steve
Aug 03 2021
On Tuesday, 3 August 2021 at 18:18:48 UTC, Steven Schveighoffer wrote:It's no different for length setting: ```d buffer = new int[100]; auto buffer2 = buffer; buffer.length = 50; buffer.length = 51; // must reallocate buffer[$-1] = 10; ```All of the buffer-stomping "must reallocate" cases are preserved in the rewrite that only assigns buffer.length when the new value is larger. The cases that were omitted, that were a performance drain, were same-length or less-length assignments.
Aug 03 2021
On 8/3/21 2:21 PM, jfondren wrote:On Tuesday, 3 August 2021 at 18:18:48 UTC, Steven Schveighoffer wrote:There is not a reallocation on shrinking of length. Or am I misunderstanding your statement? -SteveIt's no different for length setting: ```d buffer = new int[100]; auto buffer2 = buffer; buffer.length = 50; buffer.length = 51; // must reallocate buffer[$-1] = 10; ```All of the buffer-stomping "must reallocate" cases are preserved in the rewrite that only assigns buffer.length when the new value is larger. The cases that were omitted, that were a performance drain, were same-length or less-length assignments.
Aug 03 2021
On Tuesday, 3 August 2021 at 18:34:55 UTC, Steven Schveighoffer wrote:On 8/3/21 2:21 PM, jfondren wrote:I think you're understanding it but not believing it. Again: ```d void ensureHasRoom(ref ubyte[] buffer, size_t length) { buffer.length = length; // this is a serious bottleneck } void ensureHasRoom(ref ubyte[] buffer, size_t length) { if (buffer.length < length) { buffer.length = length; // this is fine actually } } ``` The story is that the situation was improved by excluding only those cases that should not have incurred any reallocations. Every single invocation of the bottlenecking `ensureHasRoom` that should have reallocated would still do so with the fixed `ensureHasRoom`. So something else was going on.On Tuesday, 3 August 2021 at 18:18:48 UTC, Steven Schveighoffer wrote:There is not a reallocation on shrinking of length. Or am I misunderstanding your statement?It's no different for length setting: ```d buffer = new int[100]; auto buffer2 = buffer; buffer.length = 50; buffer.length = 51; // must reallocate buffer[$-1] = 10; ```All of the buffer-stomping "must reallocate" cases are preserved in the rewrite that only assigns buffer.length when the new value is larger. The cases that were omitted, that were a performance drain, were same-length or less-length assignments.
Aug 03 2021
On Tuesday, 3 August 2021 at 19:04:06 UTC, jfondren wrote:```d void ensureHasRoom(ref ubyte[] buffer, size_t length) { buffer.length = length; // this is a serious bottleneck } void ensureHasRoom(ref ubyte[] buffer, size_t length) { if (buffer.length < length) { buffer.length = length; // this is fine actually } } ``` The story is that the situation was improved by excluding only those cases that should not have incurred any reallocations. Every single invocation of the bottlenecking `ensureHasRoom` that should have reallocated would still do so with the fixed `ensureHasRoom`. So something else was going on.ah. No, I get it: this was probably shrinking and then regrowing buffer.length across separate calls, which would incur reallocations on the regrowth.
Aug 03 2021
On 8/3/21 3:16 PM, jfondren wrote:On Tuesday, 3 August 2021 at 19:04:06 UTC, jfondren wrote:Yep, correct! Sorry I didn't see this before I did the other reply. -Steve```d void ensureHasRoom(ref ubyte[] buffer, size_t length) { buffer.length = length; // this is a serious bottleneck } void ensureHasRoom(ref ubyte[] buffer, size_t length) { if (buffer.length < length) { buffer.length = length; // this is fine actually } } ``` The story is that the situation was improved by excluding only those cases that should not have incurred any reallocations. Every single invocation of the bottlenecking `ensureHasRoom` that should have reallocated would still do so with the fixed `ensureHasRoom`. So something else was going on.ah. No, I get it: this was probably shrinking and then regrowing buffer.length across separate calls, which would incur reallocations on the regrowth.
Aug 03 2021
On 8/3/21 3:04 PM, jfondren wrote:On Tuesday, 3 August 2021 at 18:34:55 UTC, Steven Schveighoffer wrote:The allocation doesn't happen on the shrinking, it happens on the regrowing. So e.g. you have: ```d int[] buf; ensureHasRoom(buf, 10); // allocates buf[0 .. 10] = 42; ensureHasRoom(buf, 5); // does not reallocate in both versions buf[0 .. 5] = 43; ensureHasRoom(buf, 10); // Maybe reallocates (see below) buf[0 .. 10] = 44; ``` So before Ali made the change, the line to regrow to 10 elements DID reallocate, because now it might stomp on data held elsewhere (the runtime has no way of knowing how many references to the array buffer there are, it just knows how much has been used). After the change, the shrinking to 5 did not actually set the length to 5, the function left it at 10, so the "regrowing" sets the length from 10 to 10. This means no reallocation on the *subsequent* length change. The serious bottleneck is on the growing (unnecessarily), not in the shrinking. Clearly, the code in question can handle a buffer that isn't the exact length, but has at least enough length. Here's how I would write the function (if the buffer had to be the exact length needed): ```d void ensureHasRoom(ref ubyte[] buffer, size_t length) { bool shouldAssume = buffer.length > length; buffer.length = length; if(shouldAssume) buffer.assumeSafeAppend; } ``` which would have the same effect (though be slightly less efficient since it would still have to be an opaque call into the runtime, and possibly have to fetch block metadata). -SteveOn 8/3/21 2:21 PM, jfondren wrote:I think you're understanding it but not believing it. Again: ```d void ensureHasRoom(ref ubyte[] buffer, size_t length) { buffer.length = length; // this is a serious bottleneck } void ensureHasRoom(ref ubyte[] buffer, size_t length) { if (buffer.length < length) { buffer.length = length; // this is fine actually } } ``` The story is that the situation was improved by excluding only those cases that should not have incurred any reallocations. Every single invocation of the bottlenecking `ensureHasRoom` that should have reallocated would still do so with the fixed `ensureHasRoom`. So something else was going on.On Tuesday, 3 August 2021 at 18:18:48 UTC, Steven Schveighoffer wrote:There is not a reallocation on shrinking of length. Or am I misunderstanding your statement?It's no different for length setting: ```d buffer = new int[100]; auto buffer2 = buffer; buffer.length = 50; buffer.length = 51; // must reallocate buffer[$-1] = 10; ```All of the buffer-stomping "must reallocate" cases are preserved in the rewrite that only assigns buffer.length when the new value is larger. The cases that were omitted, that were a performance drain, were same-length or less-length assignments.
Aug 03 2021
On Tuesday, 3 August 2021 at 19:19:46 UTC, Steven Schveighoffer wrote:The allocation doesn't happen on the shrinking, it happens on the regrowing.Aye, I had some kind of sleep deprivation mental block on this function getting called repeatedly for the same buffer with different lengths. Imagine, instead, 10k separate buffers and a _single_ call of this function on each with a random length. In this case the reallocating calls would be the same with/without the fix.
Aug 03 2021
On 8/3/21 11:18 AM, Steven Schveighoffer wrote:In order for a length change to *not* reallocate, you have to call `assumeSafeAppend` on that adjusted buffer, to let the runtime know that we don't care about any existing data that might be referenced by others.Makes sense. Yes, I use assumeSafeAppend mostly on function-local-static buffers. (Similarly, Appender.clear() for appenders.) Ali
Aug 03 2021
On Sunday, 1 August 2021 at 08:54:05 UTC, Kirill wrote:It's interesting to hear do you use D's GC? Or do you use your own custom memory management structure? How performant is GC? The reason I'm asking is I'm planning to dive into 3D game dev with D as a hobby in an attempt to create a game I dreamed of since I was a kid. I'd like to know if GC is worth using at all, or should I go with 100% manual memory management. Any opinion is appreciated. Thanks in advance.I think GC fear is massively overblown, but I would be quite careful about using it heavily in a 3D game. Unpredictable pauses are your enemy. So using it to load/build e.g. level assets would be fine, but allocating anything short-lived? No way. I would likely make the core game loop nogc or be very strategic in allowing it to run. Then again, I have never build a 3d game before, only 3d scientific animations, so my advice is coming from a relatively weak position: I know D very well and have heard how games work.
Aug 03 2021
There's some good replies here. When I write high performance code, I use a mix of manual and GC allocation. Stuff that's critical for performance or recycling memory, I use manual. For not critical stuff, like setup and configuration code, I use the GC because it's so much more convenient.
Aug 03 2021
BTW, regardless of what language you use, or use GC or not, there's no way to write a high performance program without being cognizant of its memory consumption patterns.
Aug 03 2021
On Tuesday, 3 August 2021 at 19:33:27 UTC, Walter Bright wrote:BTW, regardless of what language you use, or use GC or not, there's no way to write a high performance program without being cognizant of its memory consumption patterns.Hear, hear. There have been others, but this one hit me like lightning. I'm now talking to you, and about you to everyone else, Walter. :) I'm still fairly new here. Does anyone have a Walter's Wisdoms file? Add this one. An ageless wisdom, well spoken.
Aug 04 2021
On Wednesday, 4 August 2021 at 21:58:58 UTC, Brian Tiffin wrote:I'm still fairly new here. Does anyone have a Walter's Wisdoms file? Add this one. An ageless wisdom, well spoken.On bugs vs input errors: "I believe this is a misunderstanding of what exceptions are for. "File not found" exceptions, and other errors detected in inputs, are routine and routinely recoverable. This discussion has come up repeatedly in the last 30 years. It's root is always the same - conflating handling of input errors, and handling of bugs in the logic of the program. The two are COMPLETELY different and dealing with them follow completely different philosophies, goals, and strategies. Input errors are not bugs, and vice versa. There is no overlap." - Walter Bright, 2014 Programming Languages on Crack: https://forum.dlang.org/post/saeagb$10t6$1 digitalmars.com AST macros: https://forum.dlang.org/post/qkpgea$1am3$1 digitalmars.com https://forum.dlang.org/post/l6co6u$vo$1 digitalmars.com Andrei also have "Great work is the cure for Good work" https://forum.dlang.org/post/q7u6g1$94p$1 digitalmars.com
Aug 04 2021
On Wed, Aug 04, 2021 at 09:58:58PM +0000, Brian Tiffin via Digitalmars-d wrote:On Tuesday, 3 August 2021 at 19:33:27 UTC, Walter Bright wrote:Here the ones I've added to my own quotes file: I've been around long enough to have seen an endless parade of magic new techniques du jour, most of which purport to remove the necessity of thought about your programming problem. In the end they wind up contributing one or two pieces to the collective wisdom, and fade away in the rearview mirror. -- Walter Bright Making non-nullable pointers is just plugging one hole in a cheese grater. -- Walter Bright Here's a funny one: My father told me I wasn't at all afraid of hard work. I could lie down right next to it and go to sleep. -- Walter Bright T -- This is a tpyo.BTW, regardless of what language you use, or use GC or not, there's no way to write a high performance program without being cognizant of its memory consumption patterns.Hear, hear. There have been others, but this one hit me like lightning. I'm now talking to you, and about you to everyone else, Walter. :) I'm still fairly new here. Does anyone have a Walter's Wisdoms file? Add this one. An ageless wisdom, well spoken.
Aug 04 2021
On Wednesday, 4 August 2021 at 22:42:56 UTC, H. S. Teoh wrote:Here the ones I've added to my own quotes file: [..]Ok, let's not get too OT here. Subject is still about the GC and if you use it in games for example.
Aug 05 2021