mechanical sympathy from Java view - a righteous cause?

1074 views
Skip to first unread message

Ben Cotton

unread,
Dec 20, 2013, 11:42:00 AM12/20/13
to mechanica...@googlegroups.com
First, and foremost, last thing wanted is to re-start another C/C++ vs. Java conversation.

But, I was hopeful that this forum might pep, rally, and re-motivate my belief that mechanical sympathy from the Java platform view is indeed a worth-while and righteous pursuit.

Reason I mention this is that at an (admittedly vodka fueled) holiday party last night I was overwhelmed by a pack of seasoned "C/C++ forever, just say no to Java" programmers that unanimously preached (and without any compromise) that those seeking mechanical sympathy from the Java view are fundamentally mis-directed (if not outright delusional).

They prosecuted as follows:

1.  mechanical sympathy is the pursuit of OS level/hardware/et. al. native resources to gain access to performance advantages otherwise un-available from the default development platform.
2. The Java platform purposefully denies access to OS level/hardware/et. al. native resources
3. The OS (kernel, I/O, process subsystem, system call API, hardware device drivers,etc.) are all written in C/C++ ... interfacing with these resources via C/C++ is natural and intended
4. Java platform's highest priority is WORA portability ... a necessarily OS-agnostic approach ... which, by definition, compromises its capability to fully access OS-specific mechanical resources.  
5. Java platform's non-direct access to these mechanical resources must cross a JNI bridge to C/C++ ... So, no matter how you look at it your going to wind up in C/C++ anyway.

CONCLUSION:  If you have both the capability and choice to use C/C++, why in the world wouldn't you just write your app in C/C++ in the first place?

DERIVED CONCLUSION:  pursuit of mechanical sympathy from the Java view is at conflict with itself.  Frankly, the Java platform, at its core, wants to deny you mechanical sympathy.

Though the vodka has worn off, and the prosecution has rested, I still remain a bit sympathetic to their lack of sympathy.

But I want re-engage this crowd.  Any advice for a defense re-buttal?

Happy holidays everybody,
Ben

frank.br...@gmail.com

unread,
Dec 20, 2013, 11:57:17 AM12/20/13
to mechanica...@googlegroups.com

Sorry, but I think the prosecution likely has themselves a conviction in this specific case.

Martin Thompson

unread,
Dec 20, 2013, 12:22:02 PM12/20/13
to mechanica...@googlegroups.com
This is very easy to turn into a religious war. :-)

From my personal experience the VAST MAJORITY of performance issues can be avoided with good clean design. That is, small composable methods/functions organised into a design with low coupling and high cohesion, which does not do stupid things to the underlying platform. I've seen terrible performance result from bad design in all languages.

For the limited cases of performance hot spots in a design, one must be aware of mechanical sympathy and order of algorithms. When it comes to the mechanical sympathy, some languages like C++ make it easier to communicate your intent to the machine than say Javascript. Java is somewhere in between. The focus on such areas MUST be profiler directed and not based on guesses.

When going for outright performance it is possible to squeeze out a little more with a language like C/C++, often at a huge increase in complexity, bug counts, and time to market. However the performance gap between the likes of Java and C/C++ is reducing all the time.

A fun game I often play on client engagements where such views exist is to have a bake off and see which team solve a problem fastest and get the best performance. I like to do this a few times and show that it matters more what team I'm on than which language is chosen :-) The most important point is that having good design skills and platform awareness (aka mechanical sympathy) matter more than the language. Also important is having a good network of people you can ask for help when you encounter a roadblock, which was my major reason for setting up this discussion group.

The simple way to approach such a discussions is first to define the performance goals. "Make is fast" is a crap performance goal. Once you have sensible goals based on business needs then work out the most efficient way of getting there.  Our value as programmers is to meet those goals with the simplest possible solution that can be maintained. BTW simple does not mean dumb!

Martin...

Ryan Rawson

unread,
Dec 20, 2013, 12:41:03 PM12/20/13
to mechanical-sympathy
I hope that mechanical sympathy and Java is compatible, there's an entire industry banking on it (aka the big data industry).

But the prosecution isnt entirely correct, I'll point out a few things line by line.


On Fri, Dec 20, 2013 at 8:42 AM, Ben Cotton <bendc...@gmail.com> wrote:
First, and foremost, last thing wanted is to re-start another C/C++ vs. Java conversation.

But, I was hopeful that this forum might pep, rally, and re-motivate my belief that mechanical sympathy from the Java platform view is indeed a worth-while and righteous pursuit.

Reason I mention this is that at an (admittedly vodka fueled) holiday party last night I was overwhelmed by a pack of seasoned "C/C++ forever, just say no to Java" programmers that unanimously preached (and without any compromise) that those seeking mechanical sympathy from the Java view are fundamentally mis-directed (if not outright delusional).

They prosecuted as follows:

1.  mechanical sympathy is the pursuit of OS level/hardware/et. al. native resources to gain access to performance advantages otherwise un-available from the default development platform.

To achieve performance, you want to be in alignment of the reality of the CPU/RAM/etc hardware situation.  Getting access to native kernel calls isnt the entire story.
 
2. The Java platform purposefully denies access to OS level/hardware/et. al. native resources

This use to be more so the case, but less so with nio and whatnot.  One issue is that JNI boundaries and arrays interact poorly via fully copies.  Another is the GC moves objects around (for better and worse) so you can't pass Java heap things to the Kernel.  This is fixable - with a new kernel!
 
