C++ vs Java - a motoring analogy

C++ vs Java - a motoring analogy

Author
Discussion

JonRB

Original Poster:

75,191 posts

274 months

Saturday 9th June 2007
quotequote all
dilbert said:
I don't know about smart pointers.... Don't use any of them. I have classes a bit like MFC (but they're mine) for doing anything like that.
Embrace the Standard Library (the STL) - it's part of the C++ language now.

dilbert

7,741 posts

233 months

Saturday 9th June 2007
quotequote all
JonRB said:
dilbert said:
I don't know about smart pointers.... Don't use any of them. I have classes a bit like MFC (but they're mine) for doing anything like that.
Embrace the Standard Library (the STL) - it's part of the C++ language now.
Templates per se have been a part of C++ for a long time. I personally don't like them much. It's a while since I even bothered trying to use them. So long in fact that, I cant remember why I don't like them. Possibly it's to do with virtual functions and templates, it's a bit hazy. All I remember is that there was something I wanted to do but couldn't. It wouldn't have been something that required code, more an inherent language capability that wasn't possible. Maybe things have changed.

Nevertheless, I've got enough vested in my own structural components that it would be an immense pain to migrate. I can't at the moment identify anything that I need to do that I can't, so why change. In fact it's likely that if I do need something of theirs, I'll understand what they did, and do my own. The reality is that I already have everything that they offer that I would want, and it's integrated with loads of suff that I do want, and they don't offer.

Theres plenty of business hype about at the moment about people who think it's bad if others don't want to change. Maybe they're right. They wouldn't like me though, because unless there is a reason to change I just won't. Because I tell you to isn't a good enough reason for me. (I'm not saying that's what you're saying, only what some say.)

Seems to me that the in many cases people are looking for unpopular changes, such that they can annoy people who wont change without good reason. On the face of it it's great because it's reasonable for business to dilike people that are unwilling to change. This is especially true in a world looking to be lean and mean. The trouble is that the particular approach can drive away those who are the very best at driving "intelligent change". Perhaps some of those people are often the ones that will say......

"It's time to change..... Lets look at what everyone else is doing, decide which bits we like, add the extra stuff we need, and change to something better."

It may be that something someone else did is better, but it must at least be so, in order to change.

Mediocrity is in the eye of the beholder!
smile

Edited by dilbert on Saturday 9th June 17:09

JonRB

Original Poster:

75,191 posts

274 months

Saturday 9th June 2007
quotequote all
As a freelancer, if I have a choice between a proprietary way and a standard way (ie. implemented in the Standard Library) then I'll take the latter unless there is a firm business or performance reason not to. Why spend time learning to do something in a way I may not be able to use at another client?

Templates when used to their full are truely mind-blowing. Have a look at "Modern C++ Design: Applied Generic and Design Patterns" by Andrei Alexandrescu for pattern-based programming including Template Template Parameters (not a typo) which implement Policies and Traits that modify the behaviour of the whole class. Absolutely awesome what you can achieve - ie. allow a decision to be taken at compile-time as to whether to be thread-safe or not (by choosing not in a single-threaded environment you can made performance gains by not even compiling in thread synchronisation let alone use it - maximum runtime performance)

He even gives examples of how to implement compile-time asserts which are brilliant for library code as you can trap improper use at compile time with no runtime hit at all.

I've written some really funky template-based stuff only recently that uses generic programming with "exceptions to the rule" handled by explicit template specialisation.

I'd really recommend looking into it - you're missing a world of power (and a huge amount of fun wink) by not using templates.

Edit: By the way, it's a common misconception that the STL (formerly "Standard Template Library") is just about Templates. It isn't, which is why the "T" is dropped now and it's just called the "Standard Library". It's a collection of classes, algorithms, container classes, and a whole lot more.
One of the best books around is "The C++ Standard Library: A Tutorial and Reference" by Nicolai M. Josuttis.

Edited by JonRB on Saturday 9th June 17:56

dilbert

7,741 posts

233 months

Saturday 9th June 2007
quotequote all
JonRB said:
As a freelancer, if I have a choice between a proprietary way and a standard way (ie. implemented in the Standard Library) then I'll take the latter unless there is a firm business or performance reason not to. Why spend time learning to do something in a way I may not be able to use at another client?

Templates when used to their full are truely mind-blowing. Have a look at "Modern C++ Design: Applied Generic and Design Patterns" by Andrei Alexandrescu for pattern-based programming including Template Template Parameters (not a typo) which implement Policies and Traits that modify the behaviour of the whole class. Absolutely awesome what you can achieve - ie. allow a decision to be taken at compile-time as to whether to be tread-safe or not (by choosing not in a single-threaded environment you can made performance gains by not even compiling in thread synchronisation let alone use it - maximum runtime performance)

He even gives examples of how to implement compile-time asserts which are brilliant for library code as you can trap improper use at compile time with no runtime hit at all.

I've written some really funky template-based stuff only recently that uses generic programming with "exceptions to the rule" handled by explicit template specialisation.

I'd really recommend looking into it - you're missing a world of power (and a huge amount of fun wink) by not using templates.

Edit: By the way, it's a common misconception that the STL (formerly "Standard Template Library&quotwink is just about Templates. It isn't, which is why the "T" is dropped now and it's just called the "Standard Library". It's a collection of classes, algorithms, container classes, and a whole lot more.
One of the best books around is "The C++ Standard Library: A Tutorial and Reference" by Nicolai M. Josuttis.

Edited by JonRB on Saturday 9th June 17:46
I'm quite aware of the whole business of what technologies a customer may wish to accept into his product. That one works both ways. You graft, sell a bit of your time to someone else, and they sell awhole pile of your previous effort to someone else under their name!

I've done more VHDL than I've done C++. In fact that's really what I know about. Nobody would recruit me as a software engineer. I don't know anything.

In VHDL the whole premise is that of scalable parallel design. Its a concurrent language where every single class object is primarily a stately thread object. A single object would typically be a mathematical function, or maybe a pipeline management function to manage and keep synchronized, calculations which take different lenghths of time. That stuff is great. The generic nature is fundamental. You build a multiplier, and it must be scalable..... Did you want an 8 bit multiplier, or a 16 bit one?

Its important because it's not just time that's important, but physical space (man). smile

Apart from the few important things that templates couldn't do for me (or were so complicated I couldn't figure them out), I also think that they're mostly overkill for your average application. The only time I have ever thought that templates would be useful in C++ was for my structural stuff, but in practice it didn't work out for them.... Not that I think they're bothered!!! smile

Edited by dilbert on Saturday 9th June 18:19

JonRB

Original Poster:

75,191 posts

274 months

Saturday 9th June 2007
quotequote all
Looks to me like we're in totally different problem domains, dilbert, and that in yours templates don't really contribute much. That's fine - it's just another example of the depth and breadth of the language.

However, for application-level programming, templates can be very, very powerful.

GreenV8S

30,269 posts

286 months

Saturday 9th June 2007
quotequote all
Doing it yourself from the ground up is very satisfying, but if you're reinventing basic data structures such as lists, maps, virtual arrays and so on, you have to look long and hard to make sure you aren't suffering from Not Invented Here syndrome.

dilbert

7,741 posts

233 months

Saturday 9th June 2007
quotequote all
JonRB said:
Looks to me like we're in totally different problem domains, dilbert, and that in yours templates don't really contribute much. That's fine - it's just another example of the depth and breadth of the language.

However, for application-level programming, templates can be very, very powerful.
Over the last hour or so I think the specific problem that I had with templates became clearer. I think the problem that I have with them is that template "type" is specified at compile time, and not runtime. So for example if you want to serialize a template object from storage then you have to write your code in such a way as to create an instance wrapper of a normal fixed type class, that creates and owns a template class appropriate to the serial data.

I guess I figure that if you are normally going to be dealing with objects, rather than groups of "struct" data then you can take advantage of virtual functions to handle serialization, object creation destruction, and so on. Interestingly these are all of the things that many people hate about C++..... I wonder why????? Overall I don't actually need the templates, because virtual functions do most of it for me.

It definately leaves a small problem. That is that I can't create a list appropriate to a struct type. I cover this situation which is not uncommon, but not bad enough to be significant, with a generic container class. In my environment I solely use "typedef struct", and use that as an accessor or template to a generic standard object which takes a "sizeof(template)" in the constructor.

I also have a OLE/COM style VARIANT type, but I rarely use it!

It's not what I would prefer, but it's not terrible.

You can argue that my approach is not so good when it comes to things like sort and such, but that I handle in a different way. If you used a template to sort some data, you'd have to define an operator specific to that type, anyhow.

I manage that problem by defining the sort operator as a funtion. When you call the sort, you pass a pointer to that function as an argument.


dilbert

7,741 posts

233 months

Saturday 9th June 2007
quotequote all
GreenV8S said:
Doing it yourself from the ground up is very satisfying, but if you're reinventing basic data structures such as lists, maps, virtual arrays and so on, you have to look long and hard to make sure you aren't suffering from Not Invented Here syndrome.
I'd agree with that.... I think I do suffer from that. I have re-invented the wheel to a certain extent. It's a pretty fair criticism.

I think all I would say is that there is plenty that MS and others have done, that really is great. Period. But there are parts of it, that leave most people (including me) reeling thinking that it's pain beyond belief. I just say that it doesn't have to be that way, and why ditch all the good stuff, with all the bad stuff!!!

I wouldn't want to take someone elses commercial product, it could never be mine. I do want those things of theirs that I like. Going back to the whole change issue. People have criticised me (not here) for being unwilling to change. The thing is that you can change things, make them better, and still have the thing "look and feel" familiar. Often that's a harder change than starting again from scratch. You have to figure out how to achieve a specific thing, rather than advertise what you got at the end as being the next best thing.

That's what I call hitting the spot. Not everybody is going to have the same vision of where that spot is.

Edited by dilbert on Saturday 9th June 19:23

JonRB

Original Poster:

75,191 posts

274 months

Saturday 9th June 2007
quotequote all
dilbert said:
Over the last hour or so I think the specific problem that I had with templates became clearer. I think the problem that I have with them is that template "type" is specified at compile time, and not runtime. So for example if you want to serialize a template object from storage then you have to write your code in such a way as to create an instance wrapper of a normal fixed type class, that creates and owns a template class appropriate to the serial data.
Actually, I've written some pretty funky object serialisation code, and a sockets transport layer to go with it, that makes heavy use of templates. Worked very well and the beauty of it is that it makes the compiler do a lot of the work for you so that it effectively auto-extends. If a class it doesn't know can be serialised in terms of what it does, then it works. Otherwise you get a compile-time error which forces you to address the issue.

I wish I could show you the code, but it's not really possible right now for various NDA / business reasons.

dilbert

7,741 posts

233 months

Saturday 9th June 2007
quotequote all
JonRB said:
dilbert said:
Over the last hour or so I think the specific problem that I had with templates became clearer. I think the problem that I have with them is that template "type" is specified at compile time, and not runtime. So for example if you want to serialize a template object from storage then you have to write your code in such a way as to create an instance wrapper of a normal fixed type class, that creates and owns a template class appropriate to the serial data.
Actually, I've written some pretty funky object serialisation code, and a sockets transport layer to go with it, that makes heavy use of templates. Worked very well and the beauty of it is that it makes the compiler do a lot of the work for you so that it effectively auto-extends. If a class it doesn't know can be serialised in terms of what it does, then it works. Otherwise you get a compile-time error which forces you to address the issue.

I wish I could show you the code, but it's not really possible right now for various NDA / business reasons.
All the best things are secrets!!
smile

IainT

10,040 posts

240 months

Saturday 9th June 2007
quotequote all
dilbert said:
I'm no top level cross technology guru, but there is a question that I have, and it relates to the underlying compute support that all of these languages depend on.

Clearly the primary drive for languages like Java, C# and so on are not so much ease of memory management, but cross platform compatibility. I'd have thought that's the no brainer. That's the thing that a C++ devotee like myself cannot argue with. In truth, there is no reason why C++ couldn't be a translated language. Depending on your view you could argue that C# is just that. Fortunately it has a different name.

My question though relates to the way in which processor technology is developing. The highest end microprocessors are now commonly dual core. One has to consider why. My iterpretation is that the drive for performance is still there, but the constraints of silicon, mean that it's difficult to bring them in a single microprocessor core. It's a pretty surefire thing that the future is multiprocessor, and in real terms it's already here.

If you're going to use two cores efficiently then the code has to be written in such a way that the tasks can be distributed, and this is something that is still proving to be a challenge in many software development arenas. The thing is though that if you never delete an object because it's all taken care of for you, you never really know who owns it. In a single thread that doesn't matter. In two threads on the same processor it probably doesn't matter. In two threads on different processors it really does matter.

So my question relates to the future of Java from the perspective that it may be inherently difficult to use it to take advantage of multiprocessor technologies. I don't use it, so I'm not sure. What I am sure about is that MS offer a product which has the platform independance capabilities of Java without the hideyhole approach to memory management. Clearly my money is going to be on that as a future development platform.

My question, however, is can Java compete at all in a multiprocessor world? If it can; Can it do so as it is now, or must it change?
It ceratinly does compete in the multiprocessor arena in the context of application tiers serving many simmultaneous requests. It also competes (I think compete isn't the right word but 'exists successfully' is a little verbose!) in a distributed world. Indeed this is the arena where it's strengths come to the fore.

Management and ownership of objects is rarely an issue.

Programming in a way that is inherantly more efficient in a multiprocessor world is more, imho, about the discipline of the developer and their understanding of the requirements of such a program that the language.

Multiprocessor tasks running asynchronously take a certain finesse to not come unstuck!

Saying that in my current arena (web apps) the individual requests generally take a relatively short time to service and multiprocessor boxen (and clusters of them) allow more requests to be serviced concurrently. It's rare for me to need to split an individual task up to run in multiple threads to perform adequately. So what do I know?

dilbert

7,741 posts

233 months

Saturday 9th June 2007
quotequote all
IainT said:
dilbert said:
I'm no top level cross technology guru, but there is a question that I have, and it relates to the underlying compute support that all of these languages depend on.

Clearly the primary drive for languages like Java, C# and so on are not so much ease of memory management, but cross platform compatibility. I'd have thought that's the no brainer. That's the thing that a C++ devotee like myself cannot argue with. In truth, there is no reason why C++ couldn't be a translated language. Depending on your view you could argue that C# is just that. Fortunately it has a different name.

My question though relates to the way in which processor technology is developing. The highest end microprocessors are now commonly dual core. One has to consider why. My iterpretation is that the drive for performance is still there, but the constraints of silicon, mean that it's difficult to bring them in a single microprocessor core. It's a pretty surefire thing that the future is multiprocessor, and in real terms it's already here.

If you're going to use two cores efficiently then the code has to be written in such a way that the tasks can be distributed, and this is something that is still proving to be a challenge in many software development arenas. The thing is though that if you never delete an object because it's all taken care of for you, you never really know who owns it. In a single thread that doesn't matter. In two threads on the same processor it probably doesn't matter. In two threads on different processors it really does matter.

So my question relates to the future of Java from the perspective that it may be inherently difficult to use it to take advantage of multiprocessor technologies. I don't use it, so I'm not sure. What I am sure about is that MS offer a product which has the platform independance capabilities of Java without the hideyhole approach to memory management. Clearly my money is going to be on that as a future development platform.

My question, however, is can Java compete at all in a multiprocessor world? If it can; Can it do so as it is now, or must it change?
It ceratinly does compete in the multiprocessor arena in the context of application tiers serving many simmultaneous requests. It also competes (I think compete isn't the right word but 'exists successfully' is a little verbose!) in a distributed world. Indeed this is the arena where it's strengths come to the fore.

Management and ownership of objects is rarely an issue.

Programming in a way that is inherantly more efficient in a multiprocessor world is more, imho, about the discipline of the developer and their understanding of the requirements of such a program that the language.

Multiprocessor tasks running asynchronously take a certain finesse to not come unstuck!

Saying that in my current arena (web apps) the individual requests generally take a relatively short time to service and multiprocessor boxen (and clusters of them) allow more requests to be serviced concurrently. It's rare for me to need to split an individual task up to run in multiple threads to perform adequately. So what do I know?
I only ever write doggy slow stuff that need splitting into thousands of concurrent threads!!! (None of it's true I tell ya!!) smile

There have only been a couple of things that I've done that really have needed to run this way, but when you do it, you have enough trouble already on your hands that you just want it to work. I hear what you're saying about distributed apps on separate boxes, but I'd guess there is a tendency not to have one application interfere with another. There's a socket in the way, No?

I've done some thinking about the whole Garbage Collection theme as a result of this thread, and that's a good thing for me, hope you've all been able to put up with it!!! In principal it must be faster. There's no way around that. You're making half as many calls to the memory manager. Crazily, on Wiki the example they use is probably the only one where a standard approach has a chance of keeping up. And it still doesn't (apparently).

This business of inspecting the call stack for visibility of objects is an interesting one. I cant imagine having to try and write that code!!!! "Stop the world" doesn't sound too good though, like a self imposed return to polling.

Just to be P.C......

What do I know!smile

Edited by dilbert on Saturday 9th June 20:01

IainT

10,040 posts

240 months

Saturday 9th June 2007
quotequote all
dilbert said:
I've done some thinking about the whole Garbage Collection theme as a result of this thread, and that's a good thing for me, hope you've all been able to put up with it!!! In principal it must be faster. There's no way around that. You're making half as many calls to the memory manager. Crazily, on Wiki the example they use is probably the only one where a standard approach has a chance of keeping up. And it still doesn't (apparently).
Interesting (if you're a geek like me) aside...

We were having some significant issues running our GIS rendering sub-system on a bigish Sun box - T2000 or some such.

After a lot of to-ing and fro-ing one of their super-mega-Special consultants jetted in (from deepest Wales), did some Black Magic and produced a lovely graph of Java's VM and it's usage of the standard Malloc calls (from libc.so IIRC). The scan was over a very brief period of activity but showed the VM making a massive number of calls to allocate tiny blocks of memory, 16 byte chunks. This size of allocation was some orders of magnitude greater than for any of the other byte-sizes.

Becasue Malloc is thread safe this meant a huge ammount of time was spent waiting on the library. We changed to a different malloc library (muti-threaded and memory resident) and gained about 250% performance boost.

In the end we ditched the T2k though - 1 FPU between 32 'cpus' doesnt' work for rendering images!

Ditched the Sun hardware in favour of intel for the rendering in the end - you can't swap any amount of clever architecture for clock cycles when it comes down to number crunching.

PS. My 'what do I know' was genuinely intended to indicate that I'm a long way from expert on the subject and generally might know jack!

dilbert

7,741 posts

233 months

Saturday 9th June 2007
quotequote all
IainT said:
dilbert said:
I've done some thinking about the whole Garbage Collection theme as a result of this thread, and that's a good thing for me, hope you've all been able to put up with it!!! In principal it must be faster. There's no way around that. You're making half as many calls to the memory manager. Crazily, on Wiki the example they use is probably the only one where a standard approach has a chance of keeping up. And it still doesn't (apparently).
Interesting (if you're a geek like me) aside...

We were having some significant issues running our GIS rendering sub-system on a bigish Sun box - T2000 or some such.

After a lot of to-ing and fro-ing one of their super-mega-Special consultants jetted in (from deepest Wales), did some Black Magic and produced a lovely graph of Java's VM and it's usage of the standard Malloc calls (from libc.so IIRC). The scan was over a very brief period of activity but showed the VM making a massive number of calls to allocate tiny blocks of memory, 16 byte chunks. This size of allocation was some orders of magnitude greater than for any of the other byte-sizes.

Becasue Malloc is thread safe this meant a huge ammount of time was spent waiting on the library. We changed to a different malloc library (muti-threaded and memory resident) and gained about 250% performance boost.

In the end we ditched the T2k though - 1 FPU between 32 'cpus' doesnt' work for rendering images!

Ditched the Sun hardware in favour of intel for the rendering in the end - you can't swap any amount of clever architecture for clock cycles when it comes down to number crunching.

PS. My 'what do I know' was genuinely intended to indicate that I'm a long way from expert on the subject and generally might know jack!
No problem with the the footnote... I was beginning to think people were talking about the size of my head. Just trying to ensure that the discussion didn't turn into a PC battle as well!!! smile

16 bytes, blimey, that sounds a bit scary. I'd have thought it would grab a meg and work with that for a bit. On the MS platform you link with various versions of the standard c libraries depending on your requirement for debug and thread support.

Funnily enough when I did my heap, it started with me looking at a problem with the msize() function. I wnated to be able to strip the core out of my string class, so that I could list many thousands of lines, without having the size overhead of all the indexes and other things associated with string manipulation, n each line. Clearly you want the capability, but not on every line all the time. All the associated data takes up loads of space. I didn't want to have to copy the character data twice, each time I wanted to perform a manipulation on it.

The solution was to allow a rip of the string buffer, out of the string object, and a dump back. The manipulation data is only instanced once, you can list the strings, and manipulate them when you want. The trouble was that I needed to know the size of the string, because parsing the length would have defeated the object.

I suppose that I could have put the length at the beginning of the buffer, but that also seemed to defeat the object. msize() ought to tell you the allocation size of the block that you have. Sadly, it only worked properly for me when linking with the debug library. I found the simple windows platform heap functions but they were way slow for anything less than a couple of megs at a time......

Hence the creation of the heap. At the time I wondered if I was doing the right thing by doing the work. I think at the time the frustration of the size issue was the driving factor, but I also had designs on providing better debug support than I'd had before. Having fine control of the heap now is a godsend. I wouldn't want to go back. As a whole I think it took about a week and a half, possibly two with testing. That was about a year ago.... Found a few problems as I've gone along but I don't really have the luxury of intense testing.

I'm surprised that if you're doing "industrial rendering" you're not using a full on pixel pipe, from SGI or somesuch, and maybe OpenGL. Come to think of it, does not the JVM ALU work on some crazy operand stacking scheme?

Edited by dilbert on Saturday 9th June 23:35

Size Nine Elm

5,167 posts

286 months

Sunday 10th June 2007
quotequote all
dilbert said:
Nevertheless, I've got enough vested in my own structural components that it would be an immense pain to migrate. I can't at the moment identify anything that I need to do that I can't, so why change. In fact it's likely that if I do need something of theirs, I'll understand what they did, and do my own. The reality is that I already have everything that they offer that I would want, and it's integrated with loads of suff that I do want, and they don't offer.
GreenV8S said:
Doing it yourself from the ground up is very satisfying, but if you're reinventing basic data structures such as lists, maps, virtual arrays and so on, you have to look long and hard to make sure you aren't suffering from Not Invented Here syndrome.
And also note that 'Standard is better than better'. It doesn't matter if the libraries you are coding turn out to be marginally better than a standard library for some purpose, because adhering to a standard is immesurably better in terms of communicating design and intent.

Unless for whatever reason you've achieved a 10x improvement in space/time for a particular application...

dilbert

7,741 posts

233 months

Sunday 10th June 2007
quotequote all
Size Nine Elm said:
dilbert said:
Nevertheless, I've got enough vested in my own structural components that it would be an immense pain to migrate. I can't at the moment identify anything that I need to do that I can't, so why change. In fact it's likely that if I do need something of theirs, I'll understand what they did, and do my own. The reality is that I already have everything that they offer that I would want, and it's integrated with loads of suff that I do want, and they don't offer.
GreenV8S said:
Doing it yourself from the ground up is very satisfying, but if you're reinventing basic data structures such as lists, maps, virtual arrays and so on, you have to look long and hard to make sure you aren't suffering from Not Invented Here syndrome.
And also note that 'Standard is better than better'. It doesn't matter if the libraries you are coding turn out to be marginally better than a standard library for some purpose, because adhering to a standard is immesurably better in terms of communicating design and intent.

Unless for whatever reason you've achieved a 10x improvement in space/time for a particular application...
Who me?


IainT

10,040 posts

240 months

Sunday 10th June 2007
quotequote all
dilbert said:
I'm surprised that if you're doing "industrial rendering" you're not using a full on pixel pipe, from SGI or somesuch, and maybe OpenGL. Come to think of it, does not the JVM ALU work on some crazy operand stacking scheme?
"Industrual rendering" is far too grand (and interesting sounding) for what is basically drawing maps. The main overhrad is actually fetching the map data from the database. Rendering is about 40% of the elapsed time from request to response.

Java has some nice touches in it's gfx libs - like using native OS functionality (OpenGL predominantly) and the benefits therein.

Again, a black box to be used to meet a requirement without needing to gain expert knowledge in every sub-system just to make it tick.

App developers, imvho, should be focussed on delivering the business requirements. We can happily leave the development of the architectural components to people who like to get their hands dirty writing custom stacks and the like smile