www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Memory Handling and D

reply Berin Loritsch <bloritsch d-haven.org> writes:
Something that I have learned is that garbage collection and high
throughput can cause issues that you may not have considered.  When
I can only assume the person accusing me of FUD in another thread
has little or no experience developing high transaction/high throughput
systems with a garbage collected language.

The problem I ran into with the buffered IO in the web application was
not the size of the buffer.  I mean if you have a generous 32KB buffer
and 1000 simultaneous connections, that adds up to 3.2MB at any one
time.  That's not a lot.  However, when you add garbage collection to
the picture and 1000 responses a second, then that 32KB adds up because
the GC reclamation of memory is inevitably _slower_ than the rate at
which you are claiming new memory.  What looks like a memory leak is
really the GC lagging behind.  When the server slows down it will start
catching up.  However, if the server stays busy long enough you will
grind it to a halt and possibly die from an out of memory error.

If there is a way to do more manual memory management for these
situations, where memory is reclaimed immediately--or the same
32KB buffers are reused between files, then we can be very happy
with all buffered IO and no worries.

The important thing is to realize what the limitation is, and what the
problem really is.  In Java there is little or nothing you can do about
it.  Just recently it received the ability to use memory mapping for
files or use shared memory (which can still be very unstable).  So the
tools to deal with the problem have come in late to the game.

D does live closer to the metal, but do keep in mind the limitations of
GC in high throughput systems when developing your libraries.  I don't
profess to know much about D's memory handling, but if it has no way of
signaling a block of memory immediately available then it will be just
as crippled as Java in dealing with these issues.
Aug 10 2004
next sibling parent reply Ilya Minkov <minkov cs.tum.edu> writes:
Berin Loritsch schrieb:

 Something that I have learned is that garbage collection and high
 throughput can cause issues that you may not have considered.  When
 I can only assume the person accusing me of FUD in another thread
 has little or no experience developing high transaction/high throughput
 systems with a garbage collected language.

There is no need to be so frightened of being accused of a FUD. :> Yes, there are issues. Especially the executable can slow down to impossible if it actually needs a bit more memory than physcal memory the operating system cen give you. Garbage collecor hates to use virtual memory. Memory not accesed actively, but bound in the application, cannot be swapped out, because when physical memory is running out, the garbage collector would scan through its whole living set and do a read on this memory, thus swapping it back in. D provides some solutions to these borderline situations, but they are not always nice.
 The problem I ran into with the buffered IO in the web application was
 not the size of the buffer.  I mean if you have a generous 32KB buffer
 and 1000 simultaneous connections, that adds up to 3.2MB at any one
 time.  That's not a lot.  However, when you add garbage collection to
 the picture and 1000 responses a second, then that 32KB adds up because
 the GC reclamation of memory is inevitably _slower_ than the rate at
 which you are claiming new memory.  What looks like a memory leak is
 really the GC lagging behind.  When the server slows down it will start
 catching up.  However, if the server stays busy long enough you will
 grind it to a halt and possibly die from an out of memory error.

It will not die of out of memory error. Every time you allocate memory, there is a check whether it's about time to clean up. This "about time" may be, say, when the memory usage has grown significantly, or when physical ram is near to end. Then the collector would postpone the allocation, scan though the whole memory, identify what could be cleaned up, and clean up enough to allocate. Then memory would be allocated and it would return from the memory allocation routine to your program. However, if your program is multithreaded, i'm afraid it would have to stop all of the threads as well, which might hurt.
 If there is a way to do more manual memory management for these
 situations, where memory is reclaimed immediately--or the same
 32KB buffers are reused between files, then we can be very happy
 with all buffered IO and no worries.

