POV-Ray : Newsgroups : povray.off-topic : Interesting GC performance test Server Time
5 Nov 2024 08:27:08 EST (-0500)
  Interesting GC performance test (Message 1 to 6 of 6)  
From: Darren New
Subject: Interesting GC performance test
Date: 31 Jan 2009 17:48:43
Message: <4984d54b$1@news.povray.org>
Before running: 6.8 meg of unshared memory used.
While running: 7.1 meg of unshared memory used.

Doesn't look like GC tends to expand indefinitely, even when you *do* have 
tons of memory available. If you use allocations bigger than about 80K, it 
works even better, because .NET tracks them separately in a separate 
generation.

(Patched into a larger program just to test it out, so it's not 6 meg for 
this simple bit of code.)

         private void button6_Click(object sender, EventArgs e)
         {
             byte[] outer; byte[] outer2;
             for (int i = 0; i < 1024 * 1024 * 200; i++)
             {
                 outer = new byte[8192];
                 byte[] inner1 = new byte[8192];
                 byte[] inner2 = new byte[50190];
                 for (int j = 0; j < 1024; j++)
                 {
                     outer2 = new byte[30000];
                 }
             }
         }


-- 
   Darren New, San Diego CA, USA (PST)
   "Ouch ouch ouch!"
   "What's wrong? Noodles too hot?"
   "No, I have Chopstick Tunnel Syndrome."


Post a reply to this message

From: Warp
Subject: Re: Interesting GC performance test
Date: 31 Jan 2009 18:07:52
Message: <4984d9c8@news.povray.org>
Darren New <dne### [at] sanrrcom> wrote:
>          private void button6_Click(object sender, EventArgs e)
>          {
>              byte[] outer; byte[] outer2;
>              for (int i = 0; i < 1024 * 1024 * 200; i++)
>              {
>                  outer = new byte[8192];
>                  byte[] inner1 = new byte[8192];
>                  byte[] inner2 = new byte[50190];
>                  for (int j = 0; j < 1024; j++)
>                  {
>                      outer2 = new byte[30000];
>                  }
>              }
>          }

  Are you sure the compiler is not performing some clever optimization
tricks there like: "Hmm, this code allocates a piece of memory to this
pointer, the pointer demonstrably is not passed to anything anywhere
but is re-assigned a new memory block, thus the allocated memory is
likewise freed at that point, so I'll put a GC flag to this block of
memory to tell the GC engine that it's free."

  I wonder if it makes any difference if the pointer is passed to some
function which the compiler doesn't know what it does at this point.

-- 
                                                          - Warp


Post a reply to this message

From: Darren New
Subject: Re: Interesting GC performance test
Date: 31 Jan 2009 20:15:46
Message: <4984f7c2@news.povray.org>
Warp wrote:
>   Are you sure the compiler is not performing some clever optimization
> tricks there like: "Hmm, this code allocates a piece of memory to this
> pointer, the pointer demonstrably is not passed to anything anywhere
> but is re-assigned a new memory block, thus the allocated memory is
> likewise freed at that point, so I'll put a GC flag to this block of
> memory to tell the GC engine that it's free."

I'm not sure that's the case. I'm almost certain that it doesn't reuse 
memory in the middle of the block that's already been freed.

>   I wonder if it makes any difference if the pointer is passed to some
> function which the compiler doesn't know what it does at this point.

I'll give that a go and let you know.  I'll try to make it more convoluted.

-- 
   Darren New, San Diego CA, USA (PST)
   "Ouch ouch ouch!"
   "What's wrong? Noodles too hot?"
   "No, I have Chopstick Tunnel Syndrome."


Post a reply to this message

From: Darren New
Subject: Re: Interesting GC performance test
Date: 31 Jan 2009 21:02:01
Message: <49850299$1@news.povray.org>
Darren New wrote:
> I'll give that a go and let you know.  I'll try to make it more convoluted.

