Subj : Re: OO compilers and efficiency To : comp.programming From : Jon Harrop Date : Wed Jul 20 2005 03:32 pm I've gained most of my knowledge about this from a ray tracer that I wrote recently in C++, Java, SML and OCaml: http://www.ffconsultancy.com/free/ray_tracer/languages.html There is a direct comparison of the C++ and OCaml here: http://www.ffconsultancy.com/free/ray_tracer/comparison.html I'll refer back to those pages. Chris Dollin wrote: > Jon Harrop wrote: >> Yes. The OO implementations of many useful constructs (e.g. closures and >> variant types) are certainly many times more verbose and, I suspect, it >> will be difficult for a compiler to do a good job of spotting when the OO >> is actually implementing something quite simple. > > I believe the OP was rather coming from the other direction, ie from > "simpler" languages, or at least simpler idioms. Perhaps. He certainly spoke of C but also spoke of OO in more generic terms. I took the OP to mean that pure OOP leads to unnecessary inefficiencies in many cases. > I agree that (eg) Java > makes a right pigs ear of closure-like objects, but that isn't because > it's OO, it's because it's Java. The representation of closures in C++ is very similar to that in Java (i.e. an object with a single method). > Making methods first-class values > (including adding lexical closures) and adding lambda-abstractions > (or "blocks") doesn't appear to me to conflict with the OO style. I agree. > [I happen to think subclassing is nicer than "variant types", but > I may be thinking of the wrong notion fo "variant type" - old echoes > from Pascal, rather than notions like existential types etc; which > did you mean?] Something like: type scene = Sphere of sphere | Group of sphere * scene list >> For example, I'd bet that languages with built-in support for closures, >> e.g. SML and OCaml, handle them vastly more efficiently than only-OO >> languages, e.g. C++ and Java. > > I'm not convinced about `vastly`. EG one representation of a closure > is as a freshly-allocated chunk of memory with references to the > closed-over variables and a pointer to the underlying function; this > chunk is typed as a function. > > If you immitate a closure in Java, you use a freshly-allocated object > with references to the closed-over variables Probably copies of the closed over values (referential transparency!). > and is of a class which > has an agreed method to call to run the underlying function. > > There's unnecessary plumbing, I'll grant; are we talking more than a > factor of 2 here? Ish? I'd expect SML and OCaml to be up to 5x faster than Java. >> From a performance point of view, the evidence seems to suggest "probably >> better _not_ a JIT" as Java is rarely as fast as C++ and is often several >> times slower. > > Pass on the evidence - but I'd write a JIT rather than a compiler, if > I could, because I'd have access to more information. Objectively, most new compilers are still static rather than JIT. >>> * OO languages typically [ie, Java] come with GC. C doesn't. >> >> OO programs will often be written in C++ and, consequently, often lack >> GC. > > I don't count C++ as an OO language; I think that puts you in the minority. :-) > I count it as a multi-paradigm > language that, as a consequence, suffers in each of its paradigms from > the presence of the others. (And benefits, but in different places.) I certainly don't see OO as all-or-nothing. >> Many other languages gain this ability without >> need of OO (e.g. SML) and some combine many features (e.g. OCaml). >> Despite the theoretical space saving of OO, Java is one of the most >> verbose languages. > > (Source code or compiled code size? Your use of "verbose" ambiguated > me.) Source code. >>> (What the OO program loses in GC costs is roughly >>> the same as what the C program loses in memory-management >>> costs, eg copying.) >> >> Again, this point is invalid simply because there is no logical >> correspondance between OO and GC. > > I don't believe this to be true; you may take this just as one of > my religious beliefs - if you don't have GC-style storage management, > you don't have OO. You may have /pieces/ of OO, of course. A garbage collector simply collects garbage data. It doesn't care if that data corresponded to an object in the HLL. GC and OO are orthogonal. >> If OO makes it impossible to perform optimisations in the general case >> then the intelligence of the OO compiler writer's is unimportant - OO >> will necessarily lead to slower code in general. > > The premise is unloaded, and the conclusion in any case uncertain. > ["Not implemented" doesn't imply "impossible"; it may just be "not > in our preferred domain"; and worse general-case optimisation may > be trumped by algorithmic improvements made possible by the OO > structuring. No, I don't have any numbers either.] Can you give any examples of "algorithmic improvements made possible by the OO structuring"? >> This certainly appears to be the case with Java, where object-intensive >> code is several times slower than the equivalent C++/SML/OCaml. For >> example, when dealing with 3D vectors. The solution is to code your Java >> as you would code in C, which takes you right back to square one. > > For what values of "equivalent" in the first sentence? Programs solving the same task using the same algorithm, e.g. my ray tracer. > I don't doubt > that if you make lots of new objects you will do worse than if you > don't have to create them. As Java forces you to use OO, the Java implementation of my ray tracer allocates and deallocates millions of unnecessary objects. In contrast, the C++ object is nothing more than a struct and the SML and OCaml choose to use a variant type. Consequently, the Java is up to 5x slower. A masochist can rewrite the OCaml to use an object for each 3D vector. The OCaml is then also very slow. But this is "unnatural" OCaml code. There is no elegant way around the performance bottleneck of objects in Java. >> However, OO is a poor example of something which allows the compiler to >> perform signficantly more effective optimisations. For example, the >> common constructs I mentioned earlier are obfuscated beyond recognition >> when shoehorned into OO. > > I think "common" is pushing it rather - The C++ STL certainly contains a lot of code related to "closures". When I used to code in C++, I often made use of flat inheritance hierarchies (variant types). Indeed, an OO inheritance hierarchy is the natural representation of a scene in the ray tracer for both the C++ and Java implementations. >> If you want to write efficient, non-trivial code then you should start by >> looking at the big picture (algorithms) and not details like bit >> twiddling in C. > > It's nice to end on a note of agreement. :-) -- Dr Jon D Harrop, Flying Frog Consultancy http://www.ffconsultancy.com .