First, you can use delete operator on the objects/memory allocated by the GC. This is immediately returned to the memory pool. Second, if the actually used set is growing very large, and you may want it to swap out (which i think in your case you don't), you can use std.c.stdlib.malloc and std.c.stdlib.free. Garbage collector knows nothing about memory allocated so, and should never touch it, so if you store any pointers to objects there, these objects may get deleted by the GC if they are referenced from nowhere else. But for buffers, it works well. Third, you can think of using auto classes, which allow you to free memory or OS resources at the very same moment they go out of stack scope. Auto classes are not flexible anough to be as generally usable as C++ model due to weaker operator overloading, but they serve many simple cases well. Especially you may need them to realize the first 2 tips.
 The important thing is to realize what the limitation is, and what the
 problem really is.  In Java there is little or nothing you can do about
 it.  Just recently it received the ability to use memory mapping for
 files or use shared memory (which can still be very unstable).  So the
 tools to deal with the problem have come in late to the game.

Java has always had "finally", which would allow to clean up everything, but with an immense effort on the library user, error prone.
 D does live closer to the metal, but do keep in mind the limitations of
 GC in high throughput systems when developing your libraries.  I don't
 profess to know much about D's memory handling, but if it has no way of
 signaling a block of memory immediately available then it will be just
 as crippled as Java in dealing with these issues.

In high performance circumstances, it's better to use memory managers than to allocate memory at all. Walter wrote a nice article which is hidden somewhere in the specifications. -eye
Aug 10 2004
parent reply Berin Loritsch <bloritsch d-haven.org> writes:
Ilya Minkov wrote:

 Java has always had "finally", which would allow to clean up everything, 
 but with an immense effort on the library user, error prone.

Yes, but according to specs it is meant to be called only once during the life of the object--and worse: it is not guaranteed to be called at all! There is no guarantee that it will be called in time. There are WeakReferences, but it is still slower than allocation in many cases.
 
 D does live closer to the metal, but do keep in mind the limitations of
 GC in high throughput systems when developing your libraries.  I don't
 profess to know much about D's memory handling, but if it has no way of
 signaling a block of memory immediately available then it will be just
 as crippled as Java in dealing with these issues.

In high performance circumstances, it's better to use memory managers than to allocate memory at all. Walter wrote a nice article which is hidden somewhere in the specifications.

Hmmm. Now I wonder where the artical is...
Aug 10 2004
parent reply "Ben Hinkle" <bhinkle mathworks.com> writes:
 In high performance circumstances, it's better to use memory managers
 than to allocate memory at all. Walter wrote a nice article which is
 hidden somewhere in the specifications.

Hmmm. Now I wonder where the artical is...

In case you haven't already read it, I think she is referring to the techniques in http://www.digitalmars.com/d/memory.html
Aug 10 2004
parent reply Ilya Minkov <minkov cs.tum.edu> writes:
Ben Hinkle schrieb:

 I think she is referring to the

from www.behindthename.com : ILYA m Usage: Russian Russian form of ELIJAH ELIJAH m Usage: English, Jewish, Biblical Pronounced: ee-LIE-zha From the Hebrew name Eliyahu meaning "my God is YAHWEH". Elijah was a Hebrew prophet of the 9th century BC, during the reign of King Ahab and his queen, Jezebel. The two Books of Kings in the Old Testament tell of his exploits, which culminate with him being carried to heaven in a chariot of fire. Does this leave any doubt? -eye the photoallergic master
Aug 10 2004
next sibling parent Ben Hinkle <bhinkle4 juno.com> writes:
Ilya Minkov wrote:

 Ben Hinkle schrieb:
 
 I think she is referring to the

from www.behindthename.com : ILYA m Usage: Russian Russian form of ELIJAH ELIJAH m Usage: English, Jewish, Biblical Pronounced: ee-LIE-zha From the Hebrew name Eliyahu meaning "my God is YAHWEH". Elijah was a Hebrew prophet of the 9th century BC, during the reign of King Ahab and his queen, Jezebel. The two Books of Kings in the Old Testament tell of his exploits, which culminate with him being carried to heaven in a chariot of fire. Does this leave any doubt? -eye the photoallergic master

ack! All this time I thought you were a she. Many apologies. I'll keep that URL handy for future reference.
Aug 10 2004
prev sibling next sibling parent Arcane Jill <Arcane_member pathlink.com> writes:
In article <cfar1h$2vl3$1 digitaldaemon.com>, Ilya Minkov says...
ILYA   m
Usage: Russian

Ben obviously never watched "Tha Man from UNCLE". :) Jill
Aug 10 2004
prev sibling parent coolmama66 <sam quickbabynames.com> writes:
Ilya Minkov Wrote:

 Ben Hinkle schrieb:
 
 I think she is referring to the

from www.behindthename.com : ILYA m Usage: Russian Russian form of ELIJAH ELIJAH m Usage: English, Jewish, Biblical Pronounced: ee-LIE-zha From the Hebrew name Eliyahu meaning "my God is YAHWEH". Elijah was a Hebrew prophet of the 9th century BC, during the reign of King Ahab and his queen, Jezebel. The two Books of Kings in the Old Testament tell of his exploits, which culminate with him being carried to heaven in a chariot of fire. Does this leave any doubt? -eye the photoallergic master