3. The OS (kernel, I/O, process subsystem, system call API, hardware device drivers,etc.) are all written in C/C++ ... interfacing with these resources via C/C++ is natural and intended

I don't really like naturalistic arguments, mostly because they are by analogy and dont really explain anything.  Yes the friction is less, but as I pointed out, performance isn't all about calling kernel syscalls as fast as possible.

 
4. Java platform's highest priority is WORA portability ... a necessarily OS-agnostic approach ... which, by definition, compromises its capability to fully access OS-specific mechanical resources.  


This I found problematic... the stated goal of C and C++ is to be a platform neutral, portable language.  WORA too really - remember autoconf scripts that would let a project compile and run on literally a dozen unix variants with nearly as many CPU variants?

C is based on pdp11 assembler, and it's execution model no longer accurate describes how a modern super-scalar CPU works.  I'm sure Gil can talk a lot about this.  Neither is Java, but the hotspot gives it certain optimization chances C doesn't have (until LLVM, which exists exactly for this reason).  Also C has a few ugly features that prevent optimization (eg: pointer/array aliasing) which is why some folks prefer Fortran for their performant code :-)


 
5. Java platform's non-direct access to these mechanical resources must cross a JNI bridge to C/C++ ... So, no matter how you look at it your going to wind up in C/C++ anyway.

Not true, that is assuming your only method of accessing these things is via JNI libraries, but allow me to introduce you to my friend... the JVM intrinsic.

 

CONCLUSION:  If you have both the capability and choice to use C/C++, why in the world wouldn't you just write your app in C/C++ in the first place?


My personal thoughts here are, because C is too low level and error prone (memory allocation! yay!), and C++ is too complex and error prone.  Also I hate having to take a week to decide what logging platform or write one to use at the start of every C++ project.  Ditto smart pointers,  Ditto everything else.

 

DERIVED CONCLUSION:  pursuit of mechanical sympathy from the Java view is at conflict with itself.  Frankly, the Java platform, at its core, wants to deny you mechanical sympathy.

I say untrue, Java exists with a few core assumptions that makes certain forms of mechanical sympathy harder (eg: reallocating GC), but its purpose isn't to deny you system performance.  To me, performance comes from (a) CPU, (b) cache efficiency (c) RAM efficiency and (d) IO efficiency.  Each of these has a different definition of what "efficiency" means, and multiple ways of achieving it.
 

Though the vodka has worn off, and the prosecution has rested, I still remain a bit sympathetic to their lack of sympathy.

But I want re-engage this crowd.  Any advice for a defense re-buttal?

Happy holidays everybody,
Ben

--
You received this message because you are subscribed to the Google Groups "mechanical-sympathy" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mechanical-symp...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Richard Warburton

unread,
Dec 20, 2013, 12:45:47 PM12/20/13
to mechanica...@googlegroups.com
Hi,

Ignoring the bigger picture issues, which Martin Thompson has already answered very well, I think its a mistake to make the claim that ...

5. Java platform's non-direct access to these mechanical resources must cross a JNI bridge to C/C++ ... So, no matter how you look at it your going to wind up in C/C++ anyway.

You'll find that a number of methods will get converted to intrisics in hotspot.  For example you can allocate native memory without needing to cross a JNI bridge.  I'm not advocating that you should, just observing that if you want to its entirely possible.  Its also possible to access a number of OS level features, eg memory mapped files, without having Java-originating performance hits on every I/O operation.

regards,

  Richard Warburton

Simone Bordet

unread,
Dec 20, 2013, 12:49:34 PM12/20/13
to mechanica...@googlegroups.com
Hi,

On Fri, Dec 20, 2013 at 5:42 PM, Ben Cotton <bendc...@gmail.com> wrote:
> First, and foremost, last thing wanted is to re-start another C/C++ vs. Java
> conversation.
>
> But, I was hopeful that this forum might pep, rally, and re-motivate my
> belief that mechanical sympathy from the Java platform view is indeed a
> worth-while and righteous pursuit.

I think we need to define/agree what it is meant here by "mechanical sympathy".
My interpretation sticks with the "redefinition" given by Martin
Thompson, which took the definition of Jackie Stewart: know your
hardware because you'll become a better programmer (hey, I hope Martin
agrees here :)
In this light, I think that pursuing mechanical sympathy is something
you really want to look at in general, like you want to be interested
in functional programming if you have an imperative programming
background (or viceversa), or object-oriented if you have a procedural
background, etc.

> Reason I mention this is that at an (admittedly vodka fueled) holiday party
> last night I was overwhelmed by a pack of seasoned "C/C++ forever, just say
> no to Java" programmers that unanimously preached (and without any
> compromise) that those seeking mechanical sympathy from the Java view are
> fundamentally mis-directed (if not outright delusional).
>
> They prosecuted as follows:
>
> 1. mechanical sympathy is the pursuit of OS level/hardware/et. al. native
> resources to gain access to performance advantages otherwise un-available
> from the default development platform.
> 2. The Java platform purposefully denies access to OS level/hardware/et. al.
> native resources
> 3. The OS (kernel, I/O, process subsystem, system call API, hardware device
> drivers,etc.) are all written in C/C++ ... interfacing with these resources
> via C/C++ is natural and intended
> 4. Java platform's highest priority is WORA portability ... a necessarily
> OS-agnostic approach ... which, by definition, compromises its capability to
> fully access OS-specific mechanical resources.
> 5. Java platform's non-direct access to these mechanical resources must
> cross a JNI bridge to C/C++ ... So, no matter how you look at it your going
> to wind up in C/C++ anyway.
>
> CONCLUSION: If you have both the capability and choice to use C/C++, why in
> the world wouldn't you just write your app in C/C++ in the first place?

