Do you use a garbage collector?

I

Ian Collins

Razii said:
Time: 78 ms

pretty fast...

however, if I change the loop to 10000003, the class has to change as
well.
That's not the point. The example was merely an illustration of how
object allocation can be optimised if required.

Custom allocators are a common optimisation in C++ where many small
objects are dynamically allocated.
 
M

Mike Schilling

Razii said:
There was nothing wrong with my basic premise that creating objects
with on heap is much faster in java than in c++.

Your premise was that each C++ "new" does a system call.. That's
nonsense, as what you quote below demonstrates.
---- quote---------
Creating heap objects in C++ is typically much slower because it's
based on the C concept of a heap as a big pool of memory that (and
this is essential) must be recycled. When you call delete in C++ the
released memory leaves a hole in the heap, so when you call new, the
storage allocation mechanism must go seeking to try to fit the
storage
for your object into any existing holes in the heap or else you'll
rapidly run out of heap storage. Searching for available pieces of
memory is the reason that allocating heap storage has such a
performance impact in C++, so it's far faster to create stack-based
objects.

Again, because so much of C++ is based on doing everything at
compile-time, this makes sense. But in Java there are certain places
where things happen more dynamically and it changes the model. When
it
comes to creating objects, it turns out that the garbage collector
can
have a significant impact on increasing the speed of object
creation.
This might sound a bit odd at first - that storage release affects
storage allocation - but it's the way some JVMs work and it means
that
allocating storage for heap objects in Java can be nearly as fast as
creating storage on the stack in C++.

[...] In some JVMs, the Java heap is quite different; it's more like
a
conveyor belt that moves forward every time you allocate a new
object.
This means that object storage allocation is remarkably rapid. The
"heap pointer" is simply moved forward into virgin territory, so
it's
effectively the same as C++'s stack allocation. (Of course, there's
a
little extra overhead for bookkeeping but it's nothing like
searching
for storage.)

Now you might observe that the heap isn't in fact a conveyor belt,
and
if you treat it that way you'll eventually start paging memory a lot
(which is a big performance hit) and later run out. The trick is
that
the garbage collector steps in and while it collects the garbage it
compacts all the objects in the heap so that you've effectively
moved
the "heap pointer" closer to the beginning of the conveyor belt and
further away from a page fault. The garbage collector rearranges
things and makes it possible for the high-speed, infinite-free-heap
model to be used while allocating storage.
 
A

asterisc

int main(int argc, char *argv[]) {
clock_t start=clock();
for (int i=0; i<=10000000; i++) {
Test *test = new Test(i);
if (i % 5000000 == 0)
cout << test;
}

If I add delete test; to this loop it gets faster. huh? what the
exaplanation for this?

2156 ms

and after I add delete test; to the loop

1781 ms

why is that?

Probably because of some compiler's optimizations.

When do you free memory in Java? Before or after you stop the clock?
 
I

Ian Collins

Razii said:
int main(int argc, char *argv[]) {

clock_t start=clock();
for (int i=0; i<=10000000; i++) {
Test *test = new Test(i);
if (i % 5000000 == 0)
cout << test;
}

If I add delete test; to this loop it gets faster. huh? what the
exaplanation for this?
You have just disproved your original hypothesis. Memory is returned to
the allocator, so it doesn't have to keep fetching more from the system.
 
I

Ian Collins

Razii said:
Where are these objects deleted .. does the time includes that? As I
showed in the loop, in the case of java GC collects most of these
objects in the loop.
As I pointed out earlier, you are leaking memory. Didn't you realise
that? Do you read peoples responses?
 
A

asterisc

You don't. When an object is no longer referenced by the program, the
GC will recycled it. The space is made available for subsequent new
objects.

Let me rephrase that:
When exactly is the memory deallocated? Before or after you stop the
clock?
Do you know exactly when the GC will free the memory ?

I think the memory for every new is not referenced outside the loop.
Does GC run in every loop step?
Can you print out a message like: "here is allocated at address: xxx"
and "here is deallocated from address: xxx"

What you said is pure theory. I'm worried about how is that in
practice...
 
I

Ian Collins

Razii said:
My number one hypothesis was that "new" is faster in java than in c++.
It doesn't behave the same way as in c++. I was speculating that the
reason for that is call to operating system in c++.
You claimed "In C++, each "new" allocation request will be sent to the
operating system, which is slow."

You have just disproved this by comparing the performance with and
without returning memory to the allocator. If each new requested memory
from the system, the performance would not have changed so
significantly.
 
A

asterisc

When exactly is the memory deallocated? Before or after you stop the
clock?

I already posted the output in the other post. The clock stops when
this is printed.

long end = System.currentTimeMillis();
System.out.println("Time: " + (end - start) + " ms");

The GC (in a different thread) runs several times while the main
thread is in the loop.

Once the main() thread ends, all the memory is returned to the
operating system by the JVM anyway.

Test@19f953d <----printed when i == 0
[GC 896K->108K(5056K), 0.0018061 secs]
[GC 1004K->108K(5056K), 0.0004453 secs]
[GC 1004K->108K(5056K), 0.0001847 secs]
[GC 1004K->108K(5056K), 0.0000500 secs]
[GC 1004K->108K(5056K), 0.0000461 secs]
[GC 1004K->108K(5056K), 0.0000478 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000478 secs]
[GC 1004K->108K(5056K), 0.0000506 secs]
[GC 1004K->108K(5056K), 0.0000483 secs]
[GC 1004K->108K(5056K), 0.0000461 secs]
[GC 1004K->108K(5056K), 0.0000497 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000461 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000955 secs]
[GC 1004K->108K(5056K), 0.0000494 secs]
[GC 1004K->108K(5056K), 0.0000464 secs]
[GC 1004K->108K(5056K), 0.0000481 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000469 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000486 secs]
[GC 1004K->108K(5056K), 0.0000469 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000469 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000531 secs]
[GC 1004K->108K(5056K), 0.0000461 secs]
[GC 1004K->108K(5056K), 0.0000461 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000534 secs]
[GC 1004K->108K(5056K), 0.0000481 secs]
[GC 1004K->108K(5056K), 0.0000461 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000453 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000469 secs]
[GC 1004K->108K(5056K), 0.0000453 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000534 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000469 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000469 secs]
[GC 1004K->108K(5056K), 0.0000481 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000461 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000469 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000592 secs]
[GC 1004K->108K(5056K), 0.0000464 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000469 secs]
[GC 1004K->108K(5056K), 0.0000453 secs]
[GC 1004K->108K(5056K), 0.0000469 secs]
[GC 1004K->108K(5056K), 0.0000486 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000601 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000453 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000453 secs]
[GC 1004K->108K(5056K), 0.0000469 secs]
[GC 1004K->108K(5056K), 0.0000481 secs]
Test@e86da0 <----printed when i == 5000000
[GC 1004K->108K(5056K), 0.0000528 secs]
[GC 1004K->108K(5056K), 0.0000464 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000545 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000481 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000478 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000481 secs]
[GC 1004K->108K(5056K), 0.0000464 secs]
[GC 1004K->108K(5056K), 0.0000486 secs]
[GC 1004K->108K(5056K), 0.0000478 secs]
[GC 1004K->108K(5056K), 0.0000489 secs]
[GC 1004K->108K(5056K), 0.0000481 secs]
[GC 1004K->108K(5056K), 0.0000461 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000461 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000453 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000453 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000464 secs]
[GC 1004K->108K(5056K), 0.0000612 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000469 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000902 secs]
[GC 1004K->108K(5056K), 0.0000469 secs]
[GC 1004K->108K(5056K), 0.0000601 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000461 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000503 secs]
[GC 1004K->108K(5056K), 0.0000483 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000623 secs]
[GC 1004K->108K(5056K), 0.0000461 secs]
[GC 1004K->108K(5056K), 0.0000461 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000673 secs]
[GC 1004K->108K(5056K), 0.0000461 secs]
[GC 1004K->108K(5056K), 0.0000478 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000478 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000623 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000481 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000469 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000453 secs]
[GC 1004K->108K(5056K), 0.0000453 secs]
[GC 1004K->108K(5056K), 0.0000481 secs]
[GC 1004K->108K(5056K), 0.0000514 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
Test@1975b59 <----printed when i == 10000000
Time: 172 ms

Can you print out a message like: "here is allocated at address: xxx"
and "here is deallocated from address: xxx"
 
A

asterisc

When exactly is the memory deallocated? Before or after you stop the
clock?

I already posted the output in the other post. The clock stops when
this is printed.

long end = System.currentTimeMillis();
System.out.println("Time: " + (end - start) + " ms");

The GC (in a different thread) runs several times while the main
thread is in the loop.

Once the main() thread ends, all the memory is returned to the
operating system by the JVM anyway.

Test@19f953d <----printed when i == 0
[GC 896K->108K(5056K), 0.0018061 secs]
[GC 1004K->108K(5056K), 0.0004453 secs]
[GC 1004K->108K(5056K), 0.0001847 secs]
[GC 1004K->108K(5056K), 0.0000500 secs]
[GC 1004K->108K(5056K), 0.0000461 secs]
[GC 1004K->108K(5056K), 0.0000478 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000478 secs]
[GC 1004K->108K(5056K), 0.0000506 secs]
[GC 1004K->108K(5056K), 0.0000483 secs]
[GC 1004K->108K(5056K), 0.0000461 secs]
[GC 1004K->108K(5056K), 0.0000497 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000461 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000955 secs]
[GC 1004K->108K(5056K), 0.0000494 secs]
[GC 1004K->108K(5056K), 0.0000464 secs]
[GC 1004K->108K(5056K), 0.0000481 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000469 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000486 secs]
[GC 1004K->108K(5056K), 0.0000469 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000469 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000531 secs]
[GC 1004K->108K(5056K), 0.0000461 secs]
[GC 1004K->108K(5056K), 0.0000461 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000534 secs]
[GC 1004K->108K(5056K), 0.0000481 secs]
[GC 1004K->108K(5056K), 0.0000461 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000453 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000469 secs]
[GC 1004K->108K(5056K), 0.0000453 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000534 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000469 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000469 secs]
[GC 1004K->108K(5056K), 0.0000481 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000461 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000469 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000592 secs]
[GC 1004K->108K(5056K), 0.0000464 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000469 secs]
[GC 1004K->108K(5056K), 0.0000453 secs]
[GC 1004K->108K(5056K), 0.0000469 secs]
[GC 1004K->108K(5056K), 0.0000486 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000601 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000453 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000453 secs]
[GC 1004K->108K(5056K), 0.0000469 secs]
[GC 1004K->108K(5056K), 0.0000481 secs]
Test@e86da0 <----printed when i == 5000000
[GC 1004K->108K(5056K), 0.0000528 secs]
[GC 1004K->108K(5056K), 0.0000464 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000545 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000481 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000478 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000481 secs]
[GC 1004K->108K(5056K), 0.0000464 secs]
[GC 1004K->108K(5056K), 0.0000486 secs]
[GC 1004K->108K(5056K), 0.0000478 secs]
[GC 1004K->108K(5056K), 0.0000489 secs]
[GC 1004K->108K(5056K), 0.0000481 secs]
[GC 1004K->108K(5056K), 0.0000461 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000461 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000453 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000453 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000464 secs]
[GC 1004K->108K(5056K), 0.0000612 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000469 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000902 secs]
[GC 1004K->108K(5056K), 0.0000469 secs]
[GC 1004K->108K(5056K), 0.0000601 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000461 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000503 secs]
[GC 1004K->108K(5056K), 0.0000483 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000623 secs]
[GC 1004K->108K(5056K), 0.0000461 secs]
[GC 1004K->108K(5056K), 0.0000461 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000673 secs]
[GC 1004K->108K(5056K), 0.0000461 secs]
[GC 1004K->108K(5056K), 0.0000478 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000478 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000623 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000481 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000469 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000453 secs]
[GC 1004K->108K(5056K), 0.0000453 secs]
[GC 1004K->108K(5056K), 0.0000481 secs]
[GC 1004K->108K(5056K), 0.0000514 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
Test@1975b59 <----printed when i == 10000000
Time: 172 ms

Can you print out a message like: "here is allocated at address: xxx"
and "here is deallocated from address: xxx"
 
A

asterisc

When exactly is the memory deallocated? Before or after you stop the
clock?

I already posted the output in the other post. The clock stops when
this is printed.

long end = System.currentTimeMillis();
System.out.println("Time: " + (end - start) + " ms");

The GC (in a different thread) runs several times while the main
thread is in the loop.

Once the main() thread ends, all the memory is returned to the
operating system by the JVM anyway.

Test@19f953d <----printed when i == 0
[GC 896K->108K(5056K), 0.0018061 secs]
[GC 1004K->108K(5056K), 0.0004453 secs]
[GC 1004K->108K(5056K), 0.0001847 secs]
[GC 1004K->108K(5056K), 0.0000500 secs]
[GC 1004K->108K(5056K), 0.0000461 secs]
[GC 1004K->108K(5056K), 0.0000478 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000478 secs]
[GC 1004K->108K(5056K), 0.0000506 secs]
[GC 1004K->108K(5056K), 0.0000483 secs]
[GC 1004K->108K(5056K), 0.0000461 secs]
[GC 1004K->108K(5056K), 0.0000497 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000461 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000955 secs]
[GC 1004K->108K(5056K), 0.0000494 secs]
[GC 1004K->108K(5056K), 0.0000464 secs]
[GC 1004K->108K(5056K), 0.0000481 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000469 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000486 secs]
[GC 1004K->108K(5056K), 0.0000469 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000469 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000531 secs]
[GC 1004K->108K(5056K), 0.0000461 secs]
[GC 1004K->108K(5056K), 0.0000461 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000534 secs]
[GC 1004K->108K(5056K), 0.0000481 secs]
[GC 1004K->108K(5056K), 0.0000461 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000453 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000469 secs]
[GC 1004K->108K(5056K), 0.0000453 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000534 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000469 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000469 secs]
[GC 1004K->108K(5056K), 0.0000481 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000461 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000469 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000592 secs]
[GC 1004K->108K(5056K), 0.0000464 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000469 secs]
[GC 1004K->108K(5056K), 0.0000453 secs]
[GC 1004K->108K(5056K), 0.0000469 secs]
[GC 1004K->108K(5056K), 0.0000486 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000601 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000453 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000453 secs]
[GC 1004K->108K(5056K), 0.0000469 secs]
[GC 1004K->108K(5056K), 0.0000481 secs]
Test@e86da0 <----printed when i == 5000000
[GC 1004K->108K(5056K), 0.0000528 secs]
[GC 1004K->108K(5056K), 0.0000464 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000545 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000481 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000478 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000481 secs]
[GC 1004K->108K(5056K), 0.0000464 secs]
[GC 1004K->108K(5056K), 0.0000486 secs]
[GC 1004K->108K(5056K), 0.0000478 secs]
[GC 1004K->108K(5056K), 0.0000489 secs]
[GC 1004K->108K(5056K), 0.0000481 secs]
[GC 1004K->108K(5056K), 0.0000461 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000461 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000453 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000453 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000464 secs]
[GC 1004K->108K(5056K), 0.0000612 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000469 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000902 secs]
[GC 1004K->108K(5056K), 0.0000469 secs]
[GC 1004K->108K(5056K), 0.0000601 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000461 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000503 secs]
[GC 1004K->108K(5056K), 0.0000483 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000623 secs]
[GC 1004K->108K(5056K), 0.0000461 secs]
[GC 1004K->108K(5056K), 0.0000461 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000673 secs]
[GC 1004K->108K(5056K), 0.0000461 secs]
[GC 1004K->108K(5056K), 0.0000478 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000458 secs]
[GC 1004K->108K(5056K), 0.0000478 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000623 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000481 secs]
[GC 1004K->108K(5056K), 0.0000472 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
[GC 1004K->108K(5056K), 0.0000469 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000475 secs]
[GC 1004K->108K(5056K), 0.0000453 secs]
[GC 1004K->108K(5056K), 0.0000453 secs]
[GC 1004K->108K(5056K), 0.0000481 secs]
[GC 1004K->108K(5056K), 0.0000514 secs]
[GC 1004K->108K(5056K), 0.0000455 secs]
Test@1975b59 <----printed when i == 10000000
Time: 172 ms

Can you print out a message like: "here is allocated at address: xxx"
and "here is deallocated from address: xxx"
 
M

Matthias Buelow

Juha said:
I have my doubts that this "liberating" style of programming somehow
automatically leads to clean, modular and abstract designs. All the
contrary, I would even claim that at least in some cases it leads to the
opposite direction ("reckless programming").

And your point is? The simple fact is, that bad programmers write bad
code, and good programmers write good code, no matter what the language
is or whether memory is managed automatically or manually.
 
M

Matthias Buelow

Razii said:
Yes, I did say that based on what I read on a web site. That was his
explanation regarding why allocating memory with new is slower in c++.

Maybe you shouldn't believe everything you read on a web site.
 
A

asterisc

Can you print out a message like: "here is allocated at address: xxx"
and "here is deallocated from address: xxx"

What would be the point? Everything is clear here.

[GC 1004K->108K(5056K), 0.0000464 secs]

GC == Garbage Collection.
1004K == Heap in use before collection.
108K == heap in use after collection.
5056K == Total heap size

0.0000464 secs == time it took.

There were a total of 174 of these outputs. That means,

0.0000464 * 174 = 0.0080736 sec == 8 ms

GC took 8 ms total...

What's the point allocating 1.000.000 new objects and never use them?

Why doesn't Java optimize this and allocate nothing, since they are
not used?

Anyway, in C++ it's a good idea to create memory pools if you intend
to play with a lot of small objects. Something like Ian did.

Try creating a memory pool in Java and compare it with GC's
performance.

Can you overwrite the new operator in Java?
Or are you comparing std::new with Java's new?

You forget that Java's GC is implemented in a lower-level programming
language, as C or C++. It cannot be faster than an implementation in C/
C++.
 
J

James Kanze

I have never used a GC for C++, yet in none of my C++ projects
(professional or hobby) in the last 5+ years have I had a
memory leak. I often use tools such as valgrind and AQTime to
check for memory leaks, and they have yet to report any leak.

And I wrote C and assembler for some 20 years before starting in
C++, and I never had a memory leak in them, either. From
experience, I'd say that you can either write correct programs
in any language, or you can't do it in any language. The
question is one of cost. How much effort does it take.

Garbage collection is a tool which reduces the amount of coding
necessary in some specific cases. As such, it would be foolish
not to avail oneself of it when appropriate. And it would be
just as foolish to expect it to suddenly solve all your
problems, just like that.
There just exists a *style* of programming in C++ which very
naturally leads to encapsulated, clean and safe code. (This
style is drastically different from how, for example, Java
programming is usually done.)

There are many styles of programming, both in C++ and in any
other language. Many of them don't lead to encapsulated, clean
and safe code. A few do. I use very similar styles of
programming in both Java and C++, but I've seen some pretty bad
code in both as well.

Of course, I don't quite see the relevance to garbage collection
in this. Quite obviously, you can write bad code with garbage
collection. And just as obviously, you can write bad code
without garbage collection.
One situation where GC *might* help a bit is in efficiency if
you are constantly allocating and deallocating huge amounts of
small objects in tight loops. 'new' and 'delete' in C++ are
rather slow operations, and a well-designed GC might speed
things up.
However, part of my C++ programming style just naturally also
avoids doing tons of news and deletes in tight loops (which
is, again, very different from eg. Java programming where you
basically have no choice). Thus this has never been a problem
in practice.

There are applications, of course, where you don't have the
choice; where you're developing dynamic structures (graphs,
etc.). But even there, the real gain is not in runtime (which
will rarely differ more than 10%-15% one way or the other), but
in development time. If the design determines that object
lifetime can be non-determinate, then you don't have to worry
about it when coding.

Obviously, in languages in which every object is allocated
dynamically, such objects are an overwhelming majority---almost
by definition, a value type doesn't have a determinate lifetime.
In C++, typically, objects without a determinate lifetime tend
more to be special cases: value types with variable size, or
which are too expensive to copy, even when you'd like to, or
"agents": small polymorphic objects without much, if any, state,
which are passed around, typically so that an object A can do
something dependent on the actual type of another object B.
While such objects aren't the majority, at least not in most C++
programs, they do occur often enough to make it worth having
garbage collection in your toolkit. Every little bit helps, as
they say.
Even if I some day stumble across a situation where constant
allocations and deallocations are impacting negatively the
speed of a program, and there just isn't a way around it, I
can use a more efficient allocator than the default one used
by the compiler. (I have measured speedups to up to over 8
times when using an efficient allocator compared to the
default one.)

You seem to be misunderstanding the argument. There are
specific times when garbage collection might be chosen for
performance reasons, but they are fairly rare, and as you say,
you can also optimize the performance of manual schemes. The
main argument for garbage collection is greater programmer
efficiency.

(There is a second argument, involving security. The fact that
the underlying memory of an object cannot be used for any other
object as long as there remains a pointer to the original
object. In an ideal system, of course, there wouldn't be such
pointers. But in practice, it's nice that you can make behavior
defined even if they happen to occur.)
 
J

Juha Nieminen

Razii said:
Also, according the site
above, in C++ memory is never returned to the operating system (at
least the older OS)

Which "older OS"? Some 30yo?
 
J

Juha Nieminen

Matthias said:
And your point is? The simple fact is, that bad programmers write bad
code, and good programmers write good code, no matter what the language
is or whether memory is managed automatically or manually.

My point is that the style of C++ programming which produces safe code
tends to also produce good code in other respects as well. Thus there's
a positive side-effect to not having GC in this case.

I often find that even quick&dirty small programs to perform minuscule
tasks look good because of this style of programming, and it doesn't
even necessarily require any extra work (mainly because usually the STL
can be used for data management).
 
J

Juha Nieminen

Razii said:
Well, my friend, I have proven you wrong. Razi has been victorious
once again :)

Uh? I said that the claim that each "new" performs an OS call is
blatantly false. How does your program prove that wrong?

Your C++ program does *not* perform a system call for each executed
new, and I can prove that.
 
J

Juha Nieminen

Razii said:
There was nothing wrong with my basic premise that creating objects
with on heap is much faster in java than in c++. Google search
confirms..

Your quote confirms that your claim that each 'new' causes an OS call
is false.
 
J

James Kanze

I strongly disagree. This style of programming almost
automatically leads to a clean, abstract, encapsulated design,
which is only a good thing.

We must have had to maintain C++ code written by different
people:). I don't think you can really claim that C++ forces
you to write clean, abstract, encapsulated code. (Nor does
Java, of course. Or any other language.)
Programmers using languages with GC (such as Java) might not need to
worry about where their dynamically-allocated memory is going, but
neither do I, in most cases. I even dare to claim that at least in some
cases this style of modular programming produces cleaner, simpler, more
understandable and in some cases even more efficient code than a
"mindlessly use 'new' everywhere" style of programming.

Woah. Garbage collection has absolutely nothing to do with how
often you use new. In fact, in many cases, it will result in a
lot less use of new than otherwise. It's much easier to share
representations if you don't have to worry about who's going to
delete it.
I honestly don't feel that I need to put any extra effort to
produce this kind of safe and clean code. Given that I usually
like the end result as a design, even if I have to put that
bit of extra effort it's totally worth it.
I have my doubts that this "liberating" style of programming
somehow automatically leads to clean, modular and abstract
designs. All the contrary, I would even claim that at least in
some cases it leads to the opposite direction ("reckless
programming").

The whole argument is irrelevant. On both sides. Garbage
collection doesn't make a language "dynamic", at least not in
the usual sense. Weak typing does, and I would agree that most
of the time, this leads to less robust code. The fact that
everything derives from Object (or rather, that so many things
only know about Object) is a disaster when it comes to writing
robust code. But you can do this in C++ as well---some early
container libraries did. (I believe that the problems revealed
by such libraries were part of the motivation for adding
templates to the language. Although even before templates, many
of us found that using <generic.h>, as painful as that was, was
preferable to "everything is an Object".)

In practice (and I speak here from experience), using garbage
collection in C++ doesn't impact style that much. (And with the
exception of a few people like you and Jerry Collins, many of
those worried about its impact on style really do need to change
their style.) Even with garbage collection, the "default" mode
in C++ is values, not references or pointers (call them whatever
you want), with true local variables, on the stack, and not
dynamically allocated memory. As far as I know, there's never
been the slightest suggestion that this should be changed.

The result is that, unlike the case in Java, garbage collection
isn't necessary in C++. But it does save some effort in certain
cases. And it can be used to significantly enhance security in
others. (Dangling pointers can be a serious security problem,
see
http://searchsecurity.techtarget.com/news/article/0,289142,sid14_gci1265116,00.html.
And while garbage collection can't completely eliminate dangling
pointers in C++---you can still return a pointer to a local
variable---it can certainly help.)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,576
Members
45,054
Latest member
LucyCarper

Latest Threads

Top