Well, it might be easier to figure out the pronunciation if you listen to the mp3 of the names at www.quickbabynames.com
Nov 26 2008
prev sibling next sibling parent reply Arcane Jill <Arcane_member pathlink.com> writes:
In article <cfakob$23qm$1 digitaldaemon.com>, Berin Loritsch says...

If there is a way to do more manual memory management for these
situations, where memory is reclaimed immediately--or the same
32KB buffers are reused between files, then we can be very happy
with all buffered IO and no worries.

Of course. malloc() and free(). If it works in C, it'll work in D. But an alternative D-trick is simply to call gc.fullCollect() very regularly, instead of waiting for the GC to make the decision. Jill
Aug 10 2004
parent reply Berin Loritsch <bloritsch d-haven.org> writes:
Arcane Jill wrote:
 In article <cfakob$23qm$1 digitaldaemon.com>, Berin Loritsch says...
 
 
If there is a way to do more manual memory management for these
situations, where memory is reclaimed immediately--or the same
32KB buffers are reused between files, then we can be very happy
with all buffered IO and no worries.

Of course. malloc() and free(). If it works in C, it'll work in D. But an alternative D-trick is simply to call gc.fullCollect() very regularly, instead of waiting for the GC to make the decision.

The next question I have about the gc.fullCollect() is twofold: 1) Does it block all threads the whole time it GC's? 2) How long does it take? The reason I ask is that is how Java's GC works--and a full collect on a large number of objects/allocated memory can take upwards of a second and a half. While that may not seem like a lot for a GUI application, that can be 1500 clients in the example I had originally. Granted, the equivalent in Java System.gc() is only a hint that GC could be done now--but there is no guarantee that it will be. Is there a gc.quickCollect() for a quick cycle? Those cost roughly a tenth of a second in Java which is much more acceptable.
Aug 10 2004
next sibling parent reply Ilya Minkov <minkov cs.tum.edu> writes:
Berin Loritsch schrieb:

 The next question I have about the gc.fullCollect() is twofold:
 
 1) Does it block all threads the whole time it GC's?

Yes, it should.
 2) How long does it take?

It may take long.
 The reason I ask is that is how Java's GC works--and a full collect
 on a large number of objects/allocated memory can take upwards of
 a second and a half.  While that may not seem like a lot for a GUI
 application, that can be 1500 clients in the example I had originally.

I have already heard that fugures of that order of magnitude can be reached on a very large number of objects.
 Granted, the equivalent in Java System.gc() is only a hint that GC
 could be done now--but there is no guarantee that it will be.

No guarantee here either - someone could have disabled the GC.
 Is there a gc.quickCollect() for a quick cycle?  Those cost roughly
 a tenth of a second in Java which is much more acceptable.

Generational garbage collection is not yet implemented. -eye
Aug 10 2004
parent reply Berin Loritsch <bloritsch d-haven.org> writes:
Ilya Minkov wrote:

 Berin Loritsch schrieb:
 
 Granted, the equivalent in Java System.gc() is only a hint that GC
 could be done now--but there is no guarantee that it will be.

No guarantee here either - someone could have disabled the GC.
 Is there a gc.quickCollect() for a quick cycle?  Those cost roughly
 a tenth of a second in Java which is much more acceptable.

Generational garbage collection is not yet implemented.

I see. In that case using stack buffers is probably the best way to keep the memory usage to a minimum. I have found that one of the most common sources of slowdown on server side Java programming is that of memory management. There are other things like the classic poor algorithms and creating new objects when you need to use a flyweight, but those are usually easy enough to take care of. I appreciate that D has more tools at its disposal than just GC--which is something Java does not have. This makes finding alternative solutions a lot easier. I have learned to be a lot more creative for some solutions than I care to be with Java programming.
Aug 10 2004
parent reply "Walter" <newshound digitalmars.com> writes:
"Berin Loritsch" <bloritsch d-haven.org> wrote in message
news:cfaq70$2v7m$1 digitaldaemon.com...
 I see.  In that case using stack buffers is probably the best way
 to keep the memory usage to a minimum.  I have found that one of the
 most common sources of slowdown on server side Java programming is
 that of memory management.  There are other things like the classic
 poor algorithms and creating new objects when you need to use a
 flyweight, but those are usually easy enough to take care of.

 I appreciate that D has more tools at its disposal than just GC--which
 is something Java does not have.  This makes finding alternative
 solutions a lot easier.  I have learned to be a lot more creative for
 some solutions than I care to be with Java programming.

