www. O S N E W S .com
News Features Interviews
BlogContact Editorials
.
Real world comparison: GC vs. manual memory management
By Thom Holwerda, submitted by MOS6510 on 2012-09-06 21:32:49
"During the 4th Semester of my studies I wrote a small 3d spaceship deathmatch shooter with the D-Programming language. It was created within 3 Months time and allows multiple players to play deathmatch over local area network. All of the code was written with a garbage collector in mind and made wide usage of the D standard library phobos. After the project was finished I noticed how much time is spend every frame for garbage collection, so I decided to create a version of the game which does not use a GC, to improve performance."
 Email a friend - Printer friendly - Related stories
.
Read Comments: 1-10 -- 11-20 -- 21-30 -- 31-40 -- 41-49
.
RE[7]: yes... but why?
By moondevil on 2012-09-07 13:29:31
Ah ok, there I agree with you.

One should always take care to use the more adequate set of algorithms and data structures for the problem at hand, while taking advantage of the language strengths.
Permalink - Score: 2
.
RE[2]: yes... but why?
By JAlexoid on 2012-09-07 14:44:01
> Well, outsourcing will not make you stand out for long. And the quality of a programmer lowers in time as he is used to do it the easy way. In the end, there's a reverse effect of this 'doing the easy way' - in which with the tools the programmer knows (because the lower level will be inaccessible) he will have to do fine-grained work. It's like picking needles with a boxing glove; the framework being a boxing glove, it looks nice and shiny.

The best programmers are lazy programmers(the essence of DRY principle). Outsourcing memory management has always been the trend. First it was manual, then bare metal, then OS'es managed it and now runtimes manage it.

And needles today are mostly in the form of business requirements, not getting that extra 1ms. But then again, you can actually squeeze those 1ms out of almost any system.
Permalink - Score: 3
.
RE: Targeting programs for GC
By wigry on 2012-09-07 15:04:04
Other thing a GC language programmer must be very familiar with is the GC mechanism. In Java ther are several to choose from and you really need to understand how they work in order to choose the approperiate. Even more, you need to understand how to tune your GC settings in order to get the required performance out of it.

One example.

Java 6 HotSpot server will default to Parallel GC. That is every once in a while the program freezes and memory is collected. Not god for webservers. Better is Concurrent-Mark-Sweep (CMS) GC. There are few tricks however. The default settings for CMS GC is quite poor. Basically your heap is devided into to regions Eden space and Old Gen. All memory allocations are initially made in Eden space which is CG-d very often. The objects surviving the GC will be moved to Old Gen. Looks nice. The very small Eden space is very cheap to collect. The huge Old Gen is collected at much much lower interval (up to once an hour) because that is an expensive operation.

The problem is that if the requested memory allocatio is bigger than fits into the Eden space, then the allocation is made directly in Old Gen which will fill up FAST needing very frequent Old Gen cleanup which is expensive as I told. That will make application ru even slower than with default GC.

The solution - increase the Eden space to reasonable size so that ALL allocations will happen there and elliminate the direct Old Gen allocations. Other hand try to keep the Eden space as small as possible because it is cleaned often and the smaller it is, the cheaper the cleanup.

One example from real life. I have Tomcat server that has 10GB RAM allocated to heap. Initially I enabled the CMS GC and it wasnt very fast. Discovered that 75% of alocations went directly to Old Gen which was sweeped very often. The default Eden Space size was 32MB. I initially increased it to 64MB, not much better. Then 128MB but still some allocations to Old Gen and the Eden Space was also collected too often - CPU load was too high. I increased the Eden space to 256MB and now I got the sweetspot. All allocations (except very eextreme Hibernate searches) are allocated in Eden Space, the collection happens around 50-75 times an hour and the Old Gen is very slowly increasing. The JVM analyses the situation int the Old Gen and actually analyses the rate of increase so even as I have 10GB available, the GC will kick in already around 2GB max 3GB level. On busy days, the Old Gen is collected 3 times an hour and on quieter days it is collected once an hour. Performance and app responsiveness is excellent.

Same app in the same server but with default Parallel GC had poor performance and was getting OutOfMemory errors with 6GB Heap. Now I don't use more than 3GB Heap and have excellent speed.

So you need to understand the GC algorithms and options to make the right choice and tune it correctly.

This is the whitepaper where I got all my knowledge - pure gold:
http://java.sun.com/j2se/referen...

Edited 2012-09-07 15:16 UTC
Permalink - Score: 2
.
Why only one solution?
By Alfman on 2012-09-08 01:02:54
Everyone please! There is no ONE solution that will always "win" under all conditions.

There's nothing wrong with going with GC and there's nothing wrong with managing memory oneself. I've been allocating my own objects for over a decade and it's honestly not been much trouble, it's second nature. I can see how inexperienced programmers often get in trouble with memory, but lets not exaggerate that all programmers are bad with managing objects. I can also see why some experienced programmers prefer GC and it's not a case of laziness. They're both valid options. Even the performance will vary on the specifics of the application, the benchmarks here will probably not apply directly anywhere else.


The best thing a programmer can do is to use the language that they are most comfortable with and best fits the task - don't worry about what anyone else says about GC.
Permalink - Score: 3
.
RE[4]: GC is for scripting
By tanzam75 on 2012-09-08 17:36:00
If so, then you're making your own head explode. Because I never wrote that.

I pointed out that the student was complaining about "precisely the scenario" that performs better under GC than without GC, and then said that "no wonder" he ran into problems when he took out the GC.

In other words, you will write your code differently if you have a GC, compared to if you do not have a GC. If you have a GC, you do not worry too much about short-lived objects, but worry a great deal about medium-lived objects. If you do not have a GC, then you do not worry too much about medium-lived objects, but must take care to avoid excessive overhead from constructing and destructing short-lived objects.

Since the student directly ported code that assumes a GC, it is not surprising that he ran into problems when he took out the GC. Indeed, by tailoring the code to the non-GC platform, he was able to eliminate the performance penalty.

It's puzzling how you make the leap from that to the straw man that "high performance and non-leaking code can only be achieved by using a GC."

Edited 2012-09-08 17:38 UTC
Permalink - Score: 3
.
RE[5]: GC is for scripting
By Alfman on 2012-09-08 18:56:32
tanzam75,

"If you have a GC, you do not worry too much about short-lived objects, but worry a great deal about medium-lived objects. If you do not have a GC, then you do not worry too much about medium-lived objects, but must take care to avoid excessive overhead from constructing and destructing short-lived objects."

I still don't think it's safe to assume these generalisations are accurate without benchmarking them in an application.

At the very least you need to qualify the quoted statement for objects which are on the heap, since objects which are on the stack won't suffer any heap allocation overhead. In a GC language, it can be difficult for the compiler to determine whether an object can be stored on the stack or heap since it doesn't know what other functions will do with pointers. In a non-GC language, it's possible to allocate objects on the stack and let the object destroy itself as it goes out of scope, which is free.

I'm not trying to promote one side over the other, but the issue is much more complex than can be surmised by generalisations. Programmers just have to benchmark their own code.
Permalink - Score: 2
.
RE[6]: GC is for scripting
By tanzam75 on 2012-09-08 21:55:56
> I still don't think it's safe to assume these generalisations are accurate without benchmarking them in an application.

Of course, benchmarking is always the first step in attacking performance problems. Every problem is unique.

That does not mean that we can't give rules of thumb. They may not always be true in every scenario, but they give you a starting point. They tell you what to pay attention to during the benchmarks, and what tweaks to try.
Permalink - Score: 2
.
RE[6]: GC is for scripting
By sakeniwefu on 2012-09-09 02:56:42
>
"If you have a GC, you do not worry too much about short-lived objects, but worry a great deal about medium-lived objects. If you do not have a GC, then you do not worry too much about medium-lived objects, but must take care to avoid excessive overhead from constructing and destructing short-lived objects."

I still don't think it's safe to assume these generalisations are accurate without benchmarking them in an application.


Benchmark, benchmark, and when you've established that there isn't any possible bottleneck other than memory allocation, then it still isn't the memory allocation system.

Some time ago, I designed and implemented an abstraction layer for an embedded OS and when the app it was serving was reported as being too slow by the customers my system allocator wrapper was singled out as the problem by the "profiler".

This was in a world of custom prematurely optimized everything. So my decision to keep it simple was met with little sympathy.

So, I rewrote it with a custom memory management algorithm to the point allocation and release were barely slower on average than a void (library) function call.

Guess what? It still was the bottleneck.

Some good old printf profiling revealed that the OOP client application was hitting it like crazy.

Classic allocation, Reference Counting, Garbage Collection, it wouldn't have made a difference.

The problem I see in all of GC, RAII(for system memory) or ARC is that they encourage the everything is an object mentality. And that mentality generally turns into programs that hit the allocator way too much.
Permalink - Score: 2
.
RE[7]: GC is for scripting
By Alfman on 2012-09-09 19:38:55
sakeniwefu,

"Benchmark, benchmark, and when you've established that there isn't any possible bottleneck other than memory allocation, then it still isn't the memory allocation system."

Well, GCC's allocator is not very good especially on SMP systems where it can be a bottleneck. So it might make sense to tinker with new allocators but I wouldn't want to imply that allocation is typically a bottleneck in most applications.


"So, I rewrote it with a custom memory management algorithm to the point allocation and release were barely slower on average than a void (library) function call."

I'm curious about the implementation, I've written my own too where objects were pooled in thread local storage and therefore incurred no overhead on SMP until the global allocator was hit to replenish the pools.


"Guess what? It still was the bottleneck. Some good old printf profiling revealed that the OOP client application was hitting it like crazy."

This should have been uncovered much earlier. Didn't the profiler give function counts?



"The problem I see in all of GC, RAII(for system memory) or ARC is that they encourage the everything is an object mentality. And that mentality generally turns into programs that hit the allocator way too much."

Absolutely, one of the easiest ways to improve low level performance is by reducing the number of objects we need to accomplish our tasks. If a process always allocates A+B+C, then those could be combined into one monolith object instead, reducing object overhead by a factor of 3 for both GC or non-GC languages. However many people are going to be on edge about where to draw the line between OOP purity and overhead. Even though ideally one might want to manipulate pixels as objects, the OOP paradigm just breaks down due to the inefficiency of having so many numerous objects. Some day we could have a language with virtual objects which don't exist in memory, but allow us to manipulate the pixels as if they were real objects.
Permalink - Score: 2

Read Comments 1-10 -- 11-20 -- 21-30 -- 31-40 -- 41-49

No new comments are allowed for stories older than 10 days.
This story is now archived.

.
News Features Interviews
BlogContact Editorials
.
WAP site - RSS feed
© OSNews LLC 1997-2007. All Rights Reserved.
The readers' comments are owned and a responsibility of whoever posted them.
Prefer the desktop version of OSNews?