Does anyone have a reference to a good test done comparing the speed of
C++ vs Java.
People are telling me that Java is as fast (or marginally slower +25%)
as C++, because their JVM will compile code into binary the first time
it runs.
(I realize this is not a straight C++ question, but i am trying to get
an answer from people who know C++ and Java)
Thanks,
Ivan
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
> People are telling me that Java is as fast (or marginally slower +25%)
> as C++, because their JVM will compile code into binary the first time
> it runs.
For exactly equivalent code, Java might actually be faster.
However, if you're coding Java-style in C++, you're doing it wrong.
I would rather recommend to continue this discussion elsewhere - I think
it has been discussed to death here - just IMHO.
So, question like "what is equivalent code" are of course apparent.
> However, if you're coding Java-style in C++, you're doing it wrong.
This also works vice-versa. No way how you put it, you solve problems
differently in C++ and Java, and for *most* problems, the speed of the
language is more the time (and money) required to build a program that
does what you need. (-:
In my expectation, I found java pretty fast to develop in, and pretty
slow for the final execution, but that depends on your problem domain.
So long,
Thomas
As always, it much depends on what you are doing. Part of the problem is
that a good C++ programmer will produce C++ code that runs faster than
Java code written by him/her, whereas a good Java programmer ...
There really is no margin in spending time on such discussions. The
strengths of both languages lie elsewhere.
--
Francis Glassborow ACCU
Author of 'You Can Do It!' and "You Can Program in C++"
see http://www.spellen.org/youcandoit
For project ideas and contributions:
http://www.spellen.org/youcandoit/projects
The fact that you can create a 100% complete JVM from scratch with C++, and
some assembly language of course, means that a comparison between Java and
C++ is unfair; IMHO, C++ simply has too many advantages over Java. Well,
that's what you get when you try to compare a very robust and "low-level
systems" language to a "very high-level virtual machine language" controlled
by a 'private company'... IMHO, Java should be compared to something like
Visual Basic, or C#...
Any thoughts?
> Does anyone have a reference to a good test done comparing the speed of
> C++ vs Java.
Not with your application, no.
There's an old saying: never trust a benchmark you didn't
falsify yourself. If you know both languages, and their
relative strengths and weaknesses, it's pretty straightforeward
to write a benchmark which runs faster in whichever language you
want to favorize. Typically, none of these benchmarks have the
slightest relationship to real application code, however.
> People are telling me that Java is as fast (or marginally slower +25%)
> as C++, because their JVM will compile code into binary the first time
> it runs.
Obviously, a lot depends on the actual JVM... and the C++
compiler. Still, there are some fundamental issues: Java
doesn't have anywhere near the aliasing problems that C++ does,
for example, and so has definite advantages when it comes to
optimizing arrays and such. It also works with the entire
program, always; many C++ compilers still stop at the
translation unit, or even the individual function. Similarly,
the JVM always has profiling information available (although it
typically cannot leverage off profiling from previous runs);
this is not true for all C++ compilers. Finally, the JVM knows
exactly on what machine it is running; a C++ compiler typically
generates code for a family of machines, and must make
compromizes (although most C++ compilers have options to tell
the compiler to optimize for a specific machine). On the other
hand, everything except basic types in Java must be dynamically
allocated. The JVM may be able to convert some of the uses to
on stack variables, but such analysis is very, very hard to do
reliably, and typically, if you want C++ to beat Java, you write
a benchmark with lots and lots of little objects---the garbage
collector may allow faster allocation than malloc, but there's
no way it can beat no allocation, and the excess allocations
also lead to poorer locality (more cache misses, etc.). Also,
in extreme cases, the C++ optimizer can take as long as it
wants, since it runs off line, and the time it takes isn't
counted as part of the application's run time. Not many
compilers take advantage of this, and of course, it has to be
weighed against possibly imperfect profiling data, but a couple
of days worth of static analysis should be able to turn up
optimizations no JVM could ever find.
Finally, of course, to put it all into perspective: both
languages are adequately fast for most applications. Most of
the time, the real issue is in which language your programmers
will be most productive.
--
James Kanze (GABI Software) email:james...@gmail.com
Conseils en informatique orientie objet/
Beratung in objektorientierter Datenverarbeitung
9 place Simard, 78210 St.-Cyr-l'Icole, France, +33 (0)1 30 23 00 34
The Ada Lovelace tutorial puts it this way:
"The best test of efficiency, of course, is to benchmark a specific
compiler with the type of problem you wish to solve."
IOW, you need to take the exact problem you are trying to solve with
the program, and benchmark it in different languages/compilers. There
is no "one best language for everything". Everything else is pointless
chatter. And "generic benchmarks" are almost useless. They are either
too narrow, too small, or implement things that are never used in "real
applications".
That said, there are some things that are obvious, and general enough
to be true. For instance, if you are writing a desktop GUI-heavy
application, you pretty much have to abandon Java at this point in time
if you care at all about efficiency ( i.e. user-responsiveness ). But
even if you use C++, the exact GUI toolkit you choose can have a huge
impact on performance. As well, the compiler you choose to use, the
threading model ( OS threads, or coroutines? ), etc. etc.
There just really is no substitute for writing the application in
different languages and testing it according to the performance
criteria that matter to *you* ( or your users ).
end-of-line
anyway, java is a commercial platform so in that sense I guess it is
comparable to .NET
I can't remember any other platform to compare, I thought on delphi but
it is comparable to VB
What I am looking for is not really specific measurements or anecdotal
stories from individual people's experience or tastes, or a useless
flame war.
The question is directed to people who know the internal workings of C++
compilation vs. JVM implementation as to empirically is it possible for
Java to execute as fast as C++ and if not by what margin could we expect
the difference to be, a small percentage or an order of magnitude.
Thank you for your understanding,
--
Ivan
http://wwww.0x4849.net
--
Thank you very much for your detailed reply James.
> Finally, of course, to put it all into perspective: both
> languages are adequately fast for most applications. Most of
> the time, the real issue is in which language your programmers
> will be most productive.
I have heard this often: "adequately fast". However if you think about
running applications in a data center, if an application can handle a
given load with X number of machines, and you change to Java, which is
adequately fast but is in actuality twice as slow as C++ than you may
need twice as many machines to handle the same load. So even though it
is adequately fast you could be substantially increasing the size of
your network and the amount of hardware required.
That is why I am trying to judge generically if Java would be an order
of magnitude slower than C++ by its very nature or not. However from
the replies I have gotten, it seems Java is not an order of magnitude
slower than C++, with the caveat that it all depends on the details of
your application.
-----------------
Ivan
http://www.0x4849.net
>in extreme cases, the C++ optimizer can take as long as it
>wants, since it runs off line, and the time it takes isn't
>counted as part of the application's run time. Not many
>compilers take advantage of this, and of course, it has to be
>weighed against possibly imperfect profiling data, but a couple
>of days worth of static analysis should be able to turn up
>optimizations no JVM could ever find.
I'm curious: do real-world tools exist that can carry such deep
analyses?
>Finally, of course, to put it all into perspective: both
>languages are adequately fast for most applications. Most of
>the time, the real issue is in which language your programmers
>will be most productive.
And in which language your program or library will be most *reliable*
(of course, "producing" unreliable software isn't exactly what one
means by "being productive", so my statement is really a corollary of
yours :-) --well, except perhaps that I'm not assuming you are stuck
with a given team of programmers). I think your reply, together with
that by Francis, nails down pretty much all that there is to say about
the original question as it was formulated.
> The question is directed to people who know the internal workings of C++
> compilation vs. JVM implementation as to empirically is it possible for
> Java to execute as fast as C++ and if not by what margin could we expect
> the difference to be, a small percentage or an order of magnitude.
*Optimal* C++ program will be faster than optimal Java program solving
the same problem for 99% of problems.
How much faster of course depends on the problem. I would expect ratio
1x - 4x faster.
JIT compilation can help Java a bit, bit not enough to close the gap
IMO.
> > Does anyone have a reference to a good test done comparing the speed of
> > C++ vs Java.
> The fact that you can create a 100% complete JVM from scratch with C++, and
> some assembly language of course, means that a comparison between Java and
> C++ is unfair; IMHO, C++ simply has too many advantages over Java.
By the same reasoning, C has too many advantages over C++, since
you can create a 100% complete C++ compiler from scratch in C.
Modern JVM are very sophisticated compilers: Sun currently
invests a lot more in the internal compilers in their JVM than
they do in their C++ compiler, and it shows in the relative
performances of the two.
The advantages of C++ lie elsewhere: if I'm doing a quick GUI,
Java beats C++ hands down, but for really robust software, and
large projects, I find that working in Java requires
considerably more effort.
> Well, that's what you get when you try to compare a very
> robust and "low-level systems" language to a "very high-level
> virtual machine language" controlled by a 'private company'...
> IMHO, Java should be compared to something like Visual Basic,
> or C#...
In practice, the usual alternatives for the applications where
it is most used are Perl and Python. But that doesn't address
the original question: there are things in Java which make it
inherently faster, and there are other things which work against
it. Depending on your application, one or the other may
predominate, but there are real applications which run faster in
Java than in C++. And both languages are fast enough for 99% of
all applications.
--
James Kanze (Gabi Software) email: james...@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
As far as speed, Java is probably not significantly slower
generally for common apps. However, be careful not to focus
only on speed. In the shops I've worked in (including the
current one) where both Java and C++ are used extensively,
we have had significant trouble in two areas. The first,
ironically is memory hogging. It seems that our Java apps
suck up huge amounts of memory and don't like to give it
back. This causes us a lot of grief when running these apps
with scores of other apps. Second, in my experience Java
file i/o is slower than C++ in practice.
Now perhaps the Java programmers in my shops were/are not
elite? I honestly do not know. Perhaps great Java code does
not have such problems with memory consumption and file i/o
speed. Or at least no more so than C++. On the other hand,
/in practice/ these have been problems with Java relative to
C++ /in my experience/. I'm curious if others have seen
similar trends or if they have some general advice on what
we might be doing wrong with respect to memory & file i/o.
(No we do not have memory hogging nor file i/o problems with
our C++ apps. Occasional core dumps on the other hand ... ;-)
Keith
Only because Sun invests so much more time to develop (and advertise!)
GUI for Java than for C++.
While comparing apples to oranges cannot be quite fair, this example
demonstrates that with a good library (biased opinion), C++ is quite
competitive with Java while solving GUI problems:
http://www.ultimatepp.org/www$uppweb$vsswing$en-us.html
Mirek
Yes you can, but are you implying that it is not possible to make a C
compiler in C++ or in Java for that sake? I have never tried, but I
fail to see what would stop such an attempt. I think making a JVM
(virtual machine) is fundamentally different from making compilers which
only operate om files.
---
Bjørn Roald
You can also have a look to:
http://www.flownet.com/ron/papers/lisp-java/
already mentioned in this group.
Regards
eca
In addition there are many applications where speed of program is
relatively irrelevant because they are limited by some other resource
(size of cache, speed of RAM, speed of backing store etc.) and a company
would be much better advised to spend money on better hardware resources
than try to find improvement by changing languages (and without a change
of programmers, that could be a complete disaster.)
Knowing how to help the compiler to produce more efficient code is
probably more important than knowing which language will perform better
if used by good programmers. And if you are employing mediocre
programmers, investing in good training is likely to be more helpful
(though you will likely have to pay the programmers more afterwards)
When it comes down to it, most companies make decisions based on costs.
It could well be that it is cheaper to run mediocre programs on more
hardware than excellent programs on less hardware. And cheaper to employ
mediocre programmers than excellent ones :-(
--
Francis Glassborow ACCU
Author of 'You Can Do It!' and "You Can Program in C++"
see http://www.spellen.org/youcandoit
For project ideas and contributions:
http://www.spellen.org/youcandoit/projects
> > The question is directed to people who know the internal workings of C++
> > compilation vs. JVM implementation as to empirically is it possible for
> > Java to execute as fast as C++ and if not by what margin could we expect
> > the difference to be, a small percentage or an order of magnitude.
> *Optimal* C++ program will be faster than optimal Java program solving
> the same problem for 99% of problems.
For a certain set of problems (and a certain definition of
"optimal"). For another set of problems, just the reverse might
be true.
> How much faster of course depends on the problem. I would expect ratio
> 1x - 4x faster.
> JIT compilation can help Java a bit, bit not enough to close the gap
> IMO.
If the application makes intensive use of large arrays of basic
types, and is suitably structured, Java will beat C++ easily;
the lack of aliasing allows much greater optimization, at much
less cost.
--
James Kanze (GABI Software) email:james...@gmail.com
Conseils en informatique orientie objet/
Beratung in objektorientierter Datenverarbeitung
9 place Simard, 78210 St.-Cyr-l'Icole, France, +33 (0)1 30 23 00 34
> > The advantages of C++ lie elsewhere: if I'm doing a quick GUI,
> > Java beats C++ hands down
> Only because Sun invests so much more time to develop (and advertise!)
> GUI for Java than for C++.
Because Java has a fairly well designed standard GUI, yes. Also
because the typical Java development model is rather tuned to
such programs (as opposed to large scale, critical
applications).
And I agree that if Sun had invested in C++ anywhere near the
amount they've invested in Java, we'd have a lot better language
as well. I certainly wouldn't mind a standard GUI library as
complete as Swing for C++.
The fact remains that for whatever reasons, they didn't.
> While comparing apples to oranges cannot be quite fair,
That's the real problem, I think. Java's actually quite good
for one or two niches; C++ tries (and IMHO succeeds) to be more
generalist. So while Java may be better than C++ for the GUI
interface, and C++ better than Java for the large, critical
server that I work on, I could do the GUI (fairly well,
actually, even if it would require more work) in C++, where as I
couldn't even consider Java for the server. The Java model is
too specialized, and doesn't scale, or port to domains for which
it wasn't designed.
All of which has nothing to do with the original question, which
was the relative performance:-).
> this example
> demonstrates that with a good library (biased opinion), C++ is quite
> competitive with Java while solving GUI problems:
> http://www.ultimatepp.org/www$uppweb$vsswing$en-us.html
The problem is that I've got to go and find that good library,
and install it, and train my collegues (and myself) to use it.
All without being sure that I'll be able to use it in the next
company I work for. Standardization does have its advantages.
--
James Kanze (GABI Software) email:james...@gmail.com
Conseils en informatique orientie objet/
Beratung in objektorientierter Datenverarbeitung
9 place Simard, 78210 St.-Cyr-l'Icole, France, +33 (0)1 30 23 00 34
> As far as speed, Java is probably not significantly slower
> generally for common apps. However, be careful not to focus
> only on speed. In the shops I've worked in (including the
> current one) where both Java and C++ are used extensively,
> we have had significant trouble in two areas. The first,
> ironically is memory hogging. It seems that our Java apps
> suck up huge amounts of memory and don't like to give it
> back. This causes us a lot of grief when running these apps
> with scores of other apps.
That's a good point. My experience, too, has been that Java, or
at least the Sun JVM, uses a lot more memory than one might
initially expect. And that the amount of memory seemed to be
independant of the size of the application: hello, world used as
much memory as our complex GUI based application. A priori, I
don't see why this should be implicit in the language; I suspect
that it is more an artifact of a particular implementation. But
given that 9 times out of 10, it's the implementation you're
going to have to use, it should be taken into account.
> Second, in my experience Java
> file i/o is slower than C++ in practice.
You've obviously not used the Sun CC libraries for IO:-).
(Seriously, I've no real experience with either. Most of my
critical IO is synchronized, and of course, that is slow, even
in C++.)
> Now perhaps the Java programmers in my shops were/are not
> elite? I honestly do not know. Perhaps great Java code does
> not have such problems with memory consumption and file i/o
> speed. Or at least no more so than C++. On the other hand,
> /in practice/ these have been problems with Java relative to
> C++ /in my experience/. I'm curious if others have seen
> similar trends or if they have some general advice on what
> we might be doing wrong with respect to memory & file i/o.
I can only confirm the memory use. I've heard rumors (from a
friend of a friend, so I really don't know how much faith to put
in them) that the IBM JVM didn't have the memory problem.
Supposedly (according to Sun) it is inherent with the use of
garbage collection, but I've not seen it, at least not to that
degree, with C++ using the Boehm collector. (Using garbage
collection generally does result in a bigger memory footprint,
but not anywhere near to the point using Java did.)
> (No we do not have memory hogging nor file i/o problems with
> our C++ apps. Occasional core dumps on the other hand ... ;-)
:-)
In my business, furnishing wrong information, or failing to
furnish complete information, is considered worse than a core
dump. You know, the sort of thing that happens when you get a
NullPointerException in the middle of Swing.
--
James Kanze (GABI Software) email:james...@gmail.com
Conseils en informatique orientie objet/
Beratung in objektorientierter Datenverarbeitung
9 place Simard, 78210 St.-Cyr-l'Icole, France, +33 (0)1 30 23 00 34
> >>> Does anyone have a reference to a good test done comparing the speed
of
> >>> C++ vs Java.
> >> The fact that you can create a 100% complete JVM from scratch with C++,
and
> >> some assembly language of course, means that a comparison between Java
and
> >> C++ is unfair; IMHO, C++ simply has too many advantages over Java.
> > By the same reasoning, C has too many advantages over C++, since
> > you can create a 100% complete C++ compiler from scratch in C.
> Yes you can, but are you implying that it is not possible to make a C
> compiler in C++ or in Java for that sake?
Yes and no. You can certainly write the compiler itself, but
you can't make it run the program (the way the JVM does), and
there are parts of the library which would probably cause
problems.
> I have never tried, but I
> fail to see what would stop such an attempt. I think making a JVM
> (virtual machine) is fundamentally different from making compilers which
> only operate om files.
A VM is more complicated than a compiler, in that it must cover
a number of issues that a compiler doesn't need to be concerned
with. The part of it which generates the code which will be
executed, however, is very much like a compiler, and that is the
part that makes a difference in the execution speed.
Independantly of the language, one can say that:
fully compiled:
"Unlimited" time for optimization. This isn't really true:
some of the more effective optimization techniques are
O(n^2) or worse over the size of the program, and would take
centuries or more on a complete application (millions of
lines of code). Never the less, even being able to take a
couple of hours when analysing code should provide a
definite advantage.
VM:
Knowledge of the exact target machine, and better knowledge
of the actual data being processed. Most good compilers use
profiling data to control optimization, but profiling data
is only more or less accurate with regards to real data. A
VM uses the actual data. In addition, it's even possible
for a VM to throw out already compiled code, and recompile
it, if the data characteristics change during the run.
My intuitive feeling is that being able to take hours should
give a slight edge to the compiler, but the real experts I know
tell me I'm wrong, and that the advantage is on the side of the
VM.
--
James Kanze (GABI Software) email:james...@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
> Thank you very much for your detailed reply James.
> > Finally, of course, to put it all into perspective: both
> > languages are adequately fast for most applications. Most of
> > the time, the real issue is in which language your programmers
> > will be most productive.
> I have heard this often: "adequately fast". However if you think about
> running applications in a data center, if an application can handle a
> given load with X number of machines, and you change to Java, which is
> adequately fast but is in actuality twice as slow as C++ than you may
> need twice as many machines to handle the same load. So even though it
> is adequately fast you could be substantially increasing the size of
> your network and the amount of hardware required.
So. And how much does that cost. (Java is particularly
inappropriate for large scale projects; even if it were twice as
fast as C++ here---and it's not---, the development costs you'd
save by using C++ would easily pay for the extra machines,
network speed, etc.)
> That is why I am trying to judge generically if Java would be an order
> of magnitude slower than C++ by its very nature or not. However from
> the replies I have gotten, it seems Java is not an order of magnitude
> slower than C++, with the caveat that it all depends on the details of
> your application.
That's the real point. You can't make any generalizations,
since every application is a special case.
--
James Kanze (GABI Software) email:james...@gmail.com
Conseils en informatique orientie objet/
Beratung in objektorientierter Datenverarbeitung
9 place Simard, 78210 St.-Cyr-l'Icole, France, +33 (0)1 30 23 00 34
> >in extreme cases, the C++ optimizer can take as long as it
> >wants, since it runs off line, and the time it takes isn't
> >counted as part of the application's run time. Not many
> >compilers take advantage of this, and of course, it has to be
> >weighed against possibly imperfect profiling data, but a couple
> >of days worth of static analysis should be able to turn up
> >optimizations no JVM could ever find.
> I'm curious: do real-world tools exist that can carry such deep
> analyses?
They exist. I don't know of any that run on Windows, however;
does that mean that they aren't real world? :-)
> >Finally, of course, to put it all into perspective: both
> >languages are adequately fast for most applications. Most of
> >the time, the real issue is in which language your programmers
> >will be most productive.
> And in which language your program or library will be most *reliable*
It depends on how you code. Up to a certain level, reliability
is significantly easier to achieve in Java; in fact, it's almost
impossible to write code which does achieve it. Beyond that
level, it's almost impossible to achieve in Java. For my
applications, that level is not sufficient, so C++ means better
reliability with less effort. If that level is sufficient,
however (and the project is small enough so that you don't have
to worry about organizing teams of programmers, and short term
enough that you can pretty much ignore maintenance issues), Java
is definitly worth considering.
In the end, I think it comes down to something I said in another
thread: Java is a highly specialized language, where as C++ is
general purpose. If your application corresponds to the
specialization, it's probable that Java would be the better
solution. If it doesn't, Java isn't a solution: there's no
better or worse about it. Where as with a little effort, you
can make C++ work for just about anything.
> (of course, "producing" unreliable software isn't exactly what one
> means by "being productive", so my statement is really a corollary of
> yours :-) --well, except perhaps that I'm not assuming you are stuck
> with a given team of programmers). I think your reply, together with
> that by Francis, nails down pretty much all that there is to say about
> the original question as it was formulated.
Keith Duggar did sort of hint at another point: in the real
world, your choice isn't between a perfect implementation of C++
and a perfect implementation of Java, it's between, say, VC++
2005 and Sun JDK something or other. When evaluating, you have
to take into account the tools actually available for your
platform. (Other than on Windows, for example, the
implementations of JVM have been pretty bad. If you're
targetting Sparcs, for example, Java will be distinctly slower
than C++, regardless of what the language allows.)
--
James Kanze (GABI Software) email:james...@gmail.com
Conseils en informatique orientie objet/
Beratung in objektorientierter Datenverarbeitung
9 place Simard, 78210 St.-Cyr-l'Icole, France, +33 (0)1 30 23 00 34
> What I am looking for is not really specific measurements or anecdotal
> stories from individual people's experience or tastes, or a useless
> flame war.
>
> The question is directed to people who know the internal workings of C++
> compilation vs. JVM implementation as to empirically is it possible for
> Java to execute as fast as C++ and if not by what margin could we expect
> the difference to be, a small percentage or an order of magnitude.
And the answer is, as always, "it depends on what you're doing".
What's good on the java side (speedwise, at least) is that objects
are by default passed around as pointers, not as copies, but the same
can be arranged within C++ as well, it just requires a different
programming style. What's also good on the java side is that the JIT can
adjust itself to the usage pattern of a specific method and thus
optimize it right away to the problem domain, but for C++ advanced
compilers (i.e. the intel icc compiler) also offer this type of feedback
optimization, but you are required to feed them with "typical" data.
What's bad on the java side (speedwise, again, not conceptionally) is
that a couple of runtime checks are made at runtime, i.e. array
out-of-bounds accesses, and type-checks. It has been argued that a
sufficiently smart JIT compiler can eliminate those.
And, whether any of these effects are dominant in your problem domain is
of course a question you can only answer by experimenting on realistic
data.
My personal problem domain is image procession, and this requires a lot
of data-shuffling and signal processing. Array bounds checking in java
(despite all claims of JIT optimizations) cause a slowdown here by about
a factor of two to three (no kidding), at least for java 1.4 back when I
checked it. You might get different figures nowadays.
Don't expect to find similar numbers for other problems - as said, it
really depends. Given "optimal" code on both sides, and a sufficiently
large data set such that the running time of the JIT only makes a small
contribution, I would expect two programs approximately the same speed
when the java run-time checks are not required. Note again that
"optimal" might look different.
So long,
Thomas
I am writing a regex engine and grammar in both C++ and Java, making
the code as similar as possible. My C++ virtual machine code which can
use pointer-based arrays and inlining extensively in a tight switch
statement loop is 6-8x faster for doing the most basic VM opcodes. On
the other hand, my automata/regex engine code is only 2-4x faster than
the same code in Java. It appears that Java performs very very well
with objects, which I use extensively for Nodes and Arcs in the
automata, but C++ is still basically 2x faster.
Andy
Kernigan and Pike (The Parctice of programming, 1999) implemented the
same algorithm
(The Markov Chain Algorithm) in different languages: C, C++, Java, Awk,
Perl
and compared their performances.
Here their results.
The times in the following table are the number of seconds.
The table also includes the approximate program size in lines of source
code.
Language Run Time (sec) Lines of code
C 0.36 150
Java 4.9 105
C++/STL/deque 2.6 70
C++/STL/list 1.7 70
Awk 2.2 20
Perl 1.8 18
The C and C++ versions were compiled with optimizing compilers, while
the Java
runs had just-in-time compilers enabled. The C version of the program
is fastest by a large factor;
Perl comes second. The times in the table are a snapshot of authors
experience with a particular
set of compilers and libraries, however, so you may see very different
results in
your environment.
We see a factor of 5-7 between C++ STL to pure C, and factor of 2-3
between Java and C++.
This results are 7 years old and it's important. For my opinion, C++
and Java compilers
are more mature now and also STL implementations.
I suggest to implement the same test (program listings exist in the
book) and compare result.
David
You can write template code to perform arbitrary computations at
compile time. I consider this a technique which allows one to put
domain specific optimizations in to the compiler. On a more concrete
note, gcc at any rate can perform optimizations based on profiling
information, compile in one pass with -fprofile-generate, run the
program and recompile with -fprofile-use. YMMV, of course, but I have
some rather unusual code (several thousand lines of nested if
statements) which benefit quite considerably (to the tune of 30% or so,
if I recall correctly).
-Ed
Let us say I wanted to give better answer than the usual diplomatic
"depends" :)
> > How much faster of course depends on the problem. I would expect ratio
> > 1x - 4x faster.
>
> > JIT compilation can help Java a bit, bit not enough to close the gap
> > IMO.
>
> If the application makes intensive use of large arrays of basic
> types, and is suitably structured, Java will beat C++ easily;
> the lack of aliasing allows much greater optimization, at much
> less cost.
Are you sure? I believe that you can use arrays in C++ the same way as
in Java, resulting in the same aliasing burden. Just because you can
have pointers to individual elements does not mean you have to use
them. But I can be wrong about this - can you show me some example?
--
Mirek Fidler
U++ team leader. http://www.ultimatepp.org
The documented options to the JVM probably include an initial VM size
which is taken from the OS whether used or not. That shouldn't matter
if the OS doesn't have to reserve physical memory (or backing store).
You may benefit from setting this parameter according to actual needs of
particular applications.
AFAIK neither JVM nor free()/delete will return pages to the OS once
the temporary high-water mark has been passed. The JVM at least could
in theory since it can relocate objects, a common practice in other
garbage-collected languages.
Fast allocators, which a JVM surely needs, increase memory usage by
saving pools in common sizes instead of aggressively recombining free
extents.
> Second, in my experience Java
> file i/o is slower than C++ in practice.
A telling point. Java insists on Unicode strings so pays the cost to
encode when writing 8-bit output, such as HTTP streams. You can do
efficient byte I/O but then must write ugly low-level parsing code.
> If the application makes intensive use of large arrays of basic
> types, and is suitably structured, Java will beat C++ easily;
> the lack of aliasing allows much greater optimization, at much
> less cost.
What do you mean by lack of aliasing?
What kind of optimization could Java do that C++ can't?
> While comparing apples to oranges cannot be quite fair, this example
> demonstrates that with a good library (biased opinion), C++ is quite
> competitive with Java while solving GUI problems:
>
> http://www.ultimatepp.org/www$uppweb$vsswing$en-us.html
This isn't that good from a C++ point of view.
Where is the RAII?
4x less code for C++ version of GUI app is not good from a C++ point of
view? Maybe the point of view should be adjusted a bit?
> Where is the RAII?
Everywhere. There is nothing else than RAII. (Of course, depends on
what exactly you are going to define RAII). The code is completely
deterministic.
--
Mirek Fidler
U++ team leader. http://www.ultimatepp.org
I'm going to wait for James' answer on this one, but I believe a
key detail in his answer was the "at much less cost" part; maybe
a C++ compiler could do certain optimizations, but with much much
more code analysis, for a particular situation; that simply means
that either the compiler is more likely to have bugs, or simply
that no compiler goes that far as to do those extremely complex
optimizations.
Of course, maybe there are additional issues that I'm missing
from James' comment (well, the fact that Java has always the
entire program seems like another possible explanation for his
comment --- if a compiler sees that a pointer to some data is
being passed to a function which is in a separate translation
unit, the best optimizer in the world pretty much has no choice
but to assume that that pointer will be used, and the potential
for optimization suffers; yes, maybe by flagging the condition
in the object file, and having the linker do complete additional
optimizations would solve that problem... But, really, at what
cost?
Carlos
--
PD: Just playing the devil's advocate here, in a sense; you'll
find very few people with such a pofound dislike for Java
as yours truly! :-)
[]
> AFAIK neither JVM nor free()/delete will return pages to the OS once
> the temporary high-water mark has been passed. The JVM at least could
> in theory since it can relocate objects, a common practice in other
> garbage-collected languages.
glibc malloc can return pages back to the OS. It does not do that by
default though.
Keith H Duggar wrote:
> The first ironically is memory hogging.
BTW, induced by the recent thread about GC, I have been experimenting a
little bit comparing memory consumption too.
I was using this simple benchmark code:
class A {
A *a;
A *b;
public:
A(int n) { if(n) { a = new A(n - 1); b = new A(n - 1); } else a = b =
NULL; }
~A() { delete a;delete b; }
};
int main()
{
A *a[256];
for(int i = 0; i < 256; i++)
a[i] = new A(10);
for (int i = 0; i < 10000; ++i) {
delete a[i & 255];
a[i & 255] = new A(10);
}
for(int i = 0; i < 256; i++)
delete a[i];
}
and compared to this C# version:
using System;
using System.Collections.Generic;
using System.Text;
namespace ConsoleApplication1
{
class A {
private A a;
private A b;
public A(int n) { if(n > 0) { a = new A(n - 1); b = new A(n - 1); }
}
}
class Program {
static void Main(string[] args)
{
A[] a = new A[256];
for(int i = 0; i < 256; i++)
a[i] = new A(10);
for (int i = 0; i < 10000; ++i) {
a[i & 255] = new A(10);
}
}
}
}
C# run 3 times slower than C++ version (using our current allocator),
but used 30x more memory! (150MB vs 5MB)
Really excellent way how to avoid memory problems....
--
Mirek Fidler
U++ team leader. http://www.ultimatepp.org
> VM:
> Knowledge of the exact target machine
What's the problem in compiling the C++ program as a set of dynamically
loadable modules (at least for the time-critical parts), each targeted
for different platform, shipping everything together and having the
startup or main program choosing the module to load after inspecting the
actual environment? Or maybe even earlier - at the installation time,
which would allow statically linked modules?
From what I remember, one of the steps in Oracle installation is to run
the linker on the machine where the software is being installed - that's
a perfect opportunity to select optimal pieces based on the target
environment.
Who said that C++ programs must be shipped as single monolithic black
boxes that are always built for the "least common denominator"?
> and better knowledge
> of the actual data being processed.
This is a good point and it can be an important factor in those
environment where the statistics of data cannot be foreseen or change
dynamically. The it-depends mantra still holds, though.
--
Maciej Sobczak : http://www.msobczak.com/
Programming : http://www.msobczak.com/prog/
> Everywhere. There is nothing else than RAII. (Of course, depends on
> what exactly you are going to define RAII). The code is completely
> deterministic.
RAII allows basic exception safety by acquiring resources in
constructors and releasing them in destructors.
However, I don't even see constructors and destructors. I only see a
pointer (!!! what an evil thing!) being passed to some function.
[...]
> > If the application makes intensive use of large arrays of basic
> > types, and is suitably structured, Java will beat C++ easily;
> > the lack of aliasing allows much greater optimization, at much
> > less cost.
> Are you sure?
Very. I've worked on enough compilers to know.
> I believe that you can use arrays in C++ the same way as
> in Java, resulting in the same aliasing burden. Just because you can
> have pointers to individual elements does not mean you have to use
> them.
You can use arrays in C++ pretty much in the same way as in
Java. But you can also to some things that you cannot do in
Java, and the compiler often cannot tell that you aren't.
C introduced a special keyword, restricted, to give the compiler
more information, precisely because of this problem.
> But I can be wrong about this - can you show me some example?
The classical example is something like:
void
smooth( int n, double[] a, double[] b )
{
for ( int i = 0 ; i < n - 1 ; ++ i ) {
a[ i ] = b[ i ] + b[ i + 1 ] ;
}
}
A JVM will know automatically that any two arrays are either the
same array, or non-overlapping; it could (and probably would)
save the b[i] read in the loop, and use it as the b[i+1] value
the next time through (thus avoiding a memory access). A C++
cannot, since the code it generates has to work even if it is
called with:
smooth( n, x + 1, x ) ;
(In which case, the value of b[i+1] is that of the a[i] writen
in the previous pass through the loop.)
--
James Kanze (GABI Software) email:james...@gmail.com
Conseils en informatique orientie objet/
Beratung in objektorientierter Datenverarbeitung
9 place Simard, 78210 St.-Cyr-l'Icole, France, +33 (0)1 30 23 00 34
> > What I am looking for is not really specific measurements or anecdotal
> > stories from individual people's experience or tastes, or a useless
> > flame war.
> > The question is directed to people who know the internal workings of C++
> > compilation vs. JVM implementation as to empirically is it possible for
> > Java to execute as fast as C++ and if not by what margin could we expect
> > the difference to be, a small percentage or an order of magnitude.
> And the answer is, as always, "it depends on what you're doing".
> What's good on the java side (speedwise, at least) is that objects
> are by default passed around as pointers, not as copies, but the same
> can be arranged within C++ as well, it just requires a different
> programming style.
And without garbage collection, you still have added overhead
(especially in a multithreaded environment) to ensure that the
object eventually gets deleted. It's not accidental that people
trying to show off the performance advantages of garbage
collection tend to use multithreaded programs with lots of
strings and substrings:-).
On the other hand, what's bad on the Java side (speedwise, at
least), is that you have to pass even the simplest types as
pointers, with an additional dereference to access them. If
you've something like:
struct Point { double x ; double y ; /* ctor, etc.* / } ;
the equivalent of:
std::vector< Point > array( 1000000, Point( 1.0, 2.0 ) ) ;
is going to take a lot more time in Java; accessing the elements
of the points in the array may also be slower, because of the
added indirection, and locality is very definitly going to be
significantly worse. (Of course, possible aliasing may cause
the C++ compiler to loose much of that advantage.)
The fact that objects must be dynamically allocated, and that
variables are pointers, and not the actual object, is probably
the biggest thing Java has going against it (from a performance
point of view, certainly---many of us would also argue that it
is a bad decision from a purely software engineering point of
view:-)).
> What's also good on the java side is that the JIT can
> adjust itself to the usage pattern of a specific method and thus
> optimize it right away to the problem domain, but for C++ advanced
> compilers (i.e. the intel icc compiler) also offer this type of feedback
> optimization, but you are required to feed them with "typical" data.
And a typical error is to give them data from your test suites.
Test suites that go out of their way to exercise all of the
paths, especially those that don't get exercised in typical use.
Barring that, you still have the problem that "typical" data may
vary from one site to the next.
> What's bad on the java side (speedwise, again, not conceptionally) is
> that a couple of runtime checks are made at runtime, i.e. array
> out-of-bounds accesses, and type-checks. It has been argued that a
> sufficiently smart JIT compiler can eliminate those.
There have been actual studies concerning the out-of-bounds
checks, not for Java, but for other languages, like Pascal.
Even using very dated optimization techniques, a good compiler
can eliminate well over 90% of them (including all of them in
cricital loops).
It's probably harder to eliminate the type checks, but I've not
seen any actual studies concerning them. Also important is the
fact that the type check that you don't eliminate is a lot more
expensive than any bounds check. Formally, of course, the Java
type system is even stricter than that of C++, and you can write
Java code which never needs a type check. That's not the way
actual Java is written, however.
> And, whether any of these effects are dominant in your problem domain is
> of course a question you can only answer by experimenting on realistic
> data.
> My personal problem domain is image procession, and this requires a lot
> of data-shuffling and signal processing. Array bounds checking in java
> (despite all claims of JIT optimizations) cause a slowdown here by about
> a factor of two to three (no kidding), at least for java 1.4 back when I
> checked it. You might get different figures nowadays.
I would imagine that aliasing would make C++ optimizers much
less efficient than Java for this sort of application. Unless,
of course, your arrays are of Pixel { int red, blue, green ; },
or something like that. In which case, it's likely that the
slowdown is due to the extra indirections and allocations, and
the loss of locality, rather than bounds checking.
--
James Kanze (GABI Software) email:james...@gmail.com
Conseils en informatique orientie objet/
Beratung in objektorientierter Datenverarbeitung
9 place Simard, 78210 St.-Cyr-l'Icole, France, +33 (0)1 30 23 00 34
> > VM:
> > Knowledge of the exact target machine
> What's the problem in compiling the C++ program as a set of dynamically
> loadable modules (at least for the time-critical parts), each targeted
> for different platform, shipping everything together and having the
> startup or main program choosing the module to load after inspecting the
> actual environment? Or maybe even earlier - at the installation time,
> which would allow statically linked modules?
Issues of deployment and disk usage.
Fundamentally, that's more or less what you're already doing if
you support both Sparc and Intel. The problem with taking it
further is that there are (or have been) some twenty or thirty
different variants of each, so you end up with an awful lot of
files to distribute.
It's definitly worth doing, however, in cases where there is one
particular innovation which makes a significant difference.
> From what I remember, one of the steps in Oracle installation is to run
> the linker on the machine where the software is being installed - that's
> a perfect opportunity to select optimal pieces based on the target
> environment.
That's possibly a workable solution on platforms where you can
be sure that a linker is always installed. I wouldn't like it,
however; what happens if the linker on the target platform is
not the same version as the one you used to test your code?
> Who said that C++ programs must be shipped as single monolithic black
> boxes that are always built for the "least common denominator"?
Nobody, but you'll have to admit that it's a lot easier to
deploy a single file than to require some complex installation
procedure.
> > and better knowledge
> > of the actual data being processed.
> This is a good point and it can be an important factor in those
> environment where the statistics of data cannot be foreseen or change
> dynamically. The it-depends mantra still holds, though.
Definitly. And I would repeat that in most cases, the
performance issues are secondary to many other issues.
--
James Kanze (GABI Software) email:james...@gmail.com
Conseils en informatique orientie objet/
Beratung in objektorientierter Datenverarbeitung
9 place Simard, 78210 St.-Cyr-l'Icole, France, +33 (0)1 30 23 00 34
--
> >> If the application makes intensive use of large arrays of basic
> >> types, and is suitably structured, Java will beat C++ easily;
> >> the lack of aliasing allows much greater optimization, at much
> >> less cost.
> > What do you mean by lack of aliasing?
> > What kind of optimization could Java do that C++ can't?
> I'm going to wait for James' answer on this one, but I believe a
> key detail in his answer was the "at much less cost" part; maybe
> a C++ compiler could do certain optimizations, but with much much
> more code analysis, for a particular situation; that simply means
> that either the compiler is more likely to have bugs, or simply
> that no compiler goes that far as to do those extremely complex
> optimizations.
Much less cost, to put it mildly. I believe that proving the
absense of aliasing is not computable in the general case; at
the very least, it is NP complete, which means not computable
for any reasonably sized program. (For some reasons, compiler
customers tend to object when compile times are measured in
centuries.)
It would be interesting to study whether the compiler could find
enough cases in reasonable time in typical programs to make it
worthwhile, but it would almost certainly require global
analysis; in Java, the compiler knows it immediately from the
function declaration: if the function declaration is:
void f( double a[], double b[] ) ;
Either a an b are the same array, or they don't overlap in any
way. And that's very important information for an optimizer.
(I've given a simple example in another posting.)
> Of course, maybe there are additional issues that I'm missing
> from James' comment (well, the fact that Java has always the
> entire program seems like another possible explanation for his
> comment --- if a compiler sees that a pointer to some data is
> being passed to a function which is in a separate translation
> unit, the best optimizer in the world pretty much has no choice
> but to assume that that pointer will be used, and the potential
> for optimization suffers; yes, maybe by flagging the condition
> in the object file, and having the linker do complete additional
> optimizations would solve that problem... But, really, at what
> cost?
Good optimizing C++ compilers today already generate something
along the lines of Java byte code, and defer actual code
generation to link time, using profiling information. Even with
information concerning the complete program, it's not usually
possible to exclude aliasing. In theory, at least, it would be
possible for the C++ compiler to generate two copies of the
loop, one supposing no aliasing, and another for the case where
some aliasing is present, then generate a test for aliasing to
choose which loop to use at run-time. I don't know of any
compiler which does this, however (although I have heard of a
compiler which does something similar for virtual functions).
Other than that, I don't think there is anyway to avoid the
extra cost.
--
James Kanze (GABI Software) email:james...@gmail.com
Conseils en informatique orientie objet/
Beratung in objektorientierter Datenverarbeitung
9 place Simard, 78210 St.-Cyr-l'Icole, France, +33 (0)1 30 23 00 34
Maciej Sobczak escreveu:
> James Kanze wrote:
>
>> VM:
>> Knowledge of the exact target machine
>
> What's the problem in compiling the C++ program as a set of dynamically
> loadable modules (at least for the time-critical parts)
This remembers me of IBM's FDPR:
http://www.research.ibm.com/haifa/projects/systems/cot/fdpr/index.html
Not as good as a JIT (the optimization is still done offline), but more
practical than recompiling-relinking.
- --
Daniel K. O.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.5 (GNU/Linux)
Comment: Using GnuPG with Mandriva - http://enigmail.mozdev.org
iD8DBQFFsPX4vPtRJCx0eNoRAndFAKC9xyqQT3RPENphIJjcC+k3aerXqQCbBWcH
UvRaVWD2qM29MfufoksTQMc=
=5nWH
-----END PGP SIGNATURE-----
--
Actually IMHO such raw speed tests are rather naive way of comparing
performance.
VMs will always incur a runtime overhead. The plus side however should
not be overlooked.
Performance can be achieved by dynamic optmizations of generated code.
So we should consider aspects which can be optimized and can be made
better and better.
What are the % of factors which the runtime cannot optmize much?.
Do these factors represent a large fraction of the code base?.
If yes Java will be poor else C++ will be poor.
As has been pointed out before, a VM can always fold a loop and make it
run faster.
> In the end, I think it comes down to something I said in another
> thread: Java is a highly specialized language, where as C++ is
> general purpose. If your application corresponds to the
> specialization, it's probable that Java would be the better
> solution.
Thats interesting... i would have said Java is more general and with C++
you can be more specialized. What particular specialization do you
see Java as fulfilling?
> (Java is particularly
> inappropriate for large scale projects; even if it were twice as
> fast as C++ here---and it's not---, the development costs you'd
> save by using C++ would easily pay for the extra machines,
> network speed, etc.)
That is also unexpected and interesting to me. What particular reasons
could make Java inappropriate for large scale projects?
Thank you,
--
Ivan
http://www.0x4849.net
>> What's good on the java side (speedwise, at least) is that objects
>> are by default passed around as pointers, not as copies, but the same
>> can be arranged within C++ as well, it just requires a different
>> programming style.
>
> And without garbage collection, you still have added overhead
> (especially in a multithreaded environment) to ensure that the
> object eventually gets deleted. It's not accidental that people
> trying to show off the performance advantages of garbage
> collection tend to use multithreaded programs with lots of
> strings and substrings:-).
I bet. At least, it's "one headache less". Yes, one can manage that,
but it's quite some juggling. However, for my problem domain
it is even "the less you have to allocate objects, the better"
as it keeps data locally within the processor cache. It's more
about "recycling" rather than "garbage collection". If you recycle
right away at home, nobody has to pick up the trash. (-:
>> And, whether any of these effects are dominant in your problem domain is
>> of course a question you can only answer by experimenting on realistic
>> data.
>
>> My personal problem domain is image procession, and this requires a lot
>> of data-shuffling and signal processing. Array bounds checking in java
>> (despite all claims of JIT optimizations) cause a slowdown here by about
>> a factor of two to three (no kidding), at least for java 1.4 back when I
>> checked it. You might get different figures nowadays.
>
> I would imagine that aliasing would make C++ optimizers much
> less efficient than Java for this sort of application. Unless,
> of course, your arrays are of Pixel { int red, blue, green ; },
> or something like that. In which case, it's likely that the
> slowdown is due to the extra indirections and allocations, and
> the loss of locality, rather than bounds checking.
No, nothing like that. Just "arrays". It is very efficient to handle
these with pointers in C++, which translate directly to register
access on the machine level. That's harder if all you have is an
array an an index, which at least requires an optimizer to eliminate
one addition (base + offset) and one check (offset in range).
Interestingly, aliasing has never really been a problem here, but
that's likely due to the type of operations performed on the data.
Fetch three data items, compute, write back to memory, increment
pointers.
In principle, a compiler could be able to vectorize this type of
operation, but I haven't found one that really did. My compiler
(g++) offers the C99 extension of "restricted" pointers in C++ as
well, but that didn't change the situation. You can, however, vectorize
manually which does quite a difference.
IOW, to be really fast, it requires "low level techniques", at
least currently, and things like that aren't available for Java.
If you need to shuffle bits around fast, "dirty C++ code" is hard
to beat (and hard to read, too). But I doubt that this translates
easily to other domains.
So long,
Thomas
Hi!
James Kanze wrote:
>> This is a good point and it can be an important factor in those
>> environment where the statistics of data cannot be foreseen or change
>> dynamically. The it-depends mantra still holds, though.
>
> Definitly. And I would repeat that in most cases, the
> performance issues are secondary to many other issues.
So why do you spending so much time for advocating JVM's performance?
Do not forget to tell that you have in mind IBM's JVM, because it is faster
than SUN's one.
Do not forget that Jamaica JVM is a Real-Time JVM, and it works fine, but I
do not understand why in critical applications still uses C/C++, Fortran
and Ada, but none want to use JVM and why if it is so fast, fully equipped
JBoss serwer can starts several hours. And at the end why there is no real
JVM for DSP processors. However there is one small JVM for Xilinx FPGA, but
except scientific tasks none want to use it in critical applications. And
at the end compare portabilities between all that JVM's - i mean if your
code will everywhere works?
Regards.
--
|\/\/| Seweryn Habdank-Wojewódzki
`\/\/'
> From what I remember, one of the steps in Oracle installation is to run
> the linker on the machine where the software is being installed - that's
> a perfect opportunity to select optimal pieces based on the target
> environment.
I never understood why not all proprietary programs distributed for
linux do that.
This is basically the best way to support all distributions for example.
And if you use LGPL-licensed libraries, you need to do that anyway or
load them at runtime.
--
> (For some reasons, compiler
> customers tend to object when compile times are measured in
> centuries.)
Naahhh... Maybe for developers like you, who apparently have
the bad habit of telling their customers those unnecessary
pieces of information that they won't even understand ;-)
Good developers simply tell their customers "don't worry, this
thing will rock!!"
:-)
Carlos
--
> void f( double a[], double b[] ) ;
>
> Either a an b are the same array, or they don't overlap in any
> way. And that's very important information for an optimizer.
> (I've given a simple example in another posting.)
void f(std::vector<double>& a, std::vector<double>& b);
basically gaves the same guarantees.
While std::vector is not a construct of the language, it is part of the
standard library, so the compiler could know about it.
> > void f( double a[], double b[] ) ;
> > Either a an b are the same array, or they don't overlap in any
> > way. And that's very important information for an optimizer.
> > (I've given a simple example in another posting.)
> void f(std::vector<double>& a, std::vector<double>& b);
> basically gaves the same guarantees.
You know that, and I know it, but does the compiler know?
> While std::vector is not a construct of the language, it is part of the
> standard library, so the compiler could know about it.
It could. It's even possible that the compiler analyse the
code enough to deduct that the internal pointers of std::vector
all originate as the return value of an operator new, and that
they are guaranteed not to overlap for that reason (and operator
new, of course, is part of the basic language).
In practice, however, where are we? (It's an interesting
observation, however---logically, it means that for some
programs, at least, using std::vector should, or at least could,
result in faster code than using C style arrays.)
--
James Kanze (Gabi Software) email: james...@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
My reason for commenting directly here rather than to my fellow
moderators is that I would not like to see the above go without public
comment.
--
Francis Glassborow ACCU
Author of 'You Can Do It!' and "You Can Program in C++"
see http://www.spellen.org/youcandoit
For project ideas and contributions:
http://www.spellen.org/youcandoit/projects
> > In the end, I think it comes down to something I said in another
> > thread: Java is a highly specialized language, where as C++ is
> > general purpose. If your application corresponds to the
> > specialization, it's probable that Java would be the better
> > solution.
> Thats interesting... i would have said Java is more general and with C++
> you can be more specialized.
In any given application, you can specialize C++ as much as you
want.
> What particular specialization do you
> see Java as fulfilling?
It tends to work well for small, high level applications which
are highly concerned with user presentation, but where absolute
reliability and robustness aren't necessarily issues.
> > (Java is particularly
> > inappropriate for large scale projects; even if it were twice as
> > fast as C++ here---and it's not---, the development costs you'd
> > save by using C++ would easily pay for the extra machines,
> > network speed, etc.)
> That is also unexpected and interesting to me. What particular reasons
> could make Java inappropriate for large scale projects?
The fact that you cannot separate the external specification of
the class and its implementation into separate files is almost a
killer. (The C++ solution here---header files, with textual
inclusion---is probably about the worst one you could think of,
but it's better than no solution, and with a bit of discipline,
works.) Trying to do any form of programming by contract tends
to be difficult as well---it requires using abstract classes
instead of interfaces, which in turn means that you cannot use
multiple inheritance.
The problem with Java is that it takes a particular development
model and programming paradigm, and elevates them to the
position of a dogma. If the development model is appropriate to
your application, and you don't need any other paradigms, then
Java is probably a better choice than C++, because you get
exactly what you need by default. If the development model
isn't appropriate (and it isn't for large projects, nor for
projects where reliability is an issue), or you need other
paradigms (and it's rare not to need more than one paradigm in a
large application), then you have a problem, because Java more
or less imposes its dogma. C++ sometimes frustrates me, because
all development models and all paradigms need some extra work up
front, but once you've done that work, they're there, and I've
yet to encounter a development model or a paradigm that I
couldn't make work in C++.
--
James Kanze (Gabi Software) email: james...@gmail.com
Conseils en informatique orientie objet/
Beratung in objektorientierter Datenverarbeitung
9 place Simard, 78210 St.-Cyr-l'Icole, France, +33 (0)1 30 23 00 34
--
> AFAIK neither JVM nor free()/delete will return pages to the OS once
> the temporary high-water mark has been passed. The JVM at least could
> in theory since it can relocate objects, a common practice in other
> garbage-collected languages.
I don't see any reason why free()/delete can't return the memory to the
OS, too. In fact that's what I expect if I'm working in an environment
with more or less severe memory constraints.
The reason it's often not done has more to do with performance than
anything else - the general memory allocation schemes you find in most
runtime libraries these days are implemented for the average case with
frequent allocation/deallocation/reallocation cycles. So the assumption
is that the memory requested from the OS will probably be reused sooner
or later and thus it would be more costly to return it to the OS and
re-request it at a later stage.
This is of course a rather fatal assumption if you're running on an
embedded system with a huge 64k's worth of RAM.
--
The lone C++ coder's blog: http://www.bsdninjas.co.uk/codeblog/
> >> This is a good point and it can be an important factor in those
> >> environment where the statistics of data cannot be foreseen or change
> >> dynamically. The it-depends mantra still holds, though.
> > Definitly. And I would repeat that in most cases, the
> > performance issues are secondary to many other issues.
> So why do you spending so much time for advocating JVM's performance?
I don't. I simply correct the mistaken view that C++ is
necessarily faster than Java in all cases, because Java uses a
VM, and C++ doesn't. (Formally, this isn't even a relevant
argument, because the Java specification allows for full static
compilation, and the C++ specification certainly doesn't forbid
the use of a VM.)
Typically, of course, the choice of whether to use a VM or
something statically compiled is made for reasons totally
unrelated to performance.
--
James Kanze (Gabi Software) email: james...@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
--
> James Kanze wrote:
>
> > If the application makes intensive use of large arrays of basic
> > types, and is suitably structured, Java will beat C++ easily;
> > the lack of aliasing allows much greater optimization, at much
> > less cost.
>
> What do you mean by lack of aliasing?
For example, referring to the same object by a pointer and a "direct"
reference:
SomeObj my_obj;
DerivedFromSomeObj *other_obj = &my_obj;
--
The lone C++ coder's blog: http://www.bsdninjas.co.uk/codeblog/
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
Ok, that's comforting. I'm glad to know were are not alone
and that the problem may not be due solely to any lack of
skill on our part.
> > (No we do not have memory hogging nor file i/o problems
> > with our C++ apps. Occasional core dumps on the other
> > hand ... ;-)
>
> :-)
>
> In my business, furnishing wrong information, or failing
> to furnish complete information, is considered worse than
> a core dump. You know, the sort of thing that happens
> when you get a NullPointerException in the middle of
> Swing.
Completely agreed. Based on a previous post of yours I think
we are in the same business at the moment. And yes, in that
business a core (preferably as soon as possible) is much
better than, for example, sweeping the book due to a bad
price. Especially when you are setup to simply and easily
roll back to a previous stable version of the program.
Hmm ... this makes we wonder about bald pointers. Recently,
the use of bald pointers in some older code was actually
beneficial in a way. When an obscure and rare error caused
them to dangle, subsequent access rapidly cored allowing us
to detect and eliminate the problem. Had the authors used a
naive shared pointer the stale objects would have stayed
around supplying bad data for the life of the program.
Of course, a shared_ptr/weak_ptr idiom would probably have
been a good option. But, this makes we wonder about the Java
everything is a (naive) reference and we'll handle lifetime
for you. Unless you explicitly code an acquire/release idiom
(which is a bit of a pain without deterministic destructors)
then such stale object errors can easily go unnoticed for a
very long time.
Keith
--
I've asked the following a number of times in this group (you can find
it in the archives) and the answer has had much volume and little
clarity. One thing that I remember was something like "because Java does
not have private virtual functions".
To keep things on-topic, I'd suggest a head-to-head comparison of
large-project enabling/harming features of C++ and Java.
Andrei
--
> > So why do you spending so much time for advocating JVM's performance?
>
> I don't. I simply correct the mistaken view that C++ is
> necessarily faster than Java in all cases, because Java uses a
> VM, and C++ doesn't. (Formally, this isn't even a relevant
> argument, because the Java specification allows for full static
> compilation, and the C++ specification certainly doesn't forbid
> the use of a VM.)
Java and C++ should be about equal in performance in a fair benchmark.
Unfortunately, most real C++ code that is performance sensitive is
unfair. It can go outside the C abstract machine by using, for example,
_m_paddusb in a few key places. :-)
Obviously. That is one of reasons there is nothing else than
deterministic behaviour based on constructors and destructors. Code is
exception safe without effort. Code does not leak resources without
effort. And it is a fraction of source lines of any other solution.
Sounds like win-win-win situation to me ;)
> However, I don't even see constructors and destructors.
Why should you see them? It is something that compiler and the library
should do for you.
> I only see a
> pointer (!!! what an evil thing!) being passed to some function.
The pointer does not represent ownership, therefore has nothing to do
with exception safety. The only bad thing that could happen is
dangling, but library design makes it unlikely.
> >> (For some reasons, compiler
> >> customers tend to object when compile times are measured in
> >> centuries.)
> >Naahhh... Maybe for developers like you, who apparently have
> >the bad habit of telling their customers those unnecessary
> >pieces of information that they won't even understand ;-)
> >Good developers simply tell their customers "don't worry, this
> >thing will rock!!"
> >:-)
> While I am certain that neither of the two in this dialog will start a
> flame war, and actually have a degree of respect for each other, I am
> far from happy that this should have passed moderation. The intended
> humour would easily be missed by many readers and it sets a bad example.
I'm afraid I don't see how it could be interpreted as anything
but a joke. Even without the smileys, I would have understood
it as such. I rather appreciated it, in fact, for lightening up
the thread.
--
James Kanze (Gabi Software) email: james...@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
--
[...]
> > In my business, furnishing wrong information, or failing
> > to furnish complete information, is considered worse than
> > a core dump. You know, the sort of thing that happens
> > when you get a NullPointerException in the middle of
> > Swing.
> Completely agreed. Based on a previous post of yours I think
> we are in the same business at the moment. And yes, in that
> business a core (preferably as soon as possible) is much
> better than, for example, sweeping the book due to a bad
> price. Especially when you are setup to simply and easily
> roll back to a previous stable version of the program.
Note that this is true for a lot of application domains.
Realistically, all applications must be able to live with a core
dump, because realistically, there's no way to guarantee 100%
that you won't get one. Critical applications must have some
sort of backup system, and triggering a core dump is often the
fastest way of triggering the back-up system to take over.
> Hmm ... this makes we wonder about bald pointers. Recently,
> the use of bald pointers in some older code was actually
> beneficial in a way. When an obscure and rare error caused
> them to dangle, subsequent access rapidly cored allowing us
> to detect and eliminate the problem.
The problem with such things is not that a dangling pointer
might core dump, but that such a core dump is not guaranteed.
It could also result in simply changing some data elsewhere.
> Had the authors used a
> naive shared pointer the stale objects would have stayed
> around supplying bad data for the life of the program.
Reproduceably supplying bad data:-).
This is, IMHO, one of the advantages of using classes instead of
simple structs. The stale object can set a flag, which it tests
when asked for the data. (If the test is in the form of an
assert, you've get the core dump, as above. But guaranteed.)
> Of course, a shared_ptr/weak_ptr idiom would probably have
> been a good option. But, this makes we wonder about the Java
> everything is a (naive) reference and we'll handle lifetime
> for you.
That's a misconception concerning Java (admittedly brought on by
some of the Java advocacy literature). Java does nothing to
handle object lifetime. (What it does do, of course, is allow
you to write code to detect lifetime errors, and be sure it
works. But you get this in C++ too, at least if you're using
the Boehm collector to handle memory management, so that you are
sure that the memory won't be recycled until there are no more
pointers to it.)
> Unless you explicitly code an acquire/release idiom
> (which is a bit of a pain without deterministic destructors)
> then such stale object errors can easily go unnoticed for a
> very long time.
Acquire/release doesn't have to be associated with destructors.
Associating it with destructors is really only an advantage when
objects have lifetimes known to the compiler, so the compiler
can implicitly call the destructor at the right time. Once the
object has been allocated dynamically, it's up to the
programmer, and it doesn't really matter whether you use
destructors (with a special syntax, e.g. delete, to call them),
or whether you use some other named function. (The problem with
Java here, of course, is that there are no objects for which the
compiler knows the lifetime.)
--
James Kanze (Gabi Software) email: james...@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
> [...]
>>>Either a an b are the same array, or they don't overlap in any
>>>way. And that's very important information for an optimizer.
>>>(I've given a simple example in another posting.)
>
>>void f(std::vector<double>& a, std::vector<double>& b);
>>basically gaves the same guarantees.
>
> You know that, and I know it, but does the compiler know?
I think Mathias did answer that question, right below:
>>While std::vector is not a construct of the language, it is part of the
>>standard library, so the compiler could know about it.
> It could. It's even possible that the compiler analyse the
> code enough to deduct [...]
I think Mathias' point was strong enough --- the compiler
could, and IMO *should* make that assumption up front;
std::vector can only be what the language specifies it to
be; now, the thing is, is the guarantee that they're either
the same, or entirely non-overlapping blocks, given explicitly,
or is it rather a "side-effect" of the *typical* way in which
it is implemented?
Perhaps the fact that in the original specification, storage
wasn't even required to be contiguous, I guess the guarantee
of entirely non-overlapping would be hard to deduce as being
a direct consequence of the vector's specifications.
> In practice, however, where are we? (It's an interesting
> observation, however---logically, it means that for some
> programs, at least, using std::vector should, or at least could,
> result in faster code than using C style arrays.)
We do have some programs that, at least under certain
conditions, are faster when using vectors --- such is the
case with vectors of vectors, when the dimension of the
rows is not a power of 2 --- for C arrays, a "non-trivial"
multiplication is required, whereas for vectors of vectors,
two dereferences and a trivial multiplication (a two-bit
shift) does it (and does it faster, at least for the one
test that I did a while ago --- vector of vectors was
almost twice as fast as the C-arrays version.
As you put it, it's interesting --- to say the least!
Carlos
--
> > AFAIK neither JVM nor free()/delete will return pages to the OS once
> > the temporary high-water mark has been passed. The JVM at least could
> > in theory since it can relocate objects, a common practice in other
> > garbage-collected languages.
> I don't see any reason why free()/delete can't return the memory to the
> OS, too. In fact that's what I expect if I'm working in an environment
> with more or less severe memory constraints.
> The reason it's often not done has more to do with performance than
> anything else - the general memory allocation schemes you find in most
> runtime libraries these days are implemented for the average case with
> frequent allocation/deallocation/reallocation cycles. So the assumption
> is that the memory requested from the OS will probably be reused sooner
> or later and thus it would be more costly to return it to the OS and
> re-request it at a later stage.
I think that the dominating consideration is the supposition
that allocating and freeing at the system level is expensive.
So the allocator doesn't go to the system for each individual
allocation; it grabs a lot, and then parcels it out. Which, of
course, makes returning the memory to the system very difficult;
you can only do so when all of the blocks you have parcelled out
have been freed.
Note too that early Unix (where C/C++ come from) only maintained
a top of heap pointer for each process. To return memory to the
system, all memory following the address being freed had to be
free.
> This is of course a rather fatal assumption if you're running on an
> embedded system with a huge 64k's worth of RAM.
In such cases, the best solution is probably to map malloc and
free directly to system requests.
--
James Kanze (Gabi Software) email: james...@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
--
>The fact that you cannot separate the external specification of
>the class and its implementation into separate files is almost a
>killer. (The C++ solution here---header files, with textual
>inclusion---is probably about the worst one you could think of,
>but it's better than no solution, and with a bit of discipline,
>works.) Trying to do any form of programming by contract tends
>to be difficult as well---it requires using abstract classes
>instead of interfaces, which in turn means that you cannot use
>multiple inheritance.
I had to cope with a *little* Java application a while ago and the
feature I missed most was the lack of deterministic destruction. It
may be just me, and my ignorance of the language idioms, but I found
robust resource management to be pretty much impossible.
Genny.
It can't be quite the killer you make it out to be, because as I'm sure
you're aware, large classes of enterprise software have migrated from
C++ to Java over the years. For example, the older C++ trading
systems, such as Infinity and Summit, are being displaced by Java
systems, such as Murex and Calypso. The same goes for broad classes of
enterprise software in the areas of workflow, business process
management, telco provisioning, payment systems, and so on. Grid
computing is widely adopted in Java enterprise apps as well.
> (The C++ solution here---header files, with textual
> inclusion---is probably about the worst one you could think of,
> but it's better than no solution, and with a bit of discipline,
> works.)
I think that many of us who moved away from C++ programming don't
really miss C++ header files that much :-)
> Trying to do any form of programming by contract tends
> to be difficult as well---it requires using abstract classes
> instead of interfaces, which in turn means that you cannot use
> multiple inheritance.
>
Which doesn't seem to be killer either.
The fact is, a lot of mainstream enterprise development has moved away
from C++, and it isn't coming back. That also has implications for
what does and does not make sense in charting the future of C++.
Daniel
Then I'll limit my claim to "real" OSes, which allocate memory to a
process in such a way that it isn't returnable, ie because it is in
large chunks not related to the application's allocation requests.
If you're not using separate address spaces then you are free to share
a heap amd get the reuse you want, writing your own malloc if necessary.
--
> Then I'll limit my claim to "real" OSes, which allocate memory to a
> process in such a way that it isn't returnable, ie because it is in
> large chunks not related to the application's allocation requests.
It is returnable and in fact, it is not even that much complicated.
My win32 apps do return memory to OS. My POSIX apps do not, but that is
just because I was too lazy to implement the feature ;)
Of course, another thing to consider is performance, that is why I am
using explicit function to do so. E.g. I return the memory to OS when
closing a file.
All "real" OSes have API that provides you page size chunks of memory
(usually 4KB) (VirtualAlloc in Win32, mmap in POSIX) and part of the
API are functions to return pages to system (VirtualFree/munmap).
Mirek
> Timo Geusch wrote:
> > Robert Mabee wrote:
> > > AFAIK neither JVM nor free()/delete will return pages to the OS
> > > once the temporary high-water mark has been passed. The JVM at
> > > least could in theory since it can relocate objects, a common
> > > practice in other garbage-collected languages.
> >
> > I don't see any reason why free()/delete can't return the memory to
> > the OS, too. In fact that's what I expect if I'm working in an
> > environment with more or less severe memory constraints.
>
> Then I'll limit my claim to "real" OSes, which allocate memory to a
> process in such a way that it isn't returnable, ie because it is in
> large chunks not related to the application's allocation requests.
Sorry, could you provide a couple of pointers where you got the
information from that memory from the OS tends to be allocated in a
non-returnable fashion in "real OSs"?
My understanding of most system allocation schemes is that your heap
mangement requests memory at the page lavel, for example 4k on an x86
running in "4G protected" mode. As long as you ensure that the whole
page is unused, you can just chuck it back at the OS.
In fact, schemes like the overcommiting virtual memory subsystem on
Linux do depend on this to a certain extent _if_ you actually used the
commited memory...
> If you're not using separate address spaces then you are free to share
> a heap amd get the reuse you want, writing your own malloc if
> necessary.
Care to enlighten me regarding this statement? The returnability of
memory doesn't have anything to do with the separation of address
spaces IMHO.
--
The lone C++ coder's blog: http://www.bsdninjas.co.uk/codeblog/
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
> > > So why do you spending so much time for advocating JVM's performance?
> > I don't. I simply correct the mistaken view that C++ is
> > necessarily faster than Java in all cases, because Java uses a
> > VM, and C++ doesn't. (Formally, this isn't even a relevant
> > argument, because the Java specification allows for full static
> > compilation, and the C++ specification certainly doesn't forbid
> > the use of a VM.)
> Java and C++ should be about equal in performance in a fair benchmark.
> Unfortunately, most real C++ code that is performance sensitive is
> unfair. It can go outside the C abstract machine by using, for example,
> _m_paddusb in a few key places. :-)
I suspect that in a performance sensitive application, where you
invest the man/months necessary to get the maximum performance,
C++ will generally be faster, simply because it offers more
alternatives to experiment with. More importantly, IMHO, the
techniques necessary to get maximum performance from Java (using
arrays of basic types, to avoid the extra allocations and
indirection) break encapsulation.
--
James Kanze (GABI Software) email:james...@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
--
> Java and C++ should be about equal in performance in a fair benchmark.
> Unfortunately, most real C++ code that is performance sensitive is
> unfair. It can go outside the C abstract machine by using, for example,
> _m_paddusb in a few key places. :-)
I wouldn't say it's unfair. It shows that there are broader optimization
techniques available to C++ programmer than to Java programmer. And
it's not just about full access to the underlying platform. In Java you
won't see a custom string class or a different memory manager. In C++ it's
common.
> The fact is, a lot of mainstream enterprise development has moved away
> from C++, and it isn't coming back. That also has implications for
> what does and does not make sense in charting the future of C++.
Yes, but not necessarily for reasons of technical excellence of
whatever technology/language the development moved to. I'm not a big
fan of using C++ for everything up to and including a job that a shell
script could do ten times better but some of these decisions seem to
have been made more for political and CV-massaging reasons than
anything else.
--
The lone C++ coder's blog: http://www.bsdninjas.co.uk/codeblog/
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
> >The fact that you cannot separate the external specification of
> >the class and its implementation into separate files is almost a
> >killer. (The C++ solution here---header files, with textual
> >inclusion---is probably about the worst one you could think of,
> >but it's better than no solution, and with a bit of discipline,
> >works.) Trying to do any form of programming by contract tends
> >to be difficult as well---it requires using abstract classes
> >instead of interfaces, which in turn means that you cannot use
> >multiple inheritance.
> I had to cope with a *little* Java application a while ago and the
> feature I missed most was the lack of deterministic destruction. It
> may be just me, and my ignorance of the language idioms, but I found
> robust resource management to be pretty much impossible.
It depends. I did one fairly larger Java application, and we
found it trivial: the solution was never to allocate any
resources except memory or locks (both of which are handled by
the language):-). (We also had one socket connection, to the
server, but it was active for the life of the program.)
Seriously, in a small application, with only one or two
programmers, it shouldn't be too much of a problem; the problem
occurs in larger applications, where you have to communicate to
your users that they need a finally block. In commercial
applications like those I've done recently, there aren't that
many external resources that need freeing on leaving scope (and
in other cases, you need explicit code in C++ as well); it's
something extra that you definitly need to check in code review,
but it's doable. But it still means extra work, and is another
reason why the language doesn't scale that well---the language
is not designed for use in large projects, where there are a
large number of programmers, and communications and work-flow
are important issues. (As is often the case in such cases, no
one problem is actually a killer---there are always
work-arounds---but the sum of them all definitly renders using
Java a more expensive proposition than using C++.)
--
James Kanze (GABI Software) email:james...@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
>>That is also unexpected and interesting to me. What particular reasons
>>could make Java inappropriate for large scale projects?
>
>
> The fact that you cannot separate the external specification of
> the class and its implementation into separate files is almost a
> killer. (The C++ solution here---header files, with textual
> inclusion---is probably about the worst one you could think of,
> but it's better than no solution, and with a bit of discipline,
> works.) Trying to do any form of programming by contract tends
> to be difficult as well---it requires using abstract classes
> instead of interfaces, which in turn means that you cannot use
> multiple inheritance.
Sorry, but I don't buy this. I would rather say it's the other
way around. In Java, if you want to have external specializations,
you write an interface and implement it by a class, and the
class is then the implementation. The interface makes no statements
on the internal workings of the code whatsoever and doesn't make
the internal state of the class visible. On C++, however, you
still have all "private" data readable (by the human) in the
header file, and it IMHO really shouldn't belong here, it's an
implementation detail. So likely, I think this is a
misunderstanding how to express the concepts within Java.
Of course, something the like can be arranged in C++ using the
pimpl idiom, but it requires additional work and is not expressed
in the syntax of the language itself.
> The problem with Java is that it takes a particular development
> model and programming paradigm, and elevates them to the
> position of a dogma. If the development model is appropriate to
> your application, and you don't need any other paradigms, then
> Java is probably a better choice than C++, because you get
> exactly what you need by default. If the development model
> isn't appropriate (and it isn't for large projects, nor for
> projects where reliability is an issue), or you need other
> paradigms (and it's rare not to need more than one paradigm in a
> large application), then you have a problem, because Java more
> or less imposes its dogma. C++ sometimes frustrates me, because
> all development models and all paradigms need some extra work up
> front, but once you've done that work, they're there, and I've
> yet to encounter a development model or a paradigm that I
> couldn't make work in C++.
That, however, I agree with.
What I - personally - consider most irritating in Java that you
do not have destructors, and thus cannot really release resources
at controlled times without writing additional code - it cannot
be expressed in Java. I'm also working here on a code using Corba
on the Java side, and now it's cluttered with "close()" methods
all over the place just to ensure that the Corba proxies are shutdown
early, with the result that you can have Zombie objects, etc.
So long,
Thomas
> Timo Geusch wrote:
> > The reason it's often not done has more to do with performance than
> > anything else - the general memory allocation schemes you find in
> > most runtime libraries these days are implemented for the average
> > case with frequent allocation/deallocation/reallocation cycles. So
> > the assumption is that the memory requested from the OS will
> > probably be reused sooner or later and thus it would be more costly
> > to return it to the OS and re-request it at a later stage.
>
> I think that the dominating consideration is the supposition
> that allocating and freeing at the system level is expensive.
That is also my understanding. Plus, not all OSs allow for for fast
allocation schemes for common-size objects (AFAIR the Windows heap
management does, but I don't think that any of the UNIX heap
managers/sbrk do), so if you want to take advantage of this
optimisation, you'll have to implement it on top of the OS mechanism.
> So the allocator doesn't go to the system for each individual
> allocation; it grabs a lot, and then parcels it out. Which, of
> course, makes returning the memory to the system very difficult;
> you can only do so when all of the blocks you have parcelled out
> have been freed.
Indeed.
> Note too that early Unix (where C/C++ come from) only maintained
> a top of heap pointer for each process. To return memory to the
> system, all memory following the address being freed had to be
> free.
Ewww. Do any systems still do that these days? I mean, apart from the
20-year old dusty UNIX box in the corner that everybody's too scared to
turn off or reboot?
> > This is of course a rather fatal assumption if you're running on an
> > embedded system with a huge 64k's worth of RAM.
>
> In such cases, the best solution is probably to map malloc and
> free directly to system requests.
Yup. What fun we had...
--
The lone C++ coder's blog: http://www.bsdninjas.co.uk/codeblog/
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
>> What's the problem in compiling the C++ program as a set of dynamically
>> loadable modules
> Issues of deployment and disk usage.
It's more deployment, I think. With DVD as an installation medium there
should be no problem with shipping duplicate copies of critical software
components, at least when it comes to volume. Note that we are talking
about *some* components, not whole programs (the 80/20 rule). Network
downloads are even easier.
>> From what I remember, one of the steps in Oracle installation is to run
>> the linker on the machine where the software is being installed - that's
>> a perfect opportunity to select optimal pieces based on the target
>> environment.
>
> That's possibly a workable solution on platforms where you can
> be sure that a linker is always installed.
Good point. Then let's not forget that shipping binaries is also a
deployment policy, not something that is mandated by the language.
Consider for example Linux (or alike) distributions, where literally
thousands of applications are distributed as source packages that can be
compiled at the target site, with all machine-specific optimizations
turned on, if only the user wishes so. It works, so is possible.
The fact that lots of software is distributed as binary monoliths is a
deployment strategy that has nothing to do with the language and is
usually a result of intellectual-property worries or such (still, there
is also "commercial" software distributed in source form, so there are
no strict rules). Comparing this deployment strategy directly to Java is
not fair, because Java programs are not distributed as binaries in the
C++ sense and the resulting intellectual property protection is different.
The real difference is that C++ applications are usually distributed in
the form that is determined by intellectual-property policies, whereas
Java apps are usually distributed in the form that is determined by
target JVM. I therefore see many more deployment choices for C++
applications, it's just the matter of statistics that not all options
are equally popular.
> I wouldn't like it,
> however; what happens if the linker on the target platform is
> not the same version as the one you used to test your code?
And what happens if the user has a different Windows Vista SP112 Home
SemiPro With Explorer But Without Media Player etc. combination than the
one you have tested? Linker variety is peanuts. :-)
That's still deployment issue, not the language. At the extreme you can
ship full sources and expect the user to compile them on his own.
> you'll have to admit that it's a lot easier to
> deploy a single file than to require some complex installation
> procedure.
On the system I use at home programs are usually deployed as single .tgz
files and the deployment is *a lot* easier than anything else I've seen
on other operating systems and with other deployment strategies.
Complex installation procedure is a system, not language issue.
(And the CLASSPATH hell in Java does not convince me either. ;-) )
> I would repeat that in most cases, the
> performance issues are secondary to many other issues.
Amen.
--
Maciej Sobczak : http://www.msobczak.com/
Programming : http://www.msobczak.com/prog/
> > [...]
> >>While std::vector is not a construct of the language, it is part of the
> >>standard library, so the compiler could know about it.
> > It could. It's even possible that the compiler analyse the
> > code enough to deduct [...]
> I think Mathias' point was strong enough --- the compiler
> could, and IMO *should* make that assumption up front;
> std::vector can only be what the language specifies it to
> be; now, the thing is, is the guarantee that they're either
> the same, or entirely non-overlapping blocks, given explicitly,
> or is it rather a "side-effect" of the *typical* way in which
> it is implemented?
I think there are a number of people who don't; who are of the
opinion that it should be possible to write the equivalent of
std::vector as a true user defined type, and attain the same
performance. IMHO: it's a noble goal, but until we are actually
there, I'd prefer getting the improved performace from
std::vector to not getting anywhere. On the other hand, there's
been a very strong demand (and maybe still is) that the user be
able to replace the library with another implementation. Which
limits what the compiler can "know".
At any rate, current compilers don't seem to use this
information.
> Perhaps the fact that in the original specification, storage
> wasn't even required to be contiguous, I guess the guarantee
> of entirely non-overlapping would be hard to deduce as being
> a direct consequence of the vector's specifications.
The standard very definitely requires, and has always required,
that a[i] and b[j] be distinct objects, for all a and b
different, and that regardless of the implementation.
> > In practice, however, where are we? (It's an interesting
> > observation, however---logically, it means that for some
> > programs, at least, using std::vector should, or at least could,
> > result in faster code than using C style arrays.)
> We do have some programs that, at least under certain
> conditions, are faster when using vectors --- such is the
> case with vectors of vectors, when the dimension of the
> rows is not a power of 2 --- for C arrays, a "non-trivial"
> multiplication is required, whereas for vectors of vectors,
> two dereferences and a trivial multiplication (a two-bit
> shift) does it (and does it faster, at least for the one
> test that I did a while ago --- vector of vectors was
> almost twice as fast as the C-arrays version.
Interesting. The cost of the multiplication is high enough to
offset the loss of locality and the extra indirection. Given
the importance of locality and the cost of memory accesses on
modern machines, I would not have expected this.
Given your results, I would not be too surprised if on some
machines, the C style array was also faster for "simple"
multiplications---things like a power of 2 +/- 1, which can
still be done by a shift and an add/sub., but slower for more
"exotic" values. And that which solution is faster for which
values changes from one machine to the next, depending on the
CPU implementation, clock speed, memory speed and cache.
--
James Kanze (GABI Software) email:james...@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
--
Deterministic destruction in Java isn't difficult. The pattern looks
something like this:
SomeType someType = null;
try {
someType = new SomeType();
// do some work
}
finally {
if (someType != null) {
someType.dispose();
someType = null;
}
}
I'll admit that it's less convenient than C++ objects created on the
stack:
{
SomeType someType;
// do some work
> Deterministic destruction in Java isn't difficult. The pattern looks
> something like this:
> SomeType someType = null;
> try {
> someType = new SomeType();
> // do some work
> }
> finally {
> if (someType != null) {
> someType.dispose();
> someType = null;
> }
> }
> I'll admit that it's less convenient than C++ objects created on the
> stack:
> {
> SomeType someType;
> // do some work
> }
The problem is not "convenience". The problem is that once a class
requires deterministic destruction, all other classes depending on
it or using it also need it. Thus - at least in my programs - I end
up requiring more or less a major fraction of classes somehow requiring
a "close" method. It really spoils the code base from "bottom up".
So long,
Thomas
> Deterministic destruction in Java isn't difficult. The pattern looks
> something like this:
>
> SomeType someType = null;
> try {
> someType = new SomeType();
> // do some work
> }
> finally {
> if (someType != null) {
> someType.dispose();
> someType = null;
> }
> }
>
> I'll admit that it's less convenient than C++ objects created on the
> stack:
>
> {
> SomeType someType;
> // do some work
> }
It's not just less convenient. It violates the time-honoured
principle "Once, and only once", and is therefore much more error-
prone and much less maintainable.
--
Gerhard Menzl
Non-spammers may respond to my email address, which is composed of my
full name, separated by a dot, followed by at, followed by "fwz",
followed by a dot, followed by "aero".
> > Timo Geusch wrote:
> > > Robert Mabee wrote:
> > > > AFAIK neither JVM nor free()/delete will return pages to the OS
> > > > once the temporary high-water mark has been passed. The JVM at
> > > > least could in theory since it can relocate objects, a common
> > > > practice in other garbage-collected languages.
> > > I don't see any reason why free()/delete can't return the memory to
> > > the OS, too. In fact that's what I expect if I'm working in an
> > > environment with more or less severe memory constraints.
> > Then I'll limit my claim to "real" OSes, which allocate memory to a
> > process in such a way that it isn't returnable, ie because it is in
> > large chunks not related to the application's allocation requests.
> Sorry, could you provide a couple of pointers where you got the
> information from that memory from the OS tends to be allocated in a
> non-returnable fashion in "real OSs"?
Probably hard experience. It's hard to imagine any modern
system allocating other than pages, which are "large chunks not
related to the application's allocation requests."
> My understanding of most system allocation schemes is that your heap
> mangement requests memory at the page lavel, for example 4k on an x86
> running in "4G protected" mode.
I suspect that most heap mangement implementations request
memory in far larger chunks, because system calls are (or are
perceived as being) expensive.
> As long as you ensure that the whole
> page is unused, you can just chuck it back at the OS.
And how do you do ensure that the whole page is unused?
> In fact, schemes like the overcommiting virtual memory subsystem on
> Linux do depend on this to a certain extent _if_ you actually used the
> commited memory...
I don't understand this. Overcommitting has just the opposite
effect; it only works when you allocate very large blocks, which
means more or less that you cannot return them.
--
James Kanze (GABI Software) email:james...@gmail.com
Conseils en informatique orientie objet/
Beratung in objektorientierter Datenverarbeitung
9 place Simard, 78210 St.-Cyr-l'Icole, France, +33 (0)1 30 23 00 34
--
> > Note too that early Unix (where C/C++ come from) only maintained
> > a top of heap pointer for each process. To return memory to the
> > system, all memory following the address being freed had to be
> > free.
> Ewww. Do any systems still do that these days? I mean, apart from the
> 20-year old dusty UNIX box in the corner that everybody's too scared to
> turn off or reboot?
Who knows? The usual alternative with modern Unix is mmep,
which requires an open file descriptor per allocated block, so
you're not exactly going to want to use it for each user level
allocation either.
--
James Kanze (GABI Software) email:james...@gmail.com
Conseils en informatique orientie objet/
Beratung in objektorientierter Datenverarbeitung
9 place Simard, 78210 St.-Cyr-l'Icole, France, +33 (0)1 30 23 00 34
--
> >>That is also unexpected and interesting to me. What particular reasons
> >>could make Java inappropriate for large scale projects?
> > The fact that you cannot separate the external specification of
> > the class and its implementation into separate files is almost a
> > killer. (The C++ solution here---header files, with textual
> > inclusion---is probably about the worst one you could think of,
> > but it's better than no solution, and with a bit of discipline,
> > works.) Trying to do any form of programming by contract tends
> > to be difficult as well---it requires using abstract classes
> > instead of interfaces, which in turn means that you cannot use
> > multiple inheritance.
> Sorry, but I don't buy this. I would rather say it's the other
> way around. In Java, if you want to have external specializations,
> you write an interface and implement it by a class, and the
> class is then the implementation.
That's the usual work-around, but there are things that you can
do with a class, like create instances, that you cannot do with
an interface.
> The interface makes no statements
> on the internal workings of the code whatsoever and doesn't make
> the internal state of the class visible. On C++, however, you
> still have all "private" data readable (by the human) in the
> header file, and it IMHO really shouldn't belong here, it's an
> implementation detail.
Which is a serious (and known) flaw in the C++ model; in
practice, at the application level, we use the compilation
firewall idiom a lot because of it.
> So likely, I think this is a
> misunderstanding how to express the concepts within Java.
There is a definite difference: in C++, I can define a class,
without implementing it. Other people can then write code
against that definition, and compile their code, effectivelly
working in parallel with me while I implement the class.
In Java, I have to define an interface. Other people cannot
write all of their code against it, since they cannot write
anything which creates an instance of it. They have to wait
until I've finished the implementation of the actual class.
> Of course, something the like can be arranged in C++ using the
> pimpl idiom, but it requires additional work and is not expressed
> in the syntax of the language itself.
And in Java, it cannot even be arranged.
[...]
> What I - personally - consider most irritating in Java that you
> do not have destructors, and thus cannot really release resources
> at controlled times without writing additional code - it cannot
> be expressed in Java.
You have to write the additional code in C++ as well, the
destructor:-). The problem isn't that you, as author of the
class, has to write additional code; the problem is that every
single one of your users will have to write additional code, at
the site of use. And that's very error prone.
I agree that its a serious drawback in Java. One could argue
that it affects large projects more, since it increases the
communications burden; I didn't mention it, because I find that
it also affects even small projects negatively.
> I'm also working here on a code using Corba
> on the Java side, and now it's cluttered with "close()" methods
> all over the place just to ensure that the Corba proxies are shutdown
> early, with the result that you can have Zombie objects, etc.
Not to mention that the lack of out parameters means a lot of
extra proxy objects.
--
James Kanze (GABI Software) email:james...@gmail.com
Conseils en informatique orientie objet/
Beratung in objektorientierter Datenverarbeitung
9 place Simard, 78210 St.-Cyr-l'Icole, France, +33 (0)1 30 23 00 34
--
> > My understanding of most system allocation schemes is that your heap
> > mangement requests memory at the page lavel, for example 4k on an x86
> > running in "4G protected" mode.
>
> I suspect that most heap mangement implementations request
> memory in far larger chunks, because system calls are (or are
> perceived as being) expensive.
4KB is quite a long chunk of memory, and OS response is not that tragic
in this case.
> > As long as you ensure that the whole
> > page is unused, you can just chuck it back at the OS.
>
> And how do you do ensure that the whole page is unused?
That is the job of memory allocator. Some effective memory allocation
schemes naturally produce empty 4KB pages. See e.g. memory management
subsystem of Boehm's GC, Hoard or U++ allocator.
Mirek
>>I think Mathias' point was strong enough --- the compiler
>>could, and IMO *should* make that assumption up front;
>>std::vector can only be what the language specifies it to
>>be; now, the thing is, is the guarantee that they're either
>>the same, or entirely non-overlapping blocks, given explicitly,
>>or is it rather a "side-effect" of the *typical* way in which
>>it is implemented?
>
> I think there are a number of people who don't; who are of the
> opinion that it should be possible to write the equivalent of
> std::vector as a true user defined type [...]
> On the other hand, there's
> been a very strong demand (and maybe still is) that the user be
> able to replace the library with another implementation. Which
> limits what the compiler can "know".
Wait! Two things: 1) std::vector *is* a user-defined type.
That was just a "nit pick" --- the important point is 2)
std::vector is a user-defined type that must follow certain
specifications that the compiler *know* about.
The compiler can make any assumptions that follow from the
Standard specification of std::vector, and if those
assumptions happen to be false, then it would be up to the
user to replace the defective STL implementation.
> At any rate, current compilers don't seem to use this
> information.
Ok, good point. Still, the discussion was fun while it
lasted, no? :-)
>>We do have some programs that, at least under certain
>>conditions, are faster when using vectors --- such is the
>>case with vectors of vectors, when the dimension of the
>>rows is not a power of 2 --- for C arrays, a "non-trivial"
>>multiplication is required, whereas for vectors of vectors,
>>two dereferences and a trivial multiplication (a two-bit
>>shift) does it (and does it faster, at least for the one
>>test that I did a while ago --- vector of vectors was
>>almost twice as fast as the C-arrays version.
>
> Interesting. The cost of the multiplication is high enough to
> offset the loss of locality and the extra indirection. Given
> the importance of locality and the cost of memory accesses on
> modern machines, I would not have expected this.
>
> Given your results, I would not be too surprised if on some
> machines, the C style array was also faster for "simple"
> multiplications---things like a power of 2 +/- 1, which can
> still be done by a shift and an add/sub., but slower for more
> "exotic" values.
That was the case when I did the test (which was on Linux,
with g++, not sure which version, but maybe some time around
version 3.2 or 3.3, on an Athlon XP processor).
C arrays of the form a[N][32] or [N][64], etc. were faster
(don't remember by how much), but precisely, something of
the form a[N][100] was close to twice slower than
vector< vector<T> > a (N, 100).
> And that which solution is faster for which
> values changes from one machine to the next, depending on the
> CPU implementation, clock speed, memory speed and cache.
Absolutely. I was always aware of this "caveat" in the
results of my tests --- but they're sill perfect to contest
the argument that particular language features necessarily
lead to a product with a final, effectove speed that is
superior to X other alternative. (there may be cases where
it's true, but it's perhaps surprising how little often that
is the case)
Carlos
--
The OS requirements like page alignment won't generally fit well with
the accidental allocation patterns of the application, making it rare
for the general free() to find a returnable page, so the author won't
write the code to detect such a rare case.
>>If you're not using separate address spaces then you are free to share
>>a heap amd get the reuse you want, writing your own malloc if
>>necessary.
>
> Care to enlighten me regarding this statement? The returnability of
> memory doesn't have anything to do with the separation of address
> spaces IMHO.
You can't share a heap between processes if it isn't in the address
space of both. This would only be reasonable in the single-address-
space OS which a prior poster brought up. The page boundaries no
longer intrude because they are not used for access control.
--
This does not make sense. Separating interface and specification in Java
is easy and idiomatic. The fact that you can do it in a different way
(e.g. use a class instead of an interface + class) is no news, because
in C++ you can also do things a lot of different ways. So this part of
the answer I consider unconvincing.
> The problem with Java is that it takes a particular development
> model and programming paradigm, and elevates them to the
> position of a dogma. If the development model is appropriate to
> your application, and you don't need any other paradigms, then
> Java is probably a better choice than C++, because you get
> exactly what you need by default. If the development model
> isn't appropriate (and it isn't for large projects, nor for
> projects where reliability is an issue), or you need other
> paradigms (and it's rare not to need more than one paradigm in a
> large application), then you have a problem, because Java more
> or less imposes its dogma. C++ sometimes frustrates me, because
> all development models and all paradigms need some extra work up
> front, but once you've done that work, they're there, and I've
> yet to encounter a development model or a paradigm that I
> couldn't make work in C++.
This part of the answer assumes its own conclusion. The question was,
what in Java affects robustness in large projects, particularly when
compared to C++? The answer gave some nice prose about Java being too
dogmatic, and then went on saying that "the development model isn't
appropriate (and it isn't for large projects, nor for projects where
reliability is an issue)". But that simply restates your conjecture. Why
is the development model not appropriate for large projects, nor for
projects where reliability is an issue? A short and to the point answer
would be most appreciated.
Andrei
>>Sorry, but I don't buy this. I would rather say it's the other
>>way around. In Java, if you want to have external specializations,
>>you write an interface and implement it by a class, and the
>>class is then the implementation.
>
>
> That's the usual work-around, but there are things that you can
> do with a class, like create instances, that you cannot do with
> an interface.
/* snipped. Agreement on compiler-firewall-idiom */
>>So likely, I think this is a
>>misunderstanding how to express the concepts within Java.
>
> There is a definite difference: in C++, I can define a class,
> without implementing it. Other people can then write code
> against that definition, and compile their code, effectivelly
> working in parallel with me while I implement the class.
>
> In Java, I have to define an interface. Other people cannot
> write all of their code against it, since they cannot write
> anything which creates an instance of it. They have to wait
> until I've finished the implementation of the actual class.
I'm still scratching my head about what you said.
I agree that this is a hourse of a different color, so to say, because
the design has to be different. Namely, instead of classes, you write
factories that generate classes that implement abstract interfaces. But
that's pretty close to what I'm doing in C++, too, at least for
the "classes" that are visible to the outside of the project (not
to call them interfaces).
My interface classes usually follow the compiler firewall idiom,
forwarding the call to the interface, and requiring some kind
of factory to generates them. It's not much different from
what I do in Java. No, I first learned C++, then Java.
Thus, one can potentially argue that Java requires you to write
in a certain style, whereas C++ allows you to choose the idioms
you want to use. I don't quite see though why the Java style is
unsuitable for larger scale projects - probably some concrete example
about its failure would enlighten me.
As said, I'm mostly using C++, but rather because it offers
"low-level" support that is not available in Java. C++ is very
pragmatic in this respect, which is suitable for my problem
domain (number crunching with high complexity). If the algorithmic
thru-put wouldn't matter, and I'd rather had a GUI project to
write, Java would be a prime candidate since it offers good
"high-level" support.
>>Of course, something the like can be arranged in C++ using the
>>pimpl idiom, but it requires additional work and is not expressed
>>in the syntax of the language itself.
>
>
> And in Java, it cannot even be arranged.
Huh? Of course? It's called an "interface".
>>What I - personally - consider most irritating in Java that you
>>do not have destructors, and thus cannot really release resources
>>at controlled times without writing additional code - it cannot
>>be expressed in Java.
>
>
> You have to write the additional code in C++ as well, the
> destructor:-). The problem isn't that you, as author of the
> class, has to write additional code; the problem is that every
> single one of your users will have to write additional code, at
> the site of use. And that's very error prone.
Yup, that's how I should have said it, but failed to. (-:
Thanks!
> I agree that its a serious drawback in Java. One could argue
> that it affects large projects more, since it increases the
> communications burden; I didn't mention it, because I find that
> it also affects even small projects negatively.
>
>
>>I'm also working here on a code using Corba
>>on the Java side, and now it's cluttered with "close()" methods
>>all over the place just to ensure that the Corba proxies are shutdown
>>early, with the result that you can have Zombie objects, etc.
>
>
> Not to mention that the lack of out parameters means a lot of
> extra proxy objects.
Not to mention that, yes. It's indeed another anoyance. (Leaving
the quality of the Java ORB aside, which is again just
another problem. Here it throws a null-pointer exception every
once in a while. Doesn't do anything negative - it keeps on
working, but that, uhm, causes some irritation concering the
quality of the code - let's put it this way. But Corba, now
that's quite another topic.)
So long,
Thomas
> >>I think Mathias' point was strong enough --- the compiler
> >>could, and IMO *should* make that assumption up front;
> >>std::vector can only be what the language specifies it to
> >>be; now, the thing is, is the guarantee that they're either
> >>the same, or entirely non-overlapping blocks, given explicitly,
> >>or is it rather a "side-effect" of the *typical* way in which
> >>it is implemented?
> > I think there are a number of people who don't; who are of the
> > opinion that it should be possible to write the equivalent of
> > std::vector as a true user defined type [...]
> > On the other hand, there's
> > been a very strong demand (and maybe still is) that the user be
> > able to replace the library with another implementation. Which
> > limits what the compiler can "know".
> Wait! Two things: 1) std::vector *is* a user-defined type.
For what definition of "user-defined type"? An instantiation of
std::vector is a class type; in some contexts, it is
conventional to divide the types into "fundamental types", and
"user-defined types", and in these contexts, it is a user
defined type. More generally, however (and this corresponds to
the use of the expression in the library sections of the
standard), a user-defined type is a type defined by the user,
and thus, not by the standard.
> That was just a "nit pick" --- the important point is 2)
> std::vector is a user-defined type that must follow certain
> specifications that the compiler *know* about.
It's part of the standard, and it is part of the "compiler", in
the larger sense that the standard uses the word. The compiler
can know not only about its specifications, but also the most
intimate details of its implementation. A perfectly legal
implementation of the header <vector> could be:
#pragma __turnon_buildin( "vector" )
or something along those lines. (For that matter, the compiler
could directly recognize the line "#include <vector>", and
execute whatever was necessary, without there even being a
header anywhere.)
> The compiler can make any assumptions that follow from the
> Standard specification of std::vector, and if those
> assumptions happen to be false, then it would be up to the
> user to replace the defective STL implementation.
The compiler can assume a specific implementation of
std::vector; it's part of the compiler implementation, and not
an external component or library.
A compiler implementation can, if it so desires, as an
extension, provide a means for replacing the standard library,
either completely, or in parts. The standard doesn't require
this, but it is (or was) an often requested feature, and most
compilers do provide it, at least in part. (I daresay that
replacing <typeinfo> would cause a number of problems, but you
can usually replace the STL part in block.)
> > At any rate, current compilers don't seem to use this
> > information.
> Ok, good point. Still, the discussion was fun while it
> lasted, no? :-)
Certainly. I think we all agree that compilers could do better
than they do:-). Among compiler writers, there is general
agreement that C and C++ are bitches to optimize, because of the
aliasing, but that doesn't mean that with a bit more work...
(Among tool writers, C and C++ aren't very popular either,
because of the preprocessor. And users don't like all the
undefined behavior. All in all, C++ is a horrible language.
The only problem is that the others are even worse.)
For random access, or for nested loops? (A good compiler should
be able to "unnest" the loops, and access sequentially, with a C
style array. Provided it sees the array, and not just a pointer
to the first element.)
Also, how big was N? And did the results continue to hold when
the first dimension got very big. I would imagine (but I'm
really just guessing) that locality would kick in, and slow up
std::vector, if when the second dimension gets into the
thousands or tens of thousands.
A couple of quick tests on my machine (Sun Sparc, but using g++
4.1.0) gave some surprising results. First, as expected,
running through the values in order was a lot faster (about five
times) than inverting the rows and the columns. Other than
that, strangely enough, using powers of 2 (1024x1024) was
significantly slower than using a power of 10
(1000x1000)---given that the machine I'm on doesn't have
hardware multiply and divide, I really cannot explain it.
std::vector, of course, doesn't display this difference; it's a
lot faster than C-style arrays for 1024x1024, and significantly
slower for 1000x1000. Wierd. (A quick look at the generated
code shows that g++ is maintaining both a pointer and an index
in the inner loop, thus avoiding any multiplication there. With
close to 32 registers to play with, there are obviously
optimization opportunities that you don't have on an Intel
architecture. But that still doesn't explain why the power of 2
dimensionned arrays were so slow.)
--
James Kanze (GABI Software) email:james...@gmail.com
Conseils en informatique orientie objet/
Beratung in objektorientierter Datenverarbeitung
9 place Simard, 78210 St.-Cyr-l'Icole, France, +33 (0)1 30 23 00 34
While I do not know of any implementation that does so, arranging that
memory held in a large vector (4K+) was released back to the OS when the
vector died or even more importantly when the vector grew to needing a
replacement memory block could make sense.
Actually, when I think of it, this is a good example of where such would
be desirable, otherwise a vector can rapidly consume memory which it
promptly abandons.
--
Francis Glassborow ACCU
Author of 'You Can Do It!' and "You Can Program in C++"
see http://www.spellen.org/youcandoit
For project ideas and contributions:
http://www.spellen.org/youcandoit/projects
> > > My understanding of most system allocation schemes is that your heap
> > > mangement requests memory at the page lavel, for example 4k on an x86
> > > running in "4G protected" mode.
> > I suspect that most heap mangement implementations request
> > memory in far larger chunks, because system calls are (or are
> > perceived as being) expensive.
> 4KB is quite a long chunk of memory, and OS response is not that tragic
> in this case.
4KB is chicken feed on a modern processor. On the other hand,
of course, do note what I put in parentheses. Every time I've
actually measured something widely accepted as expensive (prefix
incrementation, locking, etc.), it turned out that it wasn't:-).
So I suspect that historical traditions play a role here as
well.
> > > As long as you ensure that the whole
> > > page is unused, you can just chuck it back at the OS.
> > And how do you do ensure that the whole page is unused?
> That is the job of memory allocator. Some effective memory allocation
> schemes naturally produce empty 4KB pages.
And they're often the fastest ones. Still, it's not any easy
job for a general purpose allocator. (Note too that at least
under Solaris, once you've allocated a block of n bytes, you
can't change its size, and free up just some of the pages. And
realistically, there are reasons for preferring larger
allocations than just one page.)
--
James Kanze (GABI Software) email:james...@gmail.com
Conseils en informatique orientie objet/
Beratung in objektorientierter Datenverarbeitung
9 place Simard, 78210 St.-Cyr-l'Icole, France, +33 (0)1 30 23 00 34
--
On Jan 22, 9:57 pm, "Timo Geusch" <t...@unixconsult.co.uk> wrote:
> danielapar...@gmail.com wrote:
> > The fact is, a lot of mainstream enterprise development has moved away
> > from C++, and it isn't coming back. That also has implications for
> > what does and does not make sense in charting the future of C++.Yes, but
not necessarily for reasons of technical excellence of
> whatever technology/language the development moved to. I'm not a big
> fan of using C++ for everything up to and including a job that a shell
> script could do ten times better but some of these decisions seem to
> have been made more for political and CV-massaging reasons than
> anything else.
>
Perhaps in individual cases, but the overwhelming reason seems to be
the desire for a simpler programming model, and a focus on delivering
functionality rather than on the language itself.
comp.lang.c++.moderated is a case in point, no other language that I
know inspires so many questions that only a small percentage of the
programming community seems to be able to answer correctly, and even
acknowledged experts occasionally get wrong. It's for this reason that
I think C++ has lost its position as the general purpose language of
choice, and it won't get it back. If anything, the desire for
simplicity is increasing. This still leaves territory, but it's a
greatly reduced territory.
The performance issues raised in this thread are interesting, because
this is an area where C++ should dominate Java. I've written Monte
Carlo simulation engines in C++ that I don't think could be remotely
matched in Java, simply because of the level of control that C++ allows
over resource management. On the other hand, my clients today seem to
be quite happy to run compute-intensive Java apps on massive grids with
64 bit virtual machines, so I don't know, maybe that's the way to go.
There are also C++ apps whose performance is not impressive, just as
with Java apps, and in many cases the issues are not with the
languages, but with the programming techniques. It seems to have
become popular in recent years to load everything into memory and work
on it there, even when you're dealing with objects you want to process
once and never see again. Of course, techniques like that don't scale,
if volumes approach the resource limits.
Daniel
--
Which just goes to prove that even an expert's hunches are no use when
it comes to optimizing C++ - you have to measure.
My guess is that powers of two caused cache collisions.
> A couple of quick tests on my machine (Sun Sparc, but using g++
> 4.1.0) gave some surprising results. First, as expected,
> running through the values in order was a lot faster (about five
> times) than inverting the rows and the columns. Other than
> that, strangely enough, using powers of 2 (1024x1024) was
> significantly slower than using a power of 10
> (1000x1000)---given that the machine I'm on doesn't have
> hardware multiply and divide, I really cannot explain it.
I must admit I'm not quite sure I understand what you've tested (could
you post the programme?) but my bet would be a caching effect.
In a typical cache design, cache line n maps to memory "lines" n +
m*c, where c is the size of the cache in lines and m some integer. It
is very likely that c is a power of 2 less than or not much more than
the size of one of your rows.
This means that a[0][0] maps to the same line as a[1][0] and in fact
as any a[n][0]. If you traverse column-first, you get a cache miss on
every access.
If the size isn't a power of two, the cache lines will map to the
array in a staggered fashion, so that e.g. a[0][0] and a[1][6] now
have a cache line in common. If the cache is large enough to hold an
entire column, then for a number of columns after the first, there
won't be any cache misses.
This situation is less likely to occur with std::vector I think.
Lourens
>> [...] But that still doesn't explain why the power of 2
>>dimensionned arrays were so slow.)
>
> Which just goes to prove that even an expert's hunches are no use when
> it comes to optimizing C++ - you have to measure.
>
> My guess is that powers of two caused cache collisions.
Good pointS --- maybe 512x512 compared to 550x550 would show an
advantage in the power of 2?
Carlos
--
> [...] All in all, C++ is a horrible language.
> The only problem is that the others are even worse.
ROTFL !!!
You could also say that C++ is horrible --- it's the things
that we can do with C++ and not with other languages that are
beautiful!
>>>Given your results, I would not be too surprised if on some
>>>machines, the C style array was also faster for "simple"
>>>multiplications---things like a power of 2 +/- 1, which can
>>>still be done by a shift and an add/sub., but slower for more
>>>"exotic" values.
>
>>That was the case when I did the test (which was on Linux,
>>with g++, not sure which version, but maybe some time around
>>version 3.2 or 3.3, on an Athlon XP processor).
>
>>C arrays of the form a[N][32] or [N][64], etc. were faster
>>(don't remember by how much), but precisely, something of
>>the form a[N][100] was close to twice slower than
>>vector< vector<T> > a (N, 100).
>
> For random access, or for nested loops? (A good compiler should
> be able to "unnest" the loops, and access sequentially, with a C
> style array. Provided it sees the array, and not just a pointer
> to the first element.)
>
> Also, how big was N? And did the results continue to hold when
> the first dimension got very big. I would imagine (but I'm
> really just guessing) that locality would kick in, and slow up
> std::vector, if when the second dimension gets into the
> thousands or tens of thousands.
Your guesses seem perfectly reasonable to me --- and it is too
bad that I didn't keep a copy of those tests and the results;
I also agree with your surprise about the tests you made (the
surprising part that it is slower with a power of 2 --- the
rest seems reasonable).
From what I recall, the values of N in my tests were not too
large; I was probably calling a function to loop and do
several million times some calculations (accumulating the
randomly-filled values, perhaps?) --- still, with the function
parameter declared as a C-array, the compiler could still
optimize things.
I somewhat don't remember that I did random access; though it
makes me wonder now, since the vector of vectors had such a
huge advantage. Probably I compiled without any optimizations
at all.
Bottom line is: I better repeat those tests if I want to
continue with the anecdotical arguments about vector of vectors
vs. C arrays :-)
Carlos
--
> In practice, however, where are we?
It seems that at least glibc is a bit integrated in GCC.
It can produce warnings where not passing arguments conforming to the
format of printf, or replace printf with puts when appropriate for
example.
It doesn't seem like libstdc++ has much integration though.
[...]
> > A couple of quick tests on my machine (Sun Sparc, but using g++
> > 4.1.0) gave some surprising results. First, as expected,
> > running through the values in order was a lot faster (about five
> > times) than inverting the rows and the columns. Other than
> > that, strangely enough, using powers of 2 (1024x1024) was
> > significantly slower than using a power of 10
> > (1000x1000)---given that the machine I'm on doesn't have
> > hardware multiply and divide, I really cannot explain it.
> I must admit I'm not quite sure I understand what you've tested (could
> you post the programme?)
#define LOOP
\
double total = 0.0 ;
\
for ( size_t i = 0 ; i < dim2 ; ++ i ) {
\
for ( size_t j = 0 ; j < dim1 ; ++ j ) {
\
total += myArray[ j ][ i ] ;
\
}
\
}
\
myResult = total
Invoked over a double[N][M], a double (*)[M], and an
std::vector< std::vector< double > >( N, M ) (all members of
their respective, class which performed the benchmark.
> but my bet would be a caching effect.
I suspect as much. Note, however, that I've had some very
unexpected timings in the past, for other things, on a Sparc.
> In a typical cache design, cache line n maps to memory "lines" n +
> m*c, where c is the size of the cache in lines and m some integer. It
> is very likely that c is a power of 2 less than or not much more than
> the size of one of your rows.
> This means that a[0][0] maps to the same line as a[1][0] and in fact
> as any a[n][0]. If you traverse column-first, you get a cache miss on
> every access.
> If the size isn't a power of two, the cache lines will map to the
> array in a staggered fashion, so that e.g. a[0][0] and a[1][6] now
> have a cache line in common. If the cache is large enough to hold an
> entire column, then for a number of columns after the first, there
> won't be any cache misses.
That sounds like an likely explination.
> This situation is less likely to occur with std::vector I think.
Definitly. On the other hand, supposing that my inner dimension
corresponds to the size of a page, I'm pretty much guaranteed
that each index results in a cache miss with std::vector, no?
So how come it performed significantly better when the inner
dimension was a power of two?
I'm intreged, and I'd like to investigate more, but I'm afraid I
don't have the time. So about all I can really conclude is:
don't take any pre-conceived assumptions concerning performance
for granted. (And don't suppose that one particular measurement
is typical of anything.)
--
James Kanze (GABI Software) email:james...@gmail.com
Conseils en informatique orientie objet/
Beratung in objektorientierter Datenverarbeitung
9 place Simard, 78210 St.-Cyr-l'Icole, France, +33 (0)1 30 23 00 34
--
>
>
> On Jan 22, 9:57 pm, "Timo Geusch" <t...@unixconsult.co.uk> wrote:
> > danielapar...@gmail.com wrote:
> > > The fact is, a lot of mainstream enterprise development has moved
> > > away from C++, and it isn't coming back. That also has
> > > implications for what does and does not make sense in charting
> > > the future of C++.Yes, but
> not necessarily for reasons of technical excellence of
> > whatever technology/language the development moved to. I'm not a big
> > fan of using C++ for everything up to and including a job that a
> > shell script could do ten times better but some of these decisions
> > seem to have been made more for political and CV-massaging reasons
> > than anything else.
> >
> Perhaps in individual cases, but the overwhelming reason seems to be
> the desire for a simpler programming model, and a focus on delivering
> functionality rather than on the language itself.
And I'd say that this is a good thing; To me it seems that some of the
"new" religions^methodologies that are focusing on delivering (Agile et
al.) have led to people realising that sitting in a room doing cool
stuff for five years doesn't necessarly help.
> comp.lang.c++.moderated is a case in point, no other language that I
> know inspires so many questions that only a small percentage of the
> programming community seems to be able to answer correctly, and even
> acknowledged experts occasionally get wrong. It's for this reason
> that I think C++ has lost its position as the general purpose
> language of choice, and it won't get it back. If anything, the
> desire for simplicity is increasing. This still leaves territory,
> but it's a greatly reduced territory.
I'm a big fan of simplicity as long as it doesn't turn into
straightjacket. Unfortunately once you've played with fairly powerful
languages, a lot of the supposedly simpler languages tend to feel a bit
too restrictive to me.
Unfortunately this coin has two very distinct sides in the case of C++
as the power of C++ does come with a price tag attached and that price
tag suggests that at least some of the more powerful features have
"here be dragons" written all over it.
> The performance issues raised in this thread are interesting, because
> this is an area where C++ should dominate Java. I've written Monte
> Carlo simulation engines in C++ that I don't think could be remotely
> matched in Java, simply because of the level of control that C++
> allows over resource management. On the other hand, my clients today
> seem to be quite happy to run compute-intensive Java apps on massive
> grids with 64 bit virtual machines, so I don't know, maybe that's the
> way to go.
Reminds me of a discussion I had a couple of months ago with a
potential client who had re-implemented their quant libraries in Java
and were running them as an engine on a fairly big SUN box. They were
supposedly happy with the performance (which struck me as a tad
surprising given that the calculations are usually the bottleneck IME)
but they were throwing a massive amount of hardware at the problem in
exchange for a potential gain in programmer productivity.
C++ does allow you to squeeze a lot more from the same system if you
know what you're doing but IMHO we're still caught up by a wrong
application of Moore's law which tends to get translated into "it'll be
faster on next week's hardware" with the result being that the effort
needed to get the additional performance is never expended. And
suddenly just adding a few more machines to your massive Java-based
cluster looks like the better option.
> There are also C++ apps whose performance is not
> impressive, just as with Java apps, and in many cases the issues are
> not with the languages, but with the programming techniques.
Indeed, but I guess this is something that transcends languages anyway.
There is an awful lot of bad code out there (and yes, some of it is
written in C++) and that is usually a manifestation of an I don't know
better/I don't care mindset. I would expect that the people on this
newsgroup don't fall into this category, however.
> It
> seems to have become popular in recent years to load everything into
> memory and work on it there, even when you're dealing with objects
> you want to process once and never see again. Of course, techniques
> like that don't scale, if volumes approach the resource limits.
While I never got a around to finishing my CompSci degree I've spent
quite a few years at university studying for one a while back - well,
15-odd years now. I do tend to work in/with teams that have a fair
share of recent graduates and for some reason their rounding in
computer architecture is somewhat shaky to say the least. One of the
unfortunate side effects of this is that a lot of programs tend to be
written under the mistaken assumption that memory is infinite and that
there is no cost associated with inefficient programming.
--
The lone C++ coder's blog: http://www.bsdninjas.co.uk/codeblog/
[ See http://www.gotw.ca/resources/clcm.htm for info about ]