Many benchmarks purport to show that Java is just as fast executing as C/C++ are. Examination of those benchmarks usually shows that it is doing a lot of function call, integral and floating point computation. Those kinds of operations, with a good Java JIT, will do just as well or better than C/C++. The problem, however, is that since Java does not allow any objects or arrays on the stack (or in static data), whenever you need one it needs to be allocated on the heap. This is a lot more expensive than stack allocation. Since one winds up allocating a lot more heap objects in Java than one does in C/C++, the end result is slower. Java offers no alternatives to gc allocation. This is why D allows stack based objects and value objects.
Aug 10 2004
next sibling parent reply "van eeshan" <vanee hotmail.net> writes:
"Walter" <newshound digitalmars.com> wrote in message
news:cfb5v9$76u$1 digitaldaemon.com...
 The problem, however, is that since Java does not allow any objects or
 arrays on the stack (or in static data), whenever you need one it needs to
 be allocated on the heap. This is a lot more expensive than stack
 allocation. Since one winds up allocating a lot more heap objects in Java
 than one does in C/C++, the end result is slower. Java offers no
 alternatives to gc allocation.

 This is why D allows stack based objects and value objects.

Are you saying that D allows one to create Objects entirely upon the stack? And entirely within static data?
Aug 10 2004
next sibling parent "Walter" <newshound digitalmars.com> writes:
"van eeshan" <vanee hotmail.net> wrote in message
news:cfb72j$9l7$1 digitaldaemon.com...
 "Walter" <newshound digitalmars.com> wrote in message
 news:cfb5v9$76u$1 digitaldaemon.com...
 The problem, however, is that since Java does not allow any objects or
 arrays on the stack (or in static data), whenever you need one it needs


 be allocated on the heap. This is a lot more expensive than stack
 allocation. Since one winds up allocating a lot more heap objects in


 than one does in C/C++, the end result is slower. Java offers no
 alternatives to gc allocation.

 This is why D allows stack based objects and value objects.

Are you saying that D allows one to create Objects entirely upon the

For auto objects, it is allowed for the compiler to put them there. But I was primarilly referring to structs and arrays.
 And entirely within static data?

Structs and arrays, yes. Java does not allow structs, nor does it allow arrays on the stack.
Aug 10 2004
prev sibling parent reply Arcane Jill <Arcane_member pathlink.com> writes:
In article <cfb72j$9l7$1 digitaldaemon.com>, van eeshan says...
 This is why D allows stack based objects and value objects.

Are you saying that D allows one to create Objects entirely upon the stack?

"Allows" - yes. But you have to write your own custom allocator to do it. And such objects are forbidden from having destructors, which may perhaps be a limiting factor. Click on the "Memory Management" link and see "Allocating Class Instances On The Stack" to see how it's done. I don't actually /like/ the fact that destructors are forbidden in such cases. Obviously it makes sense to forbid delete(), but C++ allows you to call the destructor without also calling the deallocator. (In D terms: I want to be able to call ~this() without also calling delete()). But you can't do that in D, and I /think/ the reason is that the GC calls both ~this() and delete() in succession and so D doesn't let you separate them.
And entirely within static data?

Thinking it through, extension of the abovementioned technique would allow you to do that too. You'd first have to reserve the memory, by doing something like this # ubyte[SIZE] myReservedMemory; and then override new to return &myReservedMemory. I have no idea how to precalculate SIZE at compile-time though. I think obj.sizeof will just return 8. Again, you'd have to forbid destructors. Jill
Aug 10 2004
next sibling parent Sean Kelly <sean f4.ca> writes:
In article <cfcfik$3sh$1 digitaldaemon.com>, Arcane Jill says...
I don't actually /like/ the fact that destructors are forbidden in such cases.
Obviously it makes sense to forbid delete(), but C++ allows you to call the
destructor without also calling the deallocator. (In D terms: I want to be able
to call ~this() without also calling delete()).  But you can't do that in D, and
I /think/ the reason is that the GC calls both ~this() and delete() in
succession and so D doesn't let you separate them.

I don't know. They can be separated in C++ so why not in D?
And entirely within static data?

Thinking it through, extension of the abovementioned technique would allow you to do that too. You'd first have to reserve the memory, by doing something like this # ubyte[SIZE] myReservedMemory; and then override new to return &myReservedMemory. I have no idea how to precalculate SIZE at compile-time though. I think obj.sizeof will just return 8.

