News for hackers. Stuff that matters.
Re:Object Oriented Programming is Inherently Harmful by tomp on Sunday November 30, 2014 @11:34AM (#8677177)
Also: polymorphic dispatch is faster with OO (which is what Rust/Servo people have been figuring out recently).
Re:Object Oriented Programming is Inherently Harmful by Jweb_Guru on Wednesday December 03, 2014 @07:48PM (#8697283)
Not really. At best, dynamic dispatch might be faster with inheritance, but even that's kind of a stretch. Most of the slowness with using trait objects in Rust has little to do with the dispatch itself, but with casting between the types being relatively inefficient and/or unsafe (for a whole host of reasons which also affect other parts of the language).

In any case, dynamic dispatch, polymorphic or not, is considerably slower than static polymorphic dispatch, which Rust excels at. Servo's biggest performance wins over Gecko (outside of pervasive parallelism) have come by greatly reducing dynamic dispatch.

Re:Object Oriented Programming is Inherently Harmful by tomp on Thursday December 04, 2014 @08:17AM (#8699063)
But, how often is it that dynamic dispatch can be optimized into static dispatch? I imagine it probably cannot be done with most of DOM handling... Isn't Rust's static polymorphic dispatch more-or-less equivalent to what you can do in C++ with templates?
Re:Object Oriented Programming is Inherently Harmful by kibwen on Thursday December 04, 2014 @12:51PM (#8700529)
For a long time there were Servo devs pushing for Rust to feature struct inheritance in order to safely and efficiently implement the DOM. Various proposals were written and prototypes implemented, but they all received criticism from the community (often of the form "this seems like a feature that solves a problem that only Servo will ever have") and no single proposal was a clear winner over the others. Today the Servo devs hack around the issue via `unsafe` blocks and transmuting things willy-nilly, but they're still dissatisfied with it.

I expect the issue to be revisited post-1.0. In the meantime, if you'd like to familiarize yourself with some of the proposals, here's a recent-ish summary and discussion: http://discuss.rust-lang.org/t/summary-of-efficient-inherita...

Re:Object Oriented Programming is Inherently Harmful by tomp on Thursday December 04, 2014 @01:10PM (#8700650)
Right... I'm partially familiar with the development, but AFAIK, the basic goals are basically thin pointers and cheap dynamic dispatch using v-tables, not elimination of dynamic dispatch in favor of static dispatch.
Re:Object Oriented Programming is Inherently Harmful by kibwen on Thursday December 04, 2014 @02:07PM (#8701000)
My goal was to emphasize that you are correct that not all useful instances of dynamic dispatch can be reduced to static dispatch. With regard to the DOM specifically, however, there is some concern that the structure itself was designed and standardized such that it can only be implemented efficiently by assuming some sort of inheritance scheme, effectively baking the typical OO approach into the web standard. Opponents of inheritance being added to Rust have claimed that this is a unique case, and that such a feature would not pull its weight in any non-DOM scenarios (or worse, that it would be redundant with Rust's trait system and that you would fall into C++'s trap of nobody agreeing on which subsets of the language to use). Given the nebulousness of the proposals in this space, I have no dog in this fight at the moment.

My other goal was to show that Rust gives you enough tools to manually emulate an efficient inheritance-style dynamic dispatch scheme, even if it can't fully prove that your implementation is safe.

Re:Object Oriented Programming is Inherently Harmful by vardump on Sunday November 30, 2014 @01:00PM (#8677465)
Yes. If you can generate code on the fly [1], you can handle a subset of cases very efficiently.

[1]: JIT. Just in case some people confuse concepts, I'm not talking about JVM, virtual machines and such. Just plain runtime machine language generation.

Re:Object Oriented Programming is Inherently Harmful by tomp on Sunday November 30, 2014 @02:13PM (#8677728)
The problem with JIT is that it's not very simple. Sure, you can write your own single-purpose runtime-code-generating routine. But the beauty of OO is that it's widely applicable. If you want to achieve comparable speeds with JIT, you pretty much need some sort of a virtual machine; in particular, simple method-at-a-time JITs are not very efficient; you need some sort of measuring or tracing, so that you know what code to compile and how to optimize it.
Re:Object Oriented Programming is Inherently Harmful by vardump on Sunday November 30, 2014 @03:34PM (#8677986)
Sure high performance generic JITs are not simple.

NOTE: Following is meant for dynamically dispatched lightweight methods, like those that just read (or compare) or store (or modify) some simple field value or do other simple operations where dispatch and call frame setup costs dominate. In inner loops which are executed enough many times that the codegen overhead is less.

The rationale is that branches are very expensive on modern CPUs, especially indirect subroutine (= method or function) calls. Consistently 14-20 clock cycles lost in addition to whatever time call frame setup takes, pushing and popping registers from stack. If inner loop cost is otherwise just a cycle or two and the dispatched method is trivial, it's easy to see how branch mispredict and call setup costs can dominate. In some cases some unrolling and prefetching could be done in addition.

In this case I envision routines that fuse (inline) dynamically dispatched (function pointer, message passing, pattern recognition) method inside a loop. A compiler could generate the rules and runtime system can do the actual composition. The method would then be dynamically inlined within the loop. No call, no function pointer call (=vtable), no full pattern recognition, no message dispatch, etc. Just fused, inlined code.

Pattern match can't be completely resolved early? Just generate code inside the loop that does the rest of the work with tests and branches. Try the most likely case always first (may require some profiling). Same with other dynamic dispatch.

Many cases, but known exponential distribution of probabilities? Inline some most likely cases, dynamically dispatch the rest. Like before, most likely first and some profiling may be required.

This way very expensive (data dependent) indirect function call is avoided. Call frame setup and teardown is avoided. The savings can be an order of magnitude for short dispatched methods.

Definitely no complete virtual machine needed.

Note: Edited multiple times.

Re:Object Oriented Programming is Inherently Harmful by tomp on Sunday November 30, 2014 @07:37PM (#8678913)
Hm... not sure if I agree (if I understand this correctly).

If in the inner loop, the same method is called (of the same class), this means that the target of the indirect function call is always the same, and I assume that the CPU can predict that. If not, the compiler can hoist the lookup out of the loop. In certain languages, e.g. in Objective C (where lookups are dynamic, and much more expensive than vtable approach), it's a common programming pattern to manually hoist the lookup out of the loop, get the method descriptor (i.e. the jump target) and call the descriptor in the loop, without going through the lookup again.

If the inner loop loops over objects of different class (i.e. you're looping over an array of objects, each can be a different sub-class, and you're calling a virtual method), I don't think there is any way to improve vtable based approach.

Re:Object Oriented Programming is Inherently Harmful by vardump on Sunday November 30, 2014 @08:38PM (#8679080)
Well, last I checked, the cost for an indirect function call for simple operations was about 5-10x compared to inlining. Each function call constitutes of at least two branches - the call and return. Caller needs to preserve any registers that may be altered by the callee according to ABI conventions. Same for callee.

That is for correctly branch predicted calls.

Far worse for mispredicted calls.

> If the inner loop loops over objects of different class (i.e. you're looping over an array of objects, each can be a different sub-class, and you're calling a virtual method), I don't think there is any way to improve vtable based approach.

Say 90% of the objects are of certain same type and the code generator knows that. Codegen puts the test for this case as first one and inlines the code directly in the loop body. Then you can at least have those 5-10x savings in 90% of cases and have branch mispredicts for the rest of the time. That can still be a significant saving.

Re:Object Oriented Programming is Inherently Harmful by Dewie on Sunday November 30, 2014 @11:43AM (#8677200)
What does 'faster with OO' mean? Is there some implementation detail that is tied to, or heavily associated with, OO?
Re:Object Oriented Programming is Inherently Harmful by tomp on Sunday November 30, 2014 @02:21PM (#8677752)
Method dispatch using a vtable (a pointer, embedded in the object, pointing to a record of methods) is way faster than practically any other form of dynamic dispatch (except calls of known functions, of course). To support it, you pretty much need some form of single inheritance/subtyping (C++ does support multiple inheritance, but it significantly complicates the implementation). Rust's single-dispatch type-classes and Go's interfaces are dispatched in a similar way, but the record of functions is passed along the pointer to object as a "fat pointer". Servo people figured out that that is too wasteful/slow compared to C++-style vtable approach.
Re:Object Oriented Programming is Inherently Harmful by lostcolony on Sunday November 30, 2014 @12:13PM (#8677308)
I assume it's based on (this is a bit hand wavy) the fact that in an OO language, calling the method merely needs to resolve the address space of the method. With pattern matching, you first have to perform the pattern match to figure out what instruction to execute, and then that resolves to an address.

That is, because your data and function are bundled together, having the data means you also know what function to call. Decoupling them, as in a functional paradigm, and passing the data into a pattern match, you have to perform some logic upon the data to figure out what function to apply to it.

Re:Object Oriented Programming is Inherently Harmful by noblethrasher on Sunday November 30, 2014 @12:30PM (#8677361)
But, a series of pattern matching expressions can compile down to a bunch of sealed/final classes that descend from a common base class. In that case, it would still end up using a vtable[1]. I think this is how it works in F# and Scala.

[1] I think that the JITs for the CLR and JVM can do better than vtables in the cases of sealed/final classes.

Re:Object Oriented Programming is Inherently Harmful by seanmcdirmid on Sunday November 30, 2014 @01:53PM (#8677647)
I am sure it doesn't work with way in either scala or F#. You can use classes to represent structure, but the matching is still extrinsic and can't use a table given the flexibility of both languages (you don't just match on class).
Re:Object Oriented Programming is Inherently Harmful by noblethrasher on Sunday November 30, 2014 @02:12PM (#8677725)
Just curious… why not? Isn't a class definition just a type constructor? For instance, if I have a class, Foo, with three types of fields: int, bool, and string, isn't that the same as:

    Foo of int * bool * string
 
I don't have a full PC handy, but, while learning F# a few years ago, I remember using Reflector to analyze an assembly generated by FSC.exe and the pattern match turned into a class hierarchy.

It may not work for all kinds of pattern matching, but that seems like the most straightforward way of handling sum types. What am I missing?

Re:Object Oriented Programming is Inherently Harmful by seanmcdirmid on Sunday November 30, 2014 @07:45PM (#8678942)
I doubt that was what was going on, but I can't find any documentation right now on how F# optimizes case matches. If it was doing that, it would have to apply those classes to all instances of the patterns, which seems unlikely in the face of separate compilation as "Foo of int * bool * string" could be constructed in a far away place. Well, if Foo was a local type that wouldn't escape, perhaps they could optimize it in the module, but it still seems unlikely.

OO languages have trouble optimizing constructs such as interfaces (and other forms of multiple inheritance) because the v-table is no longer very linear. Now throw in arbitrary predicates and you are pretty much back to linear search. Probably the state of the art can be found in GHC, but even they probably fall back to linear in a lot of cases.

Re:Object Oriented Programming is Inherently Harmful by noblethrasher on Sunday November 30, 2014 @08:02PM (#8678976)
Looks like you're correct; I just examined some F# code in LINQPad 4, and the IL has a bunch of `isinst` instructions to check the type at runtime, and no `callvirts` to the one pattern matching expression that I created.

https://gist.github.com/noblethrasher/af1b382fa6e0423bf8bd