Subj : Re: OO compilers and efficiency To : comp.programming From : Chris Dollin Date : Wed Jul 20 2005 07:16 pm Jon Harrop wrote: > > 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. Yummy. I'll try to read those - but no promises, and I'm likely not to be able to feed such reading back into this thread. > 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. His examples were, to my eyes, all of the "less efficient than C" kind. >> 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). I suppose it would be. And the surface syntax would be worse, yes, in the absence of anonymous sub-classes? >> 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. Yippee! >> [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 Oh hells. I'd forgotten to allow for pattern-matching and data declarations. Call it 50/50. > >>> 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!). If you use anonymous sub-classes, then you can refer to final variables of the enclosing method (if any) or instance variables of the enclosing class. Clearly the final variables are anyways not mutable, and I count this as a hack to avoid implementing proper lexical scoping - the programmer has to do the work if they *really* want a variable, pah. If you refer to instance variables, it's the variable, not its value, that gets closed in. (Because what *really* gets closed in is a reference to the instance.) You (and the compiler) and take a copy anyway, this being Java ... >> 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. Just for closures, or in general? Deep gloom. I thought they'd got the performance of Java up better than that. >>> 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. Subjectively, I'd still rather write a JIT. But that's about me, and a taste for incremental compilation fed by years of Pop11. >>>> * 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. :-) Oh, I was already in the minority. It is familiar territory. >>> 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. Happy to agree, then. >> 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. The first two statements are true; the third isn't a consequence of them, it's a separate statement. I don't think of a language as OO if I have to worry about when the object might no longer be referenced. I might have reference polymorphism, as in C++, but I'd still not want to call it OO. As I say - this is my religious position; I don't insist you (or anyone else) adopt it. >>> 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"? Not off the top of my head, which rather weakens the argument. I wonder if I can find actual examples anywhere? >>> 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, Heap-allocated objects, to be specific, yes? > 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. Presumably the Java programmer can write equally unnatural code that avoids creating new objects ... > 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". Does that count as "common"? >> It's nice to end on a note of agreement. > > :-) Grins. -- Chris "electric hedgehog" Dollin It's called *extreme* programming, not *stupid* programming. .