I believe this is an orthogonal problem to mechanical sympathy, and
there is tons of information online.

> DERIVED CONCLUSION: pursuit of mechanical sympathy from the Java view is at
> conflict with itself. Frankly, the Java platform, at its core, wants to
> deny you mechanical sympathy.
>
> Though the vodka has worn off, and the prosecution has rested, I still
> remain a bit sympathetic to their lack of sympathy.
>
> But I want re-engage this crowd. Any advice for a defense re-buttal?

My take is that hardware leaks abstractions up to more abstract layers.

Why there are atomic primitives in language libraries (both in Java and C++) ?
Because today every processor has atomic instructions so it's
worthwhile to have them in more abstract languages such as Java and
C++.

Why we want to have padding primitives to layout data in memory ?
Because today CPUs are multicore and effects such as false sharing do
have an important impact on performance.

Why we want arrays with power-of-two lengths to use masking instead of modulo ?
Because widespread used CPUs are known to be slower on modulo
operation than on masking.

And so forth. Hardware features leak into our code, no matter the language.

I choose Java over C++ because of the orthogonal reasons mentioned above.
Since hardware abstractions are not perfect, I need a way to control
them, both in Java and C++ (and others).

There are cases where the control of the hardware is so important and
so central that would make no sense to choose Java.
There are other cases where what is provided by Java is compelling
over C++, yet you want to be able to have some degree of control on
the hardware.

Therefore, pursuit of mechanical sympathy in Java makes sense to me.

--
Simone Bordet
http://bordet.blogspot.com
---
Finally, no matter how good the architecture and design are,
to deliver bug-free software with optimal performance and reliability,
the implementation technique must be flawless. Victoria Livschitz

frank.br...@gmail.com

unread,
Dec 20, 2013, 12:58:31 PM12/20/13
to mechanica...@googlegroups.com

There are cases where the control of the hardware is so important and 
so central that would make no sense to choose Java. 

No doubt about it.

There are other cases where what is provided by Java is compelling 
over C++, yet you want to be able to have some degree of control on 
the hardware. 

But , in the strictly mechanical sympathy sense, and with all due respect, what provided by Java is more compelling over C++?

I still think think the prosecution has met its burden  .... beyond a reasonable doubt.

Peter Lawrey

unread,
Dec 20, 2013, 1:01:16 PM12/20/13
to mechanica...@googlegroups.com
I have found that C/C++ projects tend to optimise the low level and forget the big picture.  What could be a great system in theory, often misses a number of key things because they didn't look at the end to end system and only optimise where they get the biggest gains.

For example, one system I have worked with, they have optimised the trading system very well in C/C++ and have a ~ 20 micro-seconds response time with very good stability.  A comparable system I wrote in Java about 4 years ago was about 60 micro-seconds with higher jitter.  However, they have optimised their system so much there is very little flexibility.   What is the cost of this inflexibility and narrow scope?  They  failed to take into account that the exchanges have a 800 to 2,500 micro-second response time.  So yes they optimised ~5% of the latency down to 2%, but what about the other 95%, they don't have time to investigate that nor do they have time to use the improvement which they could do. (Despite having much, much more people in the teams) So what is basic things they could have done instead?  The could have used line arbitration for market data for some exchanges, and for order placement on all exchanges.  This would speed up the round trip with the exchange by 80 - 600 micro-seconds.

In short,

The C/C++ system saved 40 micro-seconds in the trading system but miss out on between 80 - 600 micro-seconds by having a narrow view of optimisation, not where it really mattered, the exchanges. (And they had far more people to do it)

What C/C++ advocates won't talk about is how much longer or how much more man power you need to develop the same project.  This often comes with reduced flexibility, harder to refactor and innovate.

---

However, if you want to look at the low level, compare smart pointers in C++ to Java's references.  Most 64-bit JVMs use 32-bit references, and that is all that is needed, 4-bytes can address ~ 32 GB (~64 GB in Java 8).  A smart pointer consists of two 64-bit pointers, one to the reference counter which is an allocation of its own, typically a minimum of 32-bytes, and one to the actual object.  This means a smart pointer uses 16 bytes per reference and 32 bytes per object referenced. In a multi-threaded application this reference counter can be a significant overhead to maintain.  And you have to worry about circular references and bunch of other things Java handles for you.