Interesting idea. It would be kind of a hack, but you could make an allocator that basically just had a huge static array and parceled chunks out as needed. But you would have to be very careful that delete was never called on any data from those blocks. Sean
Aug 11 2004
prev sibling parent Andy Friesen <andy ikagames.com> writes:
Arcane Jill wrote:
 
 Thinking it through, extension of the abovementioned technique would allow you
 to do that too. You'd first have to reserve the memory, by doing something like
 this
 
 #    ubyte[SIZE] myReservedMemory;
 
 and then override new to return &myReservedMemory. I have no idea how to
 precalculate SIZE at compile-time though. I think obj.sizeof will just return
8.
 Again, you'd have to forbid destructors.

You can use alloca to allocate stack storage in much the same way as malloc. The trick is that this storage is toast when the function containing the call is terminated. (which is a real drag because you can't encapsulate the alloca call) Check the very bottom of <http://www.digitalmars.com/d/memory.html> So you could write: import std.c.stdlib; ubyte[] myReservedMemory = (cast(ubyte*)alloca(SIZE))[0 .. SIZE]; The allocation of auto variables could be changed to recognize "auto T t = new ..." and implement it terms of alloca() instead of gc.malloc() We don't even need the syntax to change. :) -- andy
Aug 11 2004
prev sibling next sibling parent Dave <Dave_member pathlink.com> writes:
In article <cfb5v9$76u$1 digitaldaemon.com>, Walter says...
"Berin Loritsch" <bloritsch d-haven.org> wrote in message
news:cfaq70$2v7m$1 digitaldaemon.com...
 I see.  In that case using stack buffers is probably the best way
 to keep the memory usage to a minimum.  I have found that one of the
 most common sources of slowdown on server side Java programming is
 that of memory management.  There are other things like the classic
 poor algorithms and creating new objects when you need to use a
 flyweight, but those are usually easy enough to take care of.

 I appreciate that D has more tools at its disposal than just GC--which
 is something Java does not have.  This makes finding alternative
 solutions a lot easier.  I have learned to be a lot more creative for
 some solutions than I care to be with Java programming.

Many benchmarks purport to show that Java is just as fast executing as C/C++ are. Examination of those benchmarks usually shows that it is doing a lot of function call, integral and floating point computation. Those kinds of

FWIW, I've noticed the same recently. A couple of things Sun Hotspot seems to excel at is peephole type of optimizations on primitives for small algoritms and function calling, especially recursive functions. From what I've seen, Hotspot and IBM both really seem to suffer where the 'hotspot' is more of a 'hotarea' and where a lot of object allocation is going on (as Walter pointed out). Speaking of Java v. C/++ benchmarks, here's a link from back a while: http://www.digitalmars.com/d/archives/13897.html It refers to this: http://www.idiom.com/~zilla/Computer/javaCbenchmark.html Which in turn gets one of it's key comparisons from here (source code): http://www.aceshardware.com/Spades/read.php?article_id=154 What it looks to me the author is doing to 'measure' FFT performance is this: rate = work / fraction_of_minimum_test_time; work_required = rate * minimum_test_time; run_test(work_required); //non-test related overhead is in here result = work_required / actual_time; There's cumulative overhead involved in the measured portion of the test, so the faster system is actually reported as being slower because the amount of work for the test is initially adjusted to how fast the system is (hehheh - tricky). If the code is changed to just measure the amount of work over time: i = ITERS; start = now(); while(i--) { FFT_test(); } score = ITERS / (now() - start); You get results well opposite of the posted conclusions comparing Java to C. I've run into stuff like that alot, especially for Java vs. C/++ stuff. I also run into a lot of benchmarks where they'll basically write the Java version as close to C as Java gets and then use OOP for the C++ version. Hardly a good comparision.
The problem, however, is that since Java does not allow any objects or
arrays on the stack (or in static data), whenever you need one it needs to
be allocated on the heap. This is a lot more expensive than stack
allocation. Since one winds up allocating a lot more heap objects in Java
than one does in C/C++, the end result is slower. Java offers no
alternatives to gc allocation.

This is why D allows stack based objects and value objects.

