Today we were discussing how long Garbage Collection breaks needs. And were wondering how long it would take to simply wipe 1 Gigabyte of memory. What would it take?
On my machine, about one second:
#include <stdlib.h>
#include <stdio.h>
const long long int NUM = 1024*1024*1024/8;
int main(void) {
long long int* ptr = malloc(NUM * sizeof ptr);
printf("Gigabytes: %lld\n",NUM * sizeof ptr / 1024 / 1024 / 1024);
for(int i=0;i<NUM;i++) {
ptr[i]=1l;
}
}
I then run the following (which unwillingly measures the allocation time, too:
$ gcc -O3 -std=c99 mem.c -o mem
$ time ./mem
Gigabytes: 1
real 0m1.056s
user 0m0.205s
sys 0m0.845s
One would expect that to return 1 GIG of memory back to free pool would be just some simple pointer manipulation. GCs don't generally clear the memory returned back.
The time to allocate a 1 GIG memory depends on what is going on in the O/S at the time - you have to set up page tables etc...
You need to consider many elements here. I doubt a general-purpose garbage collector cleans up memory when it unlinks it -- that would be a waste of time. That plus Garbage collection tends not to be O(N). Garbage collection usually has a few routines that it will run -- the simplest one to mention here would be compaction, compaction itself is based on the statistics of the distribution of allocated memory. The other phases will have similar complexities..
-- edit after comments below and in the question --
Your chosen answer does not bring you closer to that feeling -- in fact it is entirely misleading -- as it is not iterating over an in-memory data structure. It is just crudely wiping memory, which is not the job of a garbage collector.
A more accurate answer
If you wanted to get a real feel for the garbage collector I suggest writing a .NET or Java app and initializing a gig + of memory in differing sizes of objects and then randomly droping 100-300mb of objects, and then recreating them again of random sizes; Do this for a few passes to mix things up. Follow this by disabling the collector, dropping a gig worth of objects and then forcing a manual collections; This last manual collection is what you want to benchmark -- and you want to do this a 100 times or so and plot the result.
A note On 20 ms
I'm sure there are ways to get a collector to behave in a real-time pattern if that is what you desire. A collector does not have to do a full sweep, it can be written to perform as a collection of atomic operations and you could disable the collection phase on a realtime-timeout -- i.e., 20 ms. In this case it would have done a partial collection which would still be usefull.
You would have to adjust the strategy I mentioned to measure how much can be done in 20ms. Be sure to understand that how much is collected is more dependant on the amount of objects present rather than the size of them. So I suggest capturing both values should you decide to formally test the GC.
I measured memory bandwidth on several recent desktop models some time ago, testing with bursty transfers, and came up with a consistent number: roughly 5 gigabytes per second. Which matches very well with Niko's number, 0.205 seconds for a gig. The 0.845 seconds of system time is burned on making the memory available. Which has much more to do with the speed of your hard drive, the state of your paging file and how many pages of other programs are loaded in RAM than memory bandwidth.
In other words, anything you measure is likely to be off by 400% or more. Sometimes much more.