In short, if you need the features Java provides you, the code will be as fast or faster in Java.  If you have a well understood, mature problem space (one which doesn't change too often) C/C++ is a better choice.

A thing they won't point out is that if you have a mature, well understood problem and you need to be super fast, an FPGA will beat C by a good margin.  IMHO the window between increasingly smarter FGPAs and more optimised Java systems, is getting narrower all the time.   

About ten years ago there was slightly more C++ jobs than Java jobs on jobserve.co.uk.  Now there is about 1/3 C++ compared with Java.




Regards,
   Peter.


--

Simone Bordet

unread,
Dec 20, 2013, 1:06:59 PM12/20/13
to mechanica...@googlegroups.com
Hi,

On Fri, Dec 20, 2013 at 6:58 PM, <frank.br...@gmail.com> wrote:
>> There are cases where the control of the hardware is so important and
>> so central that would make no sense to choose Java.
>
> No doubt about it.
>
>> There are other cases where what is provided by Java is compelling
>> over C++, yet you want to be able to have some degree of control on
>> the hardware.
>
> But , in the strictly mechanical sympathy sense, and with all due respect,
> what provided by Java is more compelling over C++?

If you write a microbenchmark about false sharing, C++ wins easily
since Java does not have yet public official ways of padding
(@Contended will arrive).
C++ has a lot more tools for mechanical sympathy, especially recent C++.

But I don't think this invalidates the pursuit of mechanical sympathy
in Java, because that's not the only thing I am doing with the
language.

Peter Lawrey

unread,
Dec 20, 2013, 1:21:33 PM12/20/13
to mechanica...@googlegroups.com

How does C++ handle false sharing much better? In java you just use padding. Not elegant but it works.

If you want full control you can just use Unsafe to layout native memory.

Ben Cotton

unread,
Dec 20, 2013, 1:24:20 PM12/20/13
to mechanica...@googlegroups.com

There are other cases where what is provided by Java is compelling 
over C++, yet you want to be able to have some degree of control on 
the hardware. 

But , in the strictly mechanical sympathy sense, and with all due respect, what provided by Java is more compelling over C++?

Here's one "Java is more compelling"  example for sure:  Take a look at  today's Java 7's Socket Direct Protocol capability. 

 From the comfy confines of the java.net and java.nio Socket APIs,  applications running on a Java 7 SDP configured VM can realize the full *native* Zero-Copy RDMA capability of Infiniband.  Native IB VERBs.  Directly from the physical OSI layer's NIC to the applications' Socket API view.   No walking up the OSI  Physical/Network/Internet/Transport/Session/Application stack.  Direct.  Physical--->Application.  Java 7 SDP ... mechanical sympathy at its best.

Now admittedly, it is a opulent Java environment that has IB (not ethernet) as their physical OSI network provider ... but in such settings Java hits a "more compelling over C++"  mechanical sympathy home run.

Simone Bordet

unread,
Dec 20, 2013, 1:28:55 PM12/20/13
to mechanica...@googlegroups.com
Hi,

On Fri, Dec 20, 2013 at 7:21 PM, Peter Lawrey <peter....@gmail.com> wrote:
> How does C++ handle false sharing much better? In java you just use padding.
> Not elegant but it works.

Sure. I meant to say that C++ has "primitives" while Java has not
until @Contended arrives.

> If you want full control you can just use Unsafe to layout native memory.

Sure, like manual padding, Unsafe is a bit more cumbersome to use.

To play devil's advocate here, why should I use manual padding (not
elegant) or Unsafe (cumbersome) when I can use C++ ?
I think the point is not about being _able_ to do things, both Java
and C++ can, but more about which one has the better tools.

Now I think that there is little doubt that C++ has better tools for
mechanical sympathy, but I don't think that means it is useless to
pursuit mechanical sympathy in Java.

Peter Lawrey

unread,
Dec 20, 2013, 1:36:14 PM12/20/13
to mechanica...@googlegroups.com

Why not use C++ for everything?

A: Due to the price you pay by longer time to market, higher maintenance costs, less reuse of embedded open source software. Are you willing to turn a two month Java project into a six month C++ project just to avoid manual padding?

Michael Hamrick

unread,
Dec 20, 2013, 1:39:00 PM12/20/13
to mechanica...@googlegroups.com
Martin,  if - in this game - you were on one design team advocating Java, but  the other design team  had Martin.clone() on their side (this Martin advocating C++) ... isn't it true that the C++ Martin would almost always have an advantage?

Peter Lawrey

unread,
Dec 20, 2013, 1:41:11 PM12/20/13
to mechanica...@googlegroups.com
Also playing devil's advocate, @Contended is a bit useless if you want a feature which is simple for developers to use.

Consider this class.

   class TwoCounters {
       @Contented
       final AtomicInteger counter1 = new AtomicInteger();
       @Contented
       final AtomicInteger counter2 = new AtomicInteger();
   }

Will this work as intended, No.  Just like final, @Contented applies to the references, not the objects.  The AtomicInteger have the same guarantee of being uncontended as they do of being final.

Martin Thompson

unread,
Dec 20, 2013, 1:41:24 PM12/20/13
to mechanica...@googlegroups.com
I think we need to define/agree what it is meant here by "mechanical sympathy".
My interpretation sticks with the "redefinition" given by Martin
Thompson, which took the definition of Jackie Stewart: know your
hardware because you'll become a better programmer (hey, I hope Martin
agrees here :)
In this light, I think that pursuing mechanical sympathy is something
you really want to look at in general, like you want to be interested
in functional programming if you have an imperative programming
background (or viceversa), or object-oriented if you have a procedural
background, etc.

I'm very much of the mindset that Mechanical Sympathy is all about software and hardware working together in harmony. This means writing code that works with and not against to the underlying platform. I also like to extend that platform to be the OS and Runtimes because they are as much our platform as the hardware. With an appropriate level of understanding of the underlying platform not only can we write more efficient code, we can also write code that is more robust because it is not surprised by the behaviour of that platform. Just like in motor racing, a good understanding of the safety features makes a huge difference. Take for example that fact that if you overheat your brakes then they fade or even fail. Understanding how you have configured a RAID makes a huge difference to performance and resilience, or your write patterns impact of the wear cycles for an SSD - you can do this from any language.
 
With regard to the comment on functional programming. Jackie Stewart believed there was a lot to be learned by driving in many different formula and disciples. He said he learned a lot from rallying that helped him in F1. Look at the end result, he was probably the greatest driver ever in the wet.

