Runtime performance is one of many desirable properties of a computer language. How fast will programs written in the language run? This page explores two assertions about language design with respect to economy of execution...
Typical examples of object-oriented languages that perform well are C++ and Ada'95 where one can have highly flexible structures (templates, parameterized classes) without paying in execution performance.
On the other end you have Java , Smalltalk, Python. These languages defer type based decisions until runtime. Although just in time compilers are supposed to fix this issue in theory, in practice it doesn't quite happen.
Statement level performance varies over many orders of magnitude from VHDL (which compiles to hardware) to shell script (that forks a task to add two numbers). Performance can be so important that people will even argue over rather small increments as in the discussion on this page.
My experience, after 20 years or so of application development experience in Smalltalk, C-based OO languages (C++, Objective-C, ObjectC, etc), Java, and so on, is that the claimed performance advantages of "strict static type checking" are less compelling when deployed than those cited here. Here's why:
On the other hand, I don't think there's enough convincing evidence of a corelation between the EconomyOfExecution and either EconomyOfSmallScaleDevelopment? or EconomyOfLargeScaleDevelopment? (the two notions Cardleli uses for EconomyOfImplementation?). What you mentioned here is anecdotical evidence. The reason for BadEngineeringPropertiesOfOoLanguages was to call for more research and implementations towards better languages, not to set existing ones in stone. I don't think that adopting a "Smalltalk is all we need and all there ever needs to be" approach is particularly helpful or justified. The reason for this page wasn't to bash Smalltalk nor to glorify C++. -- CostinCozianu
Regarding anecdotal evidence: Take a second read of the article. It's one big anecdote.
Mostly type information is used for instruction selection. C++ can make use of a floating point register for a temp because it knows the temp will always be a float. Smalltalk moves the temp data back and forth from memory. (Some lisps select instructions just as well but they have been rejected for reasons discussed elsewhere. See WhyWeHateLisp) Type information can also improve performance because...
There are different trade-offs that various statically-typed languages took, Java being a prime example. For example the project disasters related to C++ are mainly due to the liberal use of pointers and memory management, which are related to EconomyOfExecution, but are not related to StaticTyping.
But it is still unclear if there's anything inherent to StaticTyping that prevents whatever desirable properties you see in dynamically typed languages. Languages such as ML and its variants tend to prove the opposite.
Java has static type checking but JavaTypingWasSimple. This has all kind of benefits, but it also leads to loss of typing (ask yourself how many times have you used the cast operator lately) and consequently it hurts EconomyOfExecution because all kinds of checkings have to happen at run-time and because the optimizer (even if it is inside the just in time compiler/HotSpot ) is prevented from doing its job well.
A cast operator is part of every static-typed language I'm aware of (even Eiffel has one), and is one of the reasons why so few commercial static-typed language compilers actually use the static typing information for anything useful. The presence of the cast operator means that runtime checks have to happen anyway, and the runtime checks of C++ or Java are not inherently any faster than those of Smalltalk. -- TomStambaugh
The fact that there is a cast operator, doesn't mean you have to use it. In Java, yes, you really have to. But in C++ you have to deal with exceptionally rare situations to have to actually use a dynamic_cast, some authors even question the usefulness of the dynamic_cast operator. The same applies to Ada and many other languages.
Let me beat the carcass of this dead horse a little more. The fact that there is a cast operator means that the compiler has to take it into account, whether or not the developer uses it. Thus, the compiler has to emit code that does something predictable at, for example, code position "A" (such as an assignment) when an incorrect casts occur at code position "B" (such as inside an independently compiled module). The effort to reliably sort out what can and can't occur at runtime causes most commercial vendors to walk away from the whole problem. The result is that the overall EconomyOfExecution for real applications that work is about the same for modern commercial implementations of Smalltalk, C++, and Java. -- TomStambaugh
Tom, I think the burden of proof is on you. Come up with a practical example, cite a relevant study or something, but don't just state something you believe to be true, while it's common sense that it isn't. C++ compiler doesn't insert anything at point A to catch a bad cast at pont B, on the contrary, the most likely behaviour in such a situation is a total program crash. The only' thing that might slow down a C++ program is setting up exception traps, which can be disabled anyway, by a simple compiler switch. There's also the problem of object allocation and garbage collection, and tons and tons of other things - like the 23 machine instructions that I got in ComplexNumberTest. Can you back your claim with some real evidence ? Just spear us of the real applications that work. I've done a few real applications that work in C, C++, DelphiLanguage and BorlandPascal?, developing in any of these languages (without garbage collection, dynamic typing and the goodies of Smalltalk) ain't the nightmare that smalltalkers would like us to believe it is. On the contrary, it is very enjoyable. -- CC
Excuse me, Costin, but I'm responding to two assertions, from above:
Tom, what you call assertions are common places in ComputerScience. There's no point in debating these with you unless you come up with new evidence or new ideas. Who's talking of proving the negative ? What is your experience, what have you measured ?
I don't doubt that you have written real applications in C, C++, DelphiLanguage, and BorlandPascal?. So have I. The claim I dispute is YOUR implied claim that those applications would have had worse performance had they been written in Smalltalk (I agree with you that Java would have KILLED them... :)). If the strongly typed compiler of your choice in a language that includes casts really DOES blindly execute an operation without checking types as you argue it should, I argue that for an application of any complexity, you will see a large amount of unexplained, apparently random application crashes -- precisely the reliability problem that strong-typing is alleged to "solve". And if you ALSO skipped the garbage collection, I'll bet your applications also had core leaks and a whole different set of apparently random failures caused by dereferencing stale pointers created the effort to avoid the "overhead" of the garbage collector. If you REALLY mean that you ship code with BOTH unchecked casts AND manual storage management, I would respond that you make my argument for me more effectively than I can make it myself. tms
You can dispute no matter how much you want, but please try to come up with 23 machine instructions in ComplexNumberTest.
I agree that we should continue this discussion in ComplexNumberTest. Please see my additions to that page. -- TomStambaugh
And about my compiler, it doesn't execute blindly, it proves at compile time, because you usually don't use dynamic_cast in C++. Even in case you do use dynamic_cast, only yhen it inserts a check at runtime. Let's get serious and delete this crap, shall we ?
Using dynamic_cast<> whenever I might be tempted to use a C-style cast was ingrained into me by days upon days of wasted time debugging what turned out to be "slicing" problems on a largish C++/MFC project. I find it hard to believe that the contributors on this page who speak from experience with C++ won't at least acknowledge that C-style casting can lead the unsuspecting OO programmer into serious trouble.
A C-style cast has the effect of adding an axiom to the compiler's "proof" system. If you add a false axiom, then you should expect to get false conclusions. DontDoThat!
Tom, I respect your opinion in matters of Smalltalk usually, but you are really wanking it here. Most Smalltalks are one tenth the speed of C. DaveUngar?, because he's amazing, pushed Self to one half the speed of C years and years ago. Worse, C++ is faster than C because it has more tricks to pull. And your whole claim that casting costs in C++ is totally bogus. I know how much a cast costs because I spend all day measuring the impact of various C++ expressions against a variety of compilers on a variety of platforms using a variety of processors. The only thing you have to worry about when casting is integer extension and calls to emulated 32-bit multiplies and divides. Unless you are using dynamic_cast<>, but dynamic_cast<> is evil. -- SunirShah
Let's continue this discussion at ComplexNumberTest, and focus it on real stuff. -- TomStambaugh
I spend all day measuring the impact of various C++ expressions...
That leave you much time for implementing things with BusinessValue? ;)
Somebody asserted during a refactoring of this page that: Object-oriented principles run counter to performance.
It wasn't clear if the statement itself was asserted, or if the assertion was that the discussion on this page was about that. I believe there's no evidence to affirm that "Object-oriented principles run counter to performance". Please clarify.
While I didn't say that, it's definitely true. Objects boil down to extra level of indirection. Every level of indirection slows you down. -- SunirShah (unless it's resolved at compile-time, as for C++ templates -- DaveWhipp).
And speeds you up as well - SlowDownToSpeedUp.