OK. Now when it starts, it's about 6.9 meg. As you move the mouse around the 
UI and it highlights different stuff and pops up tooltips and such, it 
drifts up to about 7.2 or 7.4 meg.  If you start the code here, it pops up 
to 10.25 meg and stays there. When the routine returns, it holds about 10.20 
meg, so it isn't doing a GC at the end. It probably schedules a GC after so 
many allocations or so many function entries or something; that's usually 
how these things are set up.  If it does a GC and finds it doesn't reap 
much, it turns down how often the GC runs.

I compiled these as separate projects, so they're only combined at the point 
where you actually run them (i.e., dynamically linked), so I'm pretty sure 
there's no unexpected optimizations going on. (Honestly, I can't even figure 
out how much garbage there is after each cycle, so ... ;-)

         private void button6_Click(object sender, EventArgs e)
         {
             byte[] outer; byte[] outer2;
             Fozz f; Fozz g;
             for (int i = 0; i < 1024 * 1024 * 200; i++)
             {
                 outer = new byte[8192];
                 byte[] inner1 = new byte[8192];
                 byte[] inner2 = new byte[50190];
                 f = new Fozz(inner2);
                 for (int j = 0; j < 1024; j++)
                 {
                     outer2 = new byte[30000];
                     g = new Fozz(f);
                     f = new Fozz(outer2);
                     outer2 = g.thingie(2);
                     f = new Fozz(g.thingie(1));
                 }
             }
         }

Separate assembly:

     public class Fozz
     {
         byte[] save;
         byte[] also;
         public Fozz(byte[] incoming)
         {
             save = incoming;
             also = (byte[])incoming.Clone();
         }
         public Fozz(Fozz f)
         {
             save = (byte[])f.save.Clone();
             also = (byte[])f.also.Clone();
         }
         public byte[] thingie(int x)
         {
             if (x == 1) return (byte[])save.Clone(); else return also;
         }
     }




-- 
   Darren New, San Diego CA, USA (PST)
   "Ouch ouch ouch!"
   "What's wrong? Noodles too hot?"
   "No, I have Chopstick Tunnel Syndrome."


Post a reply to this message

From: Nicolas Alvarez
Subject: Re: Interesting GC performance test
Date: 19 Feb 2009 22:57:44
Message: <499e2a38@news.povray.org>
Darren New wrote:
> I compiled these as separate projects, so they're only combined at the
> point where you actually run them (i.e., dynamically linked), so I'm
> pretty sure there's no unexpected optimizations going on. (Honestly, I
> can't even figure out how much garbage there is after each cycle, so ...
> ;-)

But .NET, like Java, optimizes at runtime, after linking everything
together....


Post a reply to this message

From: Darren New
Subject: Re: Interesting GC performance test
Date: 20 Feb 2009 13:15:00
Message: <499ef324@news.povray.org>
Nicolas Alvarez wrote:
> But .NET, like Java, optimizes at runtime, after linking everything
> together....

Possibly, yes. I don't know it does the sort of optimization we were talking 
about, which was basically escape analysis between independent assemblies.

If it does, that just goes to show the point more - you don't have to use up 
all that much memory.

The naive view of garbage collection is that you run the GC when you run out 
of memory, and hence you tend to take a lot of memory away from other 
processes. This was the complaint Warp expressed at one point that I felt 
like investigating. Apparently the GC in .NET runs even when you're nowhere 
near running out of memory, which makes sense in all kinds of ways. And 
there are probably pretty simple ways to dynamically tune the GC frequency 
as the program runs to keep things pretty well trimmed without too much GC 
overhead. Remember that the more often you GC, the less time each one takes.

-- 
   Darren New, San Diego CA, USA (PST)
   "Ouch ouch ouch!"
   "What's wrong? Noodles too hot?"
   "No, I have Chopstick Tunnel Syndrome."


Post a reply to this message

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.