Having dabbled in motor racing myself it is so clear to me that the driver matters so much more than the machine. I've seen top racing drivers lap amateurs when the top drivers are in much inferior machinery. Highly specialised machinery also can have very limited use. I've had the fun of driving many types of cars on the track, and sure with some I'm faster than others. I kept advancing with such "toys" until one day I got to try a Formula 3000 race car. I thought so much power, so much grip, so much braking ability - in this I will fly. Then reality came crashing down. I did not have the skill to keep this beast right in its sweet spot. You need to drive it almost flat out otherwise the tires, brakes, and down force do not work. Needless to say I spent more time sideways and my lap times were really crap compared to what it was capable of in the right hands. 

Way too much of the C++ code I've seen looks like it has been written by someone who looks like me driving the F3000. Learning the fundamentals and constantly improving are way way more important than the machinery. Unless you are racing to be the absolute fastest, and a few actually are doing this, then we need to go as fast as necessary in an efficient and safe manner - and be enjoying it while doing it.

Martin...

Michael Hamrick

unread,
Dec 20, 2013, 1:44:12 PM12/20/13
to mechanica...@googlegroups.com

Way too much of the C++ code I've seen looks like it has been written by someone who looks like me driving the F3000. Learning the fundamentals and constantly improving are way way more important than the machinery. Unless you are racing to be the absolute fastest, and a few actually are doing this, then we need to go as fast as necessary in an efficient and safe manner - and be enjoying it while doing it.


Fabulous!  Thank you.    :-) 

Simone Bordet

unread,
Dec 20, 2013, 1:45:13 PM12/20/13
to mechanica...@googlegroups.com
Peter,

On Fri, Dec 20, 2013 at 7:36 PM, Peter Lawrey <peter....@gmail.com> wrote:
> Why not use C++ for everything?
>
> A: Due to the price you pay by longer time to market, higher maintenance
> costs, less reuse of embedded open source software. Are you willing to turn
> a two month Java project into a six month C++ project just to avoid manual
> padding?

You are pushing an open door with me :)

These are the orthogonal reasons I alluded to without detailing them
to avoid wars :)

Martin Thompson

unread,
Dec 20, 2013, 1:46:39 PM12/20/13
to mechanica...@googlegroups.com
C++ Martin can in general get a few percentage points more performance than Java Martin. However Java Martin can often complete the development a few times faster than C++ Martin.

Ben Cotton

unread,
Dec 20, 2013, 1:46:40 PM12/20/13
to mechanica...@googlegroups.com

Way too much of the C++ code I've seen looks like it has been written by someone who looks like me driving the F3000. Learning the fundamentals and constantly improving are way way more important than the machinery. Unless you are racing to be the absolute fastest, and a few actually are doing this, then we need to go as fast as necessary in an efficient and safe manner - and be enjoying it while doing it.


Fabulous!  Thank you.    :-) 

+1

Thanks Martin.  Very well said.

Howard Chu

unread,
Dec 20, 2013, 4:50:36 PM12/20/13
to mechanica...@googlegroups.com


On Friday, December 20, 2013 10:46:39 AM UTC-8, Martin Thompson wrote:
C++ Martin can in general get a few percentage points more performance than Java Martin. However Java Martin can often complete the development a few times faster than C++ Martin.

Still I think the comparison is lacking. There will be performance targets you can never hit in Java, no matter how long you spend in development.

Rajiv Kurian

unread,
Dec 20, 2013, 4:57:10 PM12/20/13
to mechanica...@googlegroups.com
I think every one here acknowledges that as it stands and if effort and manpower and expert knowledge are not an issue (rarely true in real life) C++/C can offer better absolute performance than Java. A few things where C/C++ does better than Java:

1) Access to all low level primitives that a platform might possess. This includes SIMD instructions and the pause instruction on x86 etc that have real benefit in high performance code. You have to find your own cross platform SIMD libraries that work well.
2) Structs. Every one talks about how unsafe can be used to achieve the same effect, but lets be honest unsafe is not fun to use and you end up writing C with an inferior syntax. Gil alludes to this in his "Enabling Java in Latency-Sensitive Environments" talk.  Things like padding or cache alignment are also easier done in C/C++ with the non standard__attribute__ ((aligned(#))) or __declspec( align( # ) ).
3) Very minor but I think memory mapped files are easier to use in C/C++.
4) Stack allocation is great. The JVM's escape analysis still isn't there. I am sure many will disagree with this given how heap allocation and frequent malloc-free cycles are slow. Preallocation and a good memory allocator like jemalloc helps here though. No magic solutions for cross thread malloc and free besides don't do it.

Also the amount of work put in something like GCC's optimizer shows. Hotspot maybe a marvel of engineering but GCC often does better than JITed code especially with auto vectorization.

C++ on the other hand is difficult to work with. Ignoring it's complicated syntax, the following are really painful:

1) Big projects take massive amounts of time to compile. Big companies (like Google) have entire teams set up to maintain build systems that make this less painful. This makes it difficult to get a change, compile, measure loop going.
2)  C++ lacks libraries. Some say it's because of the lack of GC. There are no established conventions on who allocates and who frees and getting libraries to work with each other is painful. Anecdotal evidence: I see questions on who is responsible for freeing all the freaking time on the libuv and concurrency kit mailing lists. The GC to some extent solves this for you. Using high performance expert written libraries are a great way to build systems that meet their performance goals. Writing a server that accepts 20k+ connections on a mediocre virtualized box is easy with libraries like Netty, Disruptor, Chronicle and Akka. It's not so trivial in C++. This leaves ample time for up front design time and also more time for the measurement/tuning phase. It also leaves time to add more features that could lead to a product being successful. That is after all the ultimate goal. For traders having more time to write and test strategies (which have short shelf times) could be more important than the 20 microseconds improvement (not free) that C++ brings to the table. I have the same argument for using Scala over Java. You lose some performance but it's easier to finish your project while business driven performance goals are still met.