Aug 10 2004
prev sibling parent reply "Matthias Spycher" <matthias coware.com> writes:
The statement below does not necessarily hold, as the Java language and
runtime do not expose or dictate where things are allocated. I think it's
just a matter of time, and we'll see dynamic compilers applying all kinds of
interesting optimizations that previously were not well understood or too
expensive to do. For certain applications, e.g. those that run for a long
time, the performance may end up being better than any code that is
statically compiled, simply because the runtime optimizer knows more about
the environment in which the program executes. I'm not trying to bash D, I
think it's a great step forward, but we should not underestimate the
potential of more dynamic, type-safe languages like Java; especially
considering all the research that's going on in the field today.

Here are some links related to memory management:

http://www.di.ens.fr/~blanchet/escape-eng.html
http://portal.acm.org/citation.cfm?id=353937&coll=portal&dl=ACM&CFID=25648429&CFTOKEN=76142202
http://www.memorymanagement.org/bib/f.html

"Walter" <newshound digitalmars.com> wrote in message
news:cfb5v9$76u$1 digitaldaemon.com...

 The problem, however, is that since Java does not allow any objects or
 arrays on the stack (or in static data), whenever you need one it needs to
 be allocated on the heap. This is a lot more expensive than stack
 allocation. Since one winds up allocating a lot more heap objects in Java
 than one does in C/C++, the end result is slower. Java offers no
 alternatives to gc allocation.

Aug 11 2004
next sibling parent "Walter" <newshound digitalmars.com> writes:
Since Java is under active development, it is a moving target, and anything
said about it could become false for future versions of it. But for Java
compilers available now, you can't allocate things on the stack. But thanks
for the references, they are an interesting read.

"Matthias Spycher" <matthias coware.com> wrote in message
news:cfe9u3$1bsr$1 digitaldaemon.com...
 The statement below does not necessarily hold, as the Java language and
 runtime do not expose or dictate where things are allocated. I think it's
 just a matter of time, and we'll see dynamic compilers applying all kinds

 interesting optimizations that previously were not well understood or too
 expensive to do. For certain applications, e.g. those that run for a long
 time, the performance may end up being better than any code that is
 statically compiled, simply because the runtime optimizer knows more about
 the environment in which the program executes. I'm not trying to bash D, I
 think it's a great step forward, but we should not underestimate the
 potential of more dynamic, type-safe languages like Java; especially
 considering all the research that's going on in the field today.

 Here are some links related to memory management:

 http://www.di.ens.fr/~blanchet/escape-eng.html

 http://www.memorymanagement.org/bib/f.html

 "Walter" <newshound digitalmars.com> wrote in message
 news:cfb5v9$76u$1 digitaldaemon.com...

 The problem, however, is that since Java does not allow any objects or
 arrays on the stack (or in static data), whenever you need one it needs


 be allocated on the heap. This is a lot more expensive than stack
 allocation. Since one winds up allocating a lot more heap objects in


 than one does in C/C++, the end result is slower. Java offers no
 alternatives to gc allocation.


Aug 12 2004
prev sibling parent reply Ilya Minkov <minkov cs.tum.edu> writes:
There is nothing preventing D from becoming a dynamically compiled 
language - unlike C++ which is mostly stuck. And D's guarantees are 
quite broad, which will allow to explore worlds of optimization 
possibilities.

-eye

Matthias Spycher schrieb:

 The statement below does not necessarily hold, as the Java language and
 runtime do not expose or dictate where things are allocated. I think it's
 just a matter of time, and we'll see dynamic compilers applying all kinds of
 interesting optimizations that previously were not well understood or too
 expensive to do. For certain applications, e.g. those that run for a long
 time, the performance may end up being better than any code that is
 statically compiled, simply because the runtime optimizer knows more about
 the environment in which the program executes. I'm not trying to bash D, I
 think it's a great step forward, but we should not underestimate the
 potential of more dynamic, type-safe languages like Java; especially
 considering all the research that's going on in the field today.
 
 Here are some links related to memory management:
 
 http://www.di.ens.fr/~blanchet/escape-eng.html
 http://portal.acm.org/citation.cfm?id=353937&coll=portal&dl=ACM&CFID=25648429&CFTOKEN=76142202
 http://www.memorymanagement.org/bib/f.html
 
 "Walter" <newshound digitalmars.com> wrote in message
 news:cfb5v9$76u$1 digitaldaemon.com...
 
 
The problem, however, is that since Java does not allow any objects or
arrays on the stack (or in static data), whenever you need one it needs to
be allocated on the heap. This is a lot more expensive than stack
allocation. Since one winds up allocating a lot more heap objects in Java
than one does in C/C++, the end result is slower. Java offers no
alternatives to gc allocation.


