Well, if you're reading this, then you've most likely noticed that I am almost at the bottom of the journal page. Oh well, I'm sure they'll get around to reactivating it soon.
Anyway, I accomplished some more on memory management tonight. I implemented a heap tracer so I will know if something doesn't get deallocated before the app dies. I decided against overloading the new/delete operators as I have found that my overloaded delete may not always get called in the event a constructor throws an exception. Instead I went with inline macros again. It all worked out great. It will tell you which file/function/namespace/line number that the pointer was allocated in on both creation and deletion. If a pointer is never freed, the tracer will output where it was originally created so you can track it down quickly.
Next on the menu is implementing all of this into my old engine! I'm finally moving on! It will all have been worth it in the long run I'm sure.
Journal Entry for 8/22/05
Well, last friday I sent a request to the GD.Net Gods for a name-change from JohnMMena to NoMonkey. Unfortunatelly when they switched the name it deactived my GD.Net service.
So for the meantime, I am just going to update my last entry until things get straightened out.
I got the Smart pointers within 1 second of the standard new/delete. I really think I finally got them where I want them... maybe :).
I also implemeneted freelist's which turned out to be a pain all because of one very weird problem. When I would use the freelist on a simple base class, it worked fine, but for shits and giggles I decided to use it on my smart pointer class. When I did this, I would get a user breakpoint somewhere in the heap debugger stating that some memory had moved blah, blah, blah and I think there was something about my momma being fat in there too. Anyway, after beating my head over the problem for hours, I found that if I didn't initialize one variable in the default constructor of the smart pointer class, it would run okay, but had memory leaks.
So after wanting to grab my shot gun, load my computer up onto a launcher and yell "PUUUUULLL!", I decided to let some fresh eyes take a look at it and sent it over to Visage.
He and I went back and forth on the possible problems and after mulling it all over we came to the conclusion that there couldn't be anything wrong with the code whatsoever. Then, out of desperation, I changed my initial variable allocation of the freelist from new to malloc and to he and I's surprise, it worked. I think his exact quote was "I feel worthless as a programmer right now."
Anyway, problem solved and everything seems to be working okay. I think I'm going to look into overloading new/delete for memory tracing next. Then once this is complete, I might be able to move on to the actual engine work! But I doubt it. :)
Keep it real!
Journal Entry for 8/19/05
Well, after consulting with Eberly (3D Game Engine Architecture) on the whole slow pointer issue, I finally got these things to run at a reasonable speed.
My new numbers at n=10,000,000 loops is now:
Empty test loop took 0.031000 seconds
Standard new/delete took 44.860000 seconds
mem_ptr new/release took 99.985000 seconds
The last one of course being my smart pointer. I ran this on a different, slower machine which is why the numbers are larger in general. The cool thing is that the spread between the standard new/delete vs. mem_ptr new/release is only 55 seconds whereas on the other machine w/ the older code it was 173 seconds. That's only ~0.00001 seconds of overhead per alloc/dealloc pair. Not to mention the time for the smart pointers is faster with the newer code on the slower machine than the older code on the faster machine. (Say that 10 times fast!)
To gain this speed, I implemented Eberly's hash table.
Given how fast I can allocate 10 million objects, I think I can finally wrap these babies up and move on!
Next up: Free Lists!
I've already found a pretty kick ass free list example that runs the above loop in less than a second. I'm also debating on memory pools, but I'm getting mixed reviews on what people think about their reliability/performance.
[UPDATE]
I made some more optimizations to the code, my numbers are now:
Empty test loop took 0.047000 seconds
Standard new/delete took 45.844000 seconds
mem_ptr new/release took 51.968000 seconds
How do you like them apples? I'm much happier with these results!
[/UPDATE]
Thanks again for looking!
EDIT: Okay, I ran my own tests. Here they are:
There is the code. Here is the output:
That was a lot faster than I expected. Anyway, the ScalePtr is my smart pointer tied into my object factory, which upon creation requests a Scale object (creates one if none exist), and adds a reference. Upon destruction, it removes a reference. If references equal zero, it returns its memory to the free list as "available" memory.
I can send you my code for both my object factory, my free list, and my smart pointers if you want. However, my smart pointers rely on a base Object class. Though, mine is different than Eberly's. I didn't like the idea of having all objects be forced as instances (because RemoveRef() called delete this;) -- so I have the objects handle reference counting, but the smart pointers deal with verifying the count.