If there was a project that has fixed, likely to remain stable requirements and performance is super important C++ is a great choice IMHO. Examples include a load balancer or a storage engine. Also it works great on machines with limited resources like mobile phones and embedded systems. For the rest of us mere mortals Java and other JVM languages are the perfect mix of performance and productivity. I can't stress enough how big a win it is to have libraries like Netty, Disruptor, Akka etc around to quickly build your disappearing photos application worth $2 billion. We do need to acknowledge that certain class of applications no matter how hard you try can only be done in C/C++. Many people will refuse to use even C++ on such projects and stick to C.

I am personally really excited about Rust. If you can look past it's many pointer types and complicated lifetime syntax, I think it could well be the new sweet spot. It has so many awesome features:

1) Lightweight syntax, pattern-matching, generics without the painful error messages of C++ templates but with the same performance. I would argue that most of the code is easier to read than Java thanks to the beautiful syntax.
2) Support for both 1:1 and M:N threading model. Libraries do need to be written to account for this which can be painful. Tasks also let one use non blocking IO (scheduled by the run time) with blocking syntax. This makes for really easy to write code. Again you leave some performance on the table, but doesn't matter for most people.
3) No dangling pointers, no double frees, in fact no data races. Unique pointers are checked compile time and are compiled down to raw pointers (no perf loss). The no data races is a big one especially with all the concurrent code we are writing. Again you pay a price with complicated lifetime annotations. Since there are no data races and since concurrency is done through message passing (copy less) if you allocate memory that needs to be GCed it can be done on a per task basis like Erlang. It also has RAII for releasing non memory resources.
4) Access to all the low level features of C++. This includes C++11 atomics. Easy invocation of existing native code is also a plus, though you lose all the safety guarantees. Did I mention real structs so no gymnastics needed to control layout?
5) A proper module system instead of header files. Not much here for Java developers but a big win for C++ devs.

Martin Thompson

unread,
Dec 20, 2013, 5:03:00 PM12/20/13
to mechanica...@googlegroups.com

On Friday, 20 December 2013 21:50:36 UTC, Howard Chu wrote:

On Friday, December 20, 2013 10:46:39 AM UTC-8, Martin Thompson wrote:
C++ Martin can in general get a few percentage points more performance than Java Martin. However Java Martin can often complete the development a few times faster than C++ Martin.

Still I think the comparison is lacking. There will be performance targets you can never hit in Java, no matter how long you spend in development.

You are right there are a few targets that are difficult to hit in Java. However there are very few I've not been able to work around with a bit of Unsafe and JNI, and they are getting fewer all the time as the JVM and libs advance. There are also targets that are difficult to hit in C/C++ unless using ASM or going to a FPGA.

Why is the comparison lacking.? I think it is factual. Ultimately C/C++ in the right hands can yield greater performance but with the consequence of greater time to market, higher bug count, and more complexity for all other things being equal.

Robert Frunzke

unread,
Dec 20, 2013, 5:53:36 PM12/20/13
to mechanica...@googlegroups.com
Well, I must disagree:

2)  C++ lacks libraries. Some say it's because of the lack of GC. There are no established conventions on who allocates and who frees and getting libraries to work with each other is painful. Anecdotal evidence: I see questions on who is responsible for freeing all the freaking time [..]

This is a thing every C++ developer must take responsibility for: when some library gives you some (dynamically allocated) object: who is responsible for it? Usually the context gives you a hint, and otherwise the documentation will tell you. In any case, you MUST regard it, it is essential for C++. (And in many cases objects can be stack-allocated, then it is easy...).

However, a C++ developer MUST take care of this issue, in contrast to a developer on some GC VM environment.

And the good thing about it is: there is a very clear and visible knowledge about WHO owns something at which time in processing. And this leads to a very clear and visible sense of "lifetimes of objects". Something that is unknown in (current) GC environments. Or at least it is a blurry, doubtful thing, leading to many bugs in GC environments.

Remember me, the next time you open a file, and write a try/catch clause with an additional final clause (just to close any dangling file handles) in Java ;-)

 
You lose some performance but it's easier to finish your project while business driven performance goals are still met.

Maybe. But if you trade performance against correctness, then you (or your customer) will lose some day.

It is easy to write toy-code in Java, but extremely hard to make it correct.

C++ demands much more from you, up-front, but your code will be much more correct.



Jason Koch

unread,
Dec 20, 2013, 6:05:44 PM12/20/13
to mechanica...@googlegroups.com, mechanica...@googlegroups.com

The response is that time and money and flexibility IS a factor --

If you subsitute c for any lower level primitive, and jvm for kernel or any other layer, you could equally argue that there's no point bothering with mech sympathy in such bloated environments.

Argument would go:

Why would anyone waste time on writing with c++, libc, or using the write once run anywhere kernel abstractions when you can write your own loader, machine code and device drivers for the specific hardware you own? Much more efficient!

By extension, if you write c++ you are wasting time thinking about memory layout and algorithms because if you really cared you would use machine code.

Hey just think about how much chip space is wasted on processor instructions you don't use very often! Build your own processor :)