Aug 12 2004
parent "Matthias Spycher" <matthias coware.com> writes:
That is true, but any exposure of the layout of objects in the language or
runtime API (to the programmer) will constrain a runtime optimizer. If you
take a look at the JNI, you find that it was very carefully crafted to
prevent this kind of exposure. Obviously the cost of using this API is
higher than if the layout of objects was exposed.

In this respect I don't think D should strive to be like Java. I see it more
as an alternative to statically compiled languages like C and C++. I also
hope someone will find the time to write an OS that demonstrates the value
of integrating the D language runtime (e.g. garbage collector) with the
OS -- exposing only D interfaces and modules.

Matthias

"Ilya Minkov" <minkov cs.tum.edu> wrote in message
news:cfgsqg$2ml5$1 digitaldaemon.com...
 There is nothing preventing D from becoming a dynamically compiled
 language - unlike C++ which is mostly stuck. And D's guarantees are
 quite broad, which will allow to explore worlds of optimization
 possibilities.

 -eye

 Matthias Spycher schrieb:

 The statement below does not necessarily hold, as the Java language and
 runtime do not expose or dictate where things are allocated. I think


 just a matter of time, and we'll see dynamic compilers applying all


 interesting optimizations that previously were not well understood or


 expensive to do. For certain applications, e.g. those that run for a


 time, the performance may end up being better than any code that is
 statically compiled, simply because the runtime optimizer knows more


 the environment in which the program executes. I'm not trying to bash D,


 think it's a great step forward, but we should not underestimate the
 potential of more dynamic, type-safe languages like Java; especially
 considering all the research that's going on in the field today.

 Here are some links related to memory management:

 http://www.di.ens.fr/~blanchet/escape-eng.html


 http://www.memorymanagement.org/bib/f.html

 "Walter" <newshound digitalmars.com> wrote in message
 news:cfb5v9$76u$1 digitaldaemon.com...


The problem, however, is that since Java does not allow any objects or
arrays on the stack (or in static data), whenever you need one it needs



be allocated on the heap. This is a lot more expensive than stack
allocation. Since one winds up allocating a lot more heap objects in



than one does in C/C++, the end result is slower. Java offers no
alternatives to gc allocation.



Aug 13 2004
prev sibling parent "Walter" <newshound digitalmars.com> writes:
"Berin Loritsch" <bloritsch d-haven.org> wrote in message
news:cfaohl$2uab$1 digitaldaemon.com...
 The next question I have about the gc.fullCollect() is twofold:

 1) Does it block all threads the whole time it GC's?

Yes.
 2) How long does it take?

 The reason I ask is that is how Java's GC works--and a full collect
 on a large number of objects/allocated memory can take upwards of
 a second and a half.  While that may not seem like a lot for a GUI
 application, that can be 1500 clients in the example I had originally.

GC doesn't have an upper bound to the time it takes. The more memory it has to scan, the longer it will take.
 Is there a gc.quickCollect() for a quick cycle?  Those cost roughly
 a tenth of a second in Java which is much more acceptable.

No.
Aug 10 2004
prev sibling next sibling parent reply "Walter" <newshound digitalmars.com> writes:
Yes, there are situations where gc is inappropriate. You have the following
options to deal with it:

1) use malloc/free for those buffers
2) overload operators new and delete for the struct or class being allocated
3) write a custom allocator for those buffers and use it like you would in C
4) a gc'd buffer can be reclaimed immediately if you explicitly call
'delete' on it.
Aug 10 2004
parent Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Walter wrote:
 Yes, there are situations where gc is inappropriate. You have the following
 options to deal with it:
 
 1) use malloc/free for those buffers
 2) overload operators new and delete for the struct or class being allocated
 3) write a custom allocator for those buffers and use it like you would in C
 4) a gc'd buffer can be reclaimed immediately if you explicitly call
 'delete' on it.

