Take out the trash



  • A colleague discovered that the JVM will do automatic garbage collection for you. He decided that there was no way he would allow his code to contribute to the growth of the heap...

       // Make sure that there is enough space to run this step
    System.gc();
    funcStep1ToDoLargeTaskWithLotsOfNewAndDescopingOfStorage();

    System.gc();
    funcStep2ToDoLargeTaskWithLotsOfNewAndDescopingOfStorage();

    System.gc();
    funcStep3ToDoLargeTaskWithLotsOfNewAndDescopingOfStorage();

    System.gc();
    funcStep4ToDoLargeTaskWithLotsOfNewAndDescopingOfStorage();

    System.gc();
    funcStep5ToDoLargeTaskWithLotsOfNewAndDescopingOfStorage();

    // System.gc(); // let the other developers worry about their own resources!

    Of course, the fact that System.gc() is only a request to the JVM to do garbage collection, and no guarantee that it'll happen right then and there was a tad over his head...

     



  • @snoofle said:


    Of course, the fact that System.gc() is only a request to the JVM to do garbage collection, and no guarantee that it'll happen right then and there was a tad over his head...

    From what I understand, you stand a pretty good chance of actually getting the collector to run. But it's not guaranteed.

    Also, what's this guy's background? Does he not trust managed languages? I can't remember ever having done a [code]System.gc()[/code] and I've never had a problem.



  • @MiketheLiar: exactly (he's fairly junior, so I don't think he's ever worked with a language that didn't support implied gc). Still, if you're going to read up on something,  don't stop after the first paragraph.


  • Considered Harmful

    In unmanaged (actually, even in managed headdesk) languages I've seen people recommending to "reserve" a block of memory by dynamically allocating a fixed length array of bytes up-front, and then freeing it like ballast in the case of the dread Out Of Memory error. That seems wrong to me on several levels (but I've never done eg embedded programming).



  • Snoofle you're not making me feel any better.



  • @joe.edwards said:

    In unmanaged (actually, even in managed *headdesk*) languages I've seen people recommending to "reserve" a block of memory by dynamically allocating a fixed length array of bytes up-front, and then freeing it like ballast in the case of the dread Out Of Memory error. That seems wrong to me on several levels (but I've never done eg embedded programming).

    This makes some degree of sense if you need to be able to, say, roll back a transaction upon out of memory rather than just crashing (in languages where out of memory is normally unrecoverable because any attempt to recover it would require allocating memory). It's still unreliable, though, because there's no guarantee that the OS will actually tell you you're out of memory at an appropriate time.



  • @snoofle said:

    A colleague discovered that the JVM will do automatic garbage collection for you. He decided that there was no way he would allow his code to contribute to the growth of the heap...


    At what point will you lock the doors with everyone inside and burn the building down? You must be close, surely?



  • Does your colleague's application enable the DisableExplicitGC option by default?  Because that would turn this story from sad to hilarious.

     

     



  • @mikeTheLiar said:

    From what I understand, you stand a pretty good chance of actually getting the collector to run. But it's not guaranteed.

     

    Just like calls to Sleep(n) are guaranteed to idle for [b]at least[/b] n milliseconds, but could, according to it's specification, idle until the heat death of the universe.

     



  • @Kaslai said:

    Just like calls to Sleep(n) are guaranteed to idle for at least n milliseconds, but could, according to it's specification, idle until the heat death of the universe.

    Shouldn't they call it IngestHemlock(n) then?



  • @Kaslai said:

    @mikeTheLiar said:

    From what I understand, you stand a pretty good chance of actually getting the collector to run. But it's not guaranteed.

     

    Just like calls to Sleep(n) are guaranteed to idle for at least n milliseconds, but could, according to it's specification, idle until the heat death of the universe.

     


    I would like to see a system where Sleep(n) took a constant amount of time for constant n. Physics? What's physics?



  • @Ben L. said:

    @Kaslai said:

    @mikeTheLiar said:

    From what I understand, you stand a pretty good chance of actually getting the collector to run. But it's not guaranteed.

     

    Just like calls to Sleep(n) are guaranteed to idle for at least n milliseconds, but could, according to it's specification, idle until the heat death of the universe.

     

    I would like to see a system where Sleep(n) took a constant amount of time for constant n. Physics? What's physics?
    Lay off Sleep(n)... When's the last time you said you were going to sleep for exactly n hours and did so to the millisecond?

     



  • @Adanine said:

    @Ben L. said:

    @Kaslai said:

    @mikeTheLiar said:

    From what I understand, you stand a pretty good chance of actually getting the collector to run. But it's not guaranteed.

     

    Just like calls to Sleep(n) are guaranteed to idle for at least n milliseconds, but could, according to it's specification, idle until the heat death of the universe.

     


    I would like to see a system where Sleep(n) took a constant amount of time for constant n. Physics? What's physics?
    Lay off Sleep(n)... When's the last time you said you were going to sleep for exactly n hours and did so to the millisecondarbitrarily small time unit?

     



  • @snoofle said:

    Of course, the fact that System.gc() is only a request to the JVM to do garbage collection, and no guarantee that it'll happen right then and there was a tad over his head...
    I think the bit about it being a request and sleeping at least so many nanoseconds was to make the spec compatible with (exising) implementations. It allows you to implement it as void gc(){}, or to make it run when the processor load is lower, of course. However, Sun's implementation did start gc immediately. I've used it in some debugging sessions (turned out that rendering large fonts was a bit of a problem in Sun's java lib).

    I do like the fact that he seems to think that he was only gc'ing his own resources...



  • @snoofle said:

    A colleague discovered that the JVM will do automatic garbage collection for you. He decided that there was no way he would allow his code to contribute to the growth of the heap...

       // Make sure that there is enough space to run this step
    System.gc();
    funcStep1ToDoLargeTaskWithLotsOfNewAndDescopingOfStorage();

    System.gc();
    funcStep2ToDoLargeTaskWithLotsOfNewAndDescopingOfStorage();

    System.gc();
    funcStep3ToDoLargeTaskWithLotsOfNewAndDescopingOfStorage();

    System.gc();
    funcStep4ToDoLargeTaskWithLotsOfNewAndDescopingOfStorage();

    System.gc();
    funcStep5ToDoLargeTaskWithLotsOfNewAndDescopingOfStorage();

    // System.gc(); // let the other developers worry about their own resources!

    Of course, the fact that System.gc() is only a request to the JVM to do garbage collection, and no guarantee that it'll happen right then and there was a tad over his head...

     

    Did you follow the proper procedures after discovering this code (i.e. punching this "dev" so hard in his nuts that they migrated into his throat)? Because it's the only way stupid people learn.



  • @snoofle said:

    System.gc();

    We've usedGC.Collect() quite successfully when I worked on RavenDB - see here for an example. Of course, we've only used it in a small number of places, and only when it was actually needed - these are specifically places where we know we've just generated a lot of garbage and we are trying (and failing) to allocate more memory.



  •  I have a confession to make.  I once wrote a program that called System.gc() and that actually affected the semantics of the program.  Basically, the program parsed some input, built a bunch of expression trees, and then generated some code that calculated the results of those expressions.  But the input was stupid and actually had a lot of expressions in it whose value was unused.  So I used a WeakHashMap to store references to the expressions and did a call to System.gc() to clean up unused expressions (expressions that were actually used had strong references elsewhere), which optimized the output of my program.

    Of course it was a stupid way to do things; I easily could have just iterated over the expressions that I knew were directly reachable and recursed into them to find reachable subexpressions.  I don't remember why I didn't; I was probably just being lazy.  In my partial defence, this code was never intended to run in production (on the other hand, the code that was generated still does to this day as far as I know...))



  • @The_Assimilator said:

    punching this "dev" so hard in his nuts that they migrated into his throat

    Yes. He's now call Bridget and talks utter bollocks.

    @The_Assimilator said:

    Because it's the only way stupid people learn.

    Evidence would suggest otherwise, given suitably large values of stupid.


Log in to reply