Thanks
Jason

Robert Frunzke

unread,
Dec 20, 2013, 6:25:34 PM12/20/13
to mechanica...@googlegroups.com
Maybe, but...:


Am Samstag, 21. Dezember 2013 00:05:44 UTC+1 schrieb Jason Koch:

The response is that time and money and flexibility IS a factor --

Okey-dokey! No resistance from me.


If you subsitute c for any lower level primitive, and jvm for kernel or any other layer, you could equally argue that there's no point bothering with mech sympathy in such bloated environments.

No, C is not any lower level primitive and JVM is not the kernel! That kind of substitution is stupid, and not our topic.

 
Argument would go:

Why would anyone waste time on writing with c++, libc, or using the write once run anywhere kernel abstractions when you can write your own loader, machine code and device drivers for the specific hardware you own? Much more efficient!

By extension, if you write c++ you are wasting time thinking about memory layout and algorithms because if you really cared you would use machine code.

Read some lines below here... your assumed substitutions are rather surreal.

And your imaginary "wasted time" - is not so wasted at all, but most of the time it is essential for correct code. As I showed in my text about object lifetimes. Give "thinking about it" a try.

And comparison to "machine code" is unfair, stupid. Adding the values of two values in Java, in encapsulated integer objects, does not feel like machine code? It feels like a missing abstraction in java. But well, another topic...


Hey just think about how much chip space is wasted on processor instructions you don't use very often! Build your own processor :)

No.. whats your point here?

I am not an offender of GC VM environments at all. But I just do not like how people dismiss C++ when they have absolutely no idea of the underlying concepts, and thus in such discussions often also present how little they know about their actual GC VM environment (Java) at all. Java is not perfect, get it.

Rajiv Kurian

unread,
Dec 20, 2013, 6:29:40 PM12/20/13
to mechanica...@googlegroups.com


On Friday, December 20, 2013 2:53:36 PM UTC-8, Robert Frunzke wrote:
Well, I must disagree:

2)  C++ lacks libraries. Some say it's because of the lack of GC. There are no established conventions on who allocates and who frees and getting libraries to work with each other is painful. Anecdotal evidence: I see questions on who is responsible for freeing all the freaking time [..]

This is a thing every C++ developer must take responsibility for: when some library gives you some (dynamically allocated) object: who is responsible for it? Usually the context gives you a hint, and otherwise the documentation will tell you. In any case, you MUST regard it, it is essential for C++. (And in many cases objects can be stack-allocated, then it is easy...).

However, a C++ developer MUST take care of this issue, in contrast to a developer on some GC VM environment.

And the good thing about it is: there is a very clear and visible knowledge about WHO owns something at which time in processing. And this leads to a very clear and visible sense of "lifetimes of objects". Something that is unknown in (current) GC environments. Or at least it is a blurry, doubtful thing, leading to many bugs in GC environments.

Remember me, the next time you open a file, and write a try/catch clause with an additional final clause (just to close any dangling file handles) in Java ;-)
I typically use C++ a lot more than Java and I appreciate RAII. I am not labeling GC as a silver bullet - just observing that it helped Java to develop a rich ecosystem of high performance libraries. Rust I think again looks great in this regard. Ownership of objects is statically verified. There are no dangling pointers, no double frees, no returning a pointer to a stack allocated structure. This bugs are eliminated not with GC but with static analysis.

 
You lose some performance but it's easier to finish your project while business driven performance goals are still met.

Maybe. But if you trade performance against correctness, then you (or your customer) will lose some day.

It is easy to write toy-code in Java, but extremely hard to make it correct.

C++ demands much more from you, up-front, but your code will be much more correct.
Where did I talk about trading correctness? Could you elaborate why it is difficult to write correct code in Java or any more tougher than it is in C++? 

Rajiv Kurian

unread,
Dec 20, 2013, 6:35:37 PM12/20/13
to mechanica...@googlegroups.com


On Friday, December 20, 2013 3:29:40 PM UTC-8, Rajiv Kurian wrote:


On Friday, December 20, 2013 2:53:36 PM UTC-8, Robert Frunzke wrote:
Well, I must disagree:

2)  C++ lacks libraries. Some say it's because of the lack of GC. There are no established conventions on who allocates and who frees and getting libraries to work with each other is painful. Anecdotal evidence: I see questions on who is responsible for freeing all the freaking time [..]

This is a thing every C++ developer must take responsibility for: when some library gives you some (dynamically allocated) object: who is responsible for it? Usually the context gives you a hint, and otherwise the documentation will tell you. In any case, you MUST regard it, it is essential for C++. (And in many cases objects can be stack-allocated, then it is easy...).

However, a C++ developer MUST take care of this issue, in contrast to a developer on some GC VM environment.

And the good thing about it is: there is a very clear and visible knowledge about WHO owns something at which time in processing. And this leads to a very clear and visible sense of "lifetimes of objects". Something that is unknown in (current) GC environments. Or at least it is a blurry, doubtful thing, leading to many bugs in GC environments.

Remember me, the next time you open a file, and write a try/catch clause with an additional final clause (just to close any dangling file handles) in Java ;-)
I typically use C++ a lot more than Java and I appreciate RAII. I am not labeling GC as a silver bullet - just observing that it helped Java to develop a rich ecosystem of high performance libraries. Rust I think again looks great in this regard. Ownership of objects is statically verified. There are no dangling pointers, no double frees, no returning a pointer to a stack allocated structure. This bugs are eliminated not with GC but with static analysis.
Edit: These bugs* 