I would add another possibility, which can work in some limited circumstances: 5) Disable the gc most of the time. Run it once in a while to clean up lots of memory at once. This option works well when the working set of a program is pretty small. If only a small % of your program is actual active memory (and most is garbage), then a scan won't take long to complete and the GC can reclaim huge swaths of memory with little overhead. On the other hand, if you scan regularly, then you have lots of overhead: you reclaim relatively little memory each time that you perform a full scan. The problems, of course are twofold: a) you have a lot of garbage lying around most of the time, and b) it's hard to guarantee that you run the gc soon enough to avoid out of memory errors. WALTER: This implies that there might be a new useful gc mode, called something like "preferDisable". This mode prefers to allocate memory from the OS rather than run the GC (just like the state "disable"), but unlike "disable", it will run the GC if the OS won't give the program any more memory. Roughly, the memory allocation algorithm would work like this: void *getMemBlock(size_t s) { void *ret; ret = FindMemBlock(s); if(ret != null) return ret; if(gc_state == enabled) { fullCollect(); ret = FindMemBlock(s); if(ret != null) return ret; ret = AllocNewMemFromOS(s); return ret; } else { ret = AllocNewMemFromOS(s); if(ret != null) return ret; // uh oh...no more memory from OS! if(gc_state == preferDisable) { fullCollect(); ret = FindMemBlock(s); } return ret; } }
Aug 10 2004
prev sibling next sibling parent reply Sean Kelly <sean f4.ca> writes:
In article <cfakob$23qm$1 digitaldaemon.com>, Berin Loritsch says...
If there is a way to do more manual memory management for these
situations, where memory is reclaimed immediately--or the same
32KB buffers are reused between files, then we can be very happy
with all buffered IO and no worries.

Another alternative that Walter didn't mention would be to keep a queue of streams and recycle them rather than destroying and creating new ones every time you need one. Assuming the streams are coded in such a way that they can be reset to a clean state before reuse, this is likely the easiest method to prevent memory problems.
D does live closer to the metal, but do keep in mind the limitations of
GC in high throughput systems when developing your libraries.  I don't
profess to know much about D's memory handling, but if it has no way of
signaling a block of memory immediately available then it will be just
as crippled as Java in dealing with these issues.

Good point. Sean
Aug 10 2004
parent reply Nick <Nick_member pathlink.com> writes:
In article <cfb7kk$aam$1 digitaldaemon.com>, Sean Kelly says...
In article <cfakob$23qm$1 digitaldaemon.com>, Berin Loritsch says...
If there is a way to do more manual memory management for these
situations, where memory is reclaimed immediately--or the same
32KB buffers are reused between files, then we can be very happy
with all buffered IO and no worries.

Another alternative that Walter didn't mention would be to keep a queue of streams and recycle them rather than destroying and creating new ones every time you need one. Assuming the streams are coded in such a way that they can be reset to a clean state before reuse, this is likely the easiest method to prevent memory problems.

Hmm, or how about having the streams themselves keeping a common queue of buffers? That could be implemented in phobos and be completely transparent to the user. What do you think? Nick
Aug 11 2004
next sibling parent Sean Kelly <sean f4.ca> writes:
Nick wrote:
 
 Hmm, or how about having the streams themselves keeping a common queue of
 buffers? That could be implemented in phobos and be completely transparent to
 the user. What do you think?

I don't see why not. I wouldn't make it a part of the library spec (if such a thing is ever written) but it's a good candidate for optimization. Sean
Aug 11 2004
prev sibling parent Berin Loritsch <bloritsch d-haven.org> writes:
Nick wrote:
 In article <cfb7kk$aam$1 digitaldaemon.com>, Sean Kelly says...
 
In article <cfakob$23qm$1 digitaldaemon.com>, Berin Loritsch says...

If there is a way to do more manual memory management for these
situations, where memory is reclaimed immediately--or the same
32KB buffers are reused between files, then we can be very happy
with all buffered IO and no worries.

Another alternative that Walter didn't mention would be to keep a queue of streams and recycle them rather than destroying and creating new ones every time you need one. Assuming the streams are coded in such a way that they can be reset to a clean state before reuse, this is likely the easiest method to prevent memory problems.

Hmm, or how about having the streams themselves keeping a common queue of buffers? That could be implemented in phobos and be completely transparent to the user. What do you think?

I think it would work. Just allow the user to control the size of the common queue when they need to. It won't be necessary in most common applications that interact with the filesystem/sockets every once in a while, but it will help when the developer needs to tune the application for heavy use. If we have a one size fits most with the option of customizing the size then everything should be fine.
Aug 13 2004
prev sibling parent "Walter" <newshound digitalmars.com> writes:
"Berin Loritsch" <bloritsch d-haven.org> wrote in message
news:cfakob$23qm$1 digitaldaemon.com...
 D does live closer to the metal, but do keep in mind the limitations of
 GC in high throughput systems when developing your libraries.  I don't
 profess to know much about D's memory handling, but if it has no way of
 signaling a block of memory immediately available then it will be just
 as crippled as Java in dealing with these issues.

D has: delete p; to do just that.
Aug 11 2004