kb1
Junior Member
Posts: 229
Registered: 11-06 |
DaniJ said:
I just want to point out a contextual difference between where Graf is coming from and you (kb1) and Maes are - in ZDoom (and it's derivatives) a mobj_t is not a single fixed size. In his port a mobj_t instance is a dynamic composition, inheriting from (potentially) several different base classes.
Yes, absolutely - In my case, mobj_t's are fixed size, which is what makes them an obvious choice for me, I probably wouldn't have considered trying it otherwise. Excellent point.
Maes said:
In the working version of the code, I noticed that I didn't do any particular zeroing except maybe for the function codepointer. TBQH I don't remember what the actual issue was, however it seems solved now :-/
Quasar said:
I feel it should be noted that establishment of rigorous referential integrity is an obvious prerequisite.
Yes, I should have mentioned this. I'm using the Boom P_RemoveThinkerDelayed scheme, which is absolutely essential, and things of this nature when spawnning a new mobj:
code:
memset(mobj, 0, sizeof(*mobj));
info = &mobjinfo[type];
mobj->type = type;
mobj->info = info;
etc.
Graf Zahl said:
(things in a respectful manner)
Ok, you're being respectful :), I appreciate it - thank you, so I will respond.
Graf Zahl said:
So...
As I pointed out, you have a higher peak because you got 2 distinctive blocks of memory, which both need to be able to keep the maximum required amount of RAM.
This is true, but, then sizes of each pool are effectively smaller, aren't they? (of course, it's tricky to know what those are, which is partially alleviated by dynamic allocation) Graf Zahl said:
If you run out of memory in such situations, keeping a freelist would inevitably mean you allocate more memory - because you need to keep all the freed objects' memory allocated.
If you're dynamically allocating space, and you run out of memory, too bad - you don't have enough memory to run this map! Seriously. I assume that peak memory usage is what is needed, because during one frame of the game, it *is* needed. I think you're getting thrown off by my first discussion about running a low-memory condition to speed up testing. I'm not concerned with low memory handling in this discussion - this is about maintaining performance throughout a game session.
Graf Zahl said:
So, why not increase the heap's size to begin with?
Because I had a very real need to get the mobj_t's out of Doom/Boom's crappy heap, because they were causing the poor z_zone heap to needlessly purge and reload itself frequently. Yes, I could use a better implementation, or simply malloc/new each object. But, WOW! What a difference it made to just use the freelist - I literally stopped worrying about the crappy heap once that was done - the very specific problems I was concentrating on at the time simply disappeared.
Graf Zahl said:
Seriously, the first thing I'd do with Doom these days is dump the zone heap.
Agreed, it's shit.
Graf Zahl said:
Uh... Sorry, no. This may have been the case in days long past, but with modern CPUs and memory caching on the CPU it's not that easy. Your freelist *may* be better, yet again it may not. It depends a lot on memory usage patterns.
What I was saying is that it's *not* easy to judge what the external allocation functions are going to do. That doesn't mean not to use them, but, I won't whole-heartedly trust them either. Interesting that you mention the memory caching schemes - the freelist certainly does not provide perfect cache performance, but it *does* stick all the mobj_t's together.
Graf Zahl said:
Also, micro-optimization, meaning you optimize code that only runs less than 1% of the entire execution time will bring no realistic speed improvement at all...The only exception I have to make is when a significant number of very small objects gets frequently allocated and deallocated...And by frequent I mean something like several hundreds of these that get thrown away in the same frame normally.
1% is a *huge* amount! The maximum amount of time you can spend on a frame is 1/35 second, otherwise you're missing frames. If all of your code for rendering, state management, collision, sound, without counting memory alloc/dealloc time, takes 100% of 1/35 of a second, that extra 1% needed to allocate/deallocate causes you to miss a frame, which is a catastrophe if you're also running synchronous network play - now, your lagging. 1% of a total frame's time is not what you should be concerned with, it's the balance of remaining time (or lack of) that determines how smooth the game is.
Imagine a scenario if you will: Running a "Brutal Doom"-like add-on, in a rather brutal map. You've walked into a room with, say, 200 monsters. These are custom monsters, that spawn multiple missiles at a time. You fire the BFG, and they fire their missiles. Your BFG shot lands, and the traces are spawnned. You now have 200 monsters, half of them have spawnned 3 missiles, and you've spawnned, say 30 BFG clouds. You splatter 30 monsters, each of which sprays arms, heads, legs, and countless blood gibs. Tons of these gibs fall into the lava, which spawns splashes, and smoke spawnners. As these gibs bounce and hit the walls and floor, they spawn extra blood splats.
Can you honestly say that, this intense, but not unheard-of scenario does not have the potential to call SpawnMobj multiple hundreds of times per frame? Also consider that, you may be running HD resolution, 32-bit color, uncapped frame-rate, in a 3-player coop game. In this scenario, you have *no* time to spend in memory allocation calls - calls that would intersperse mobj_t's in with textures, flats, sounds, sprites in memory, messing up the memory cache.
*Anything* you can do to enhance performance, that is not too convoluted to maintain, should be considered for inclusion. Otherwise, your users just suffer needlessly for your coding philosophy.
You can place "valid REJECT map building" in this category as well. I wish people would spend the small amount of extra time it takes to do this - it's almost always a win.
Maes said:
...but the code changed a lot since them, and I didn't commit the unsuccessful attempts.
This in turn triggered me to complete a proper "codepointer" system with rewirable per-mobj "function pointers".
Just curious, are you now maintaining original demo sync with your port? That would be incredible! Is that something you're considering?
|