Robert Frunzke

unread,
Dec 20, 2013, 6:45:11 PM12/20/13
to mechanica...@googlegroups.com


Am Samstag, 21. Dezember 2013 00:29:40 UTC+1 schrieb Rajiv Kurian:


On Friday, December 20, 2013 2:53:36 PM UTC-8, Robert Frunzke wrote:
Well, I must disagree:

2)  C++ lacks libraries. Some say it's because of the lack of GC. There are no established conventions on who allocates and who frees and getting libraries to work with each other is painful. Anecdotal evidence: I see questions on who is responsible for freeing all the freaking time [..]

This is a thing every C++ developer must take responsibility for: when some library gives you some (dynamically allocated) object: who is responsible for it? Usually the context gives you a hint, and otherwise the documentation will tell you. In any case, you MUST regard it, it is essential for C++. (And in many cases objects can be stack-allocated, then it is easy...).

However, a C++ developer MUST take care of this issue, in contrast to a developer on some GC VM environment.

And the good thing about it is: there is a very clear and visible knowledge about WHO owns something at which time in processing. And this leads to a very clear and visible sense of "lifetimes of objects". Something that is unknown in (current) GC environments. Or at least it is a blurry, doubtful thing, leading to many bugs in GC environments.

Remember me, the next time you open a file, and write a try/catch clause with an additional final clause (just to close any dangling file handles) in Java ;-)
I typically use C++ a lot more than Java and I appreciate RAII. I am not labeling GC as a silver bullet - just observing that it helped Java to develop a rich ecosystem of high performance libraries. Rust I think again looks great in this regard. Ownership of objects is statically verified. There are no dangling pointers, no double frees, no returning a pointer to a stack allocated structure. This bugs are eliminated not with GC but with static analysis.

Okay, I can not yet imagine how static analysis could solve the problem, but I will definitely have a look at Rust!!

 
 
You lose some performance but it's easier to finish your project while business driven performance goals are still met.

Maybe. But if you trade performance against correctness, then you (or your customer) will lose some day.

It is easy to write toy-code in Java, but extremely hard to make it correct.

C++ demands much more from you, up-front, but your code will be much more correct.
Where did I talk about trading correctness? Could you elaborate why it is difficult to write correct code in Java or any more tougher than it is in C++? 

My statement was just a statement against the common statement that "c++ is just for performance".... while correctness, idioms, language features and so on are silently ignored. And the first issue seen in production java code is a lax understanding of correctness: dangling file handles, exceptions (in common error cases) that nobody can still understand (instead of plain, simple error messages to the user for common error cases), and so on.

You can write correct code in Java, but - IMHO - many people trade correctness for easy, fast-written, code.

But that is just my impression.

Robert Frunzke

unread,
Dec 20, 2013, 6:57:46 PM12/20/13
to mechanica...@googlegroups.com


There are no dangling pointers, no double frees, no returning a pointer to a stack allocated structure.

By the way: "double frees" and similar things are the issues, that Java mentors tell their pupils to make them amenable!


But, Java is not so much different. In Java, you may call on or read something from a NULL object, and get an exception.

In C++, this can happen too. But in C++ you would use stack objects and object references in situations, where an instance would actually be expected, and a plain pointer (which can be NULL) only in situations where the object actually could be NULL.

So, you would have the choice, and you would have agreements.

In Java you will not have that choice. To write correct Java, you would have to check any stupid object "ref" for being null at many stupid code points.


such are things

 

Rajiv Kurian

unread,
Dec 20, 2013, 7:10:17 PM12/20/13
to mechanica...@googlegroups.com


On Friday, December 20, 2013 3:45:11 PM UTC-8, Robert Frunzke wrote:


Am Samstag, 21. Dezember 2013 00:29:40 UTC+1 schrieb Rajiv Kurian:


On Friday, December 20, 2013 2:53:36 PM UTC-8, Robert Frunzke wrote:
Well, I must disagree:

2)  C++ lacks libraries. Some say it's because of the lack of GC. There are no established conventions on who allocates and who frees and getting libraries to work with each other is painful. Anecdotal evidence: I see questions on who is responsible for freeing all the freaking time [..]

This is a thing every C++ developer must take responsibility for: when some library gives you some (dynamically allocated) object: who is responsible for it? Usually the context gives you a hint, and otherwise the documentation will tell you. In any case, you MUST regard it, it is essential for C++. (And in many cases objects can be stack-allocated, then it is easy...).

However, a C++ developer MUST take care of this issue, in contrast to a developer on some GC VM environment.

And the good thing about it is: there is a very clear and visible knowledge about WHO owns something at which time in processing. And this leads to a very clear and visible sense of "lifetimes of objects". Something that is unknown in (current) GC environments. Or at least it is a blurry, doubtful thing, leading to many bugs in GC environments.

Remember me, the next time you open a file, and write a try/catch clause with an additional final clause (just to close any dangling file handles) in Java ;-)
I typically use C++ a lot more than Java and I appreciate RAII. I am not labeling GC as a silver bullet - just observing that it helped Java to develop a rich ecosystem of high performance libraries. Rust I think again looks great in this regard. Ownership of objects is statically verified. There are no dangling pointers, no double frees, no returning a pointer to a stack allocated structure. This bugs are eliminated not with GC but with static analysis.

Okay, I can not yet imagine how static analysis could solve the problem, but I will definitely have a look at Rust!!
Please take look at the ownership section of the tutorial and also borrowed pointers.