26 Feb, 2008, KaVir wrote in the 21st comment:
Votes: 0
DavidHaley said:
Of course it is negligible. Your reaction is the of the sort that encourages less informed people to think that C++ incurs this terrible performance hit over C.


I explained that there is a difference, but that it is usually negligible for muds. I think that's a far more useful reaction than denying any difference at all - that's just going to confuse people further, because they'll hear conflicting information.

DavidHaley said:
Yes, and if you overload the addition operator, maybe ++i won't actually add anything at all!


I'm talking about correct implementations of the ++ prefix and postfix operators. The former will have a better performance than the latter.

DavidHaley said:
I take your point but I'm just not sure why it's relevant, especially considering that the intention of "i" is pretty clearly to talk about integers…


Or index values, or iterators, or even just as a generic loop counter. It could also be an extremely large integer wrapped in an object, or might in the future be converted into such.

DavidHaley said:
By the way, what kind of performance hit are you talking about – compile-time or runtime? The only justification I ever heard for prefix operators was compile-time, but you made it sound like it was a runtime gain…


The allocation and initialisation of a temporary variable on the stack is done during runtime.

DavidHaley said:
KaVir said:
Once again it'll be negligible, but it's still considered good practice in C++ to use the prefix operators.


I'm curious to hear who establishes this "good practice" and why.


It's mentioned in a number of places, but personally I'd recommend reading the explanation in "More Effective C++", by Scott Meyers.

http://www.podgoretsky.pri.ee/ftp/Docs/C...

ITEM 6. Distinguish Between Prefix and Postfix Forms of Increment and decrement operators.

"If you're the kind who worries about efficiency, you probably broke into a sweat when you first saw the postfix increment function. That function has to create a temporary object for its return value (see Item 19), and the implementation above also creates an explicit temporary object (oldValue) that has to be constructed and destructed. The prefix increment function has no such temporaries. This leads to the possibly startling conclusion that, for efficiency reasons alone, clients of UPInt should prefer prefix increment to postfix increment unless they really need the behavior of postfix increment. Let us be explicit about this. When dealing with user-defined types, prefix increment should be used whenever possible, because it's inherently more efficient."
26 Feb, 2008, David Haley wrote in the 22nd comment:
Votes: 0
KaVir said:
I explained that there is a difference, but that it is usually negligible for muds. I think that's a far more useful reaction than denying any difference at all - that's just going to confuse people further, because they'll hear conflicting information.

You might not think it makes a difference, but you started with a direct correction, and only later confirmed that it was in fact negligible. That is the kind of attitude I am fighting because I think it does people a disservice to think about these issues unless it is extremely relevant to them.

KaVir said:
The allocation and initialisation of a temporary variable on the stack is done during runtime.

So, all you're talking about is the creation of a temporary, and you really don't think that the optimizer should be trusted to deal with that kind of detail? Something about "premature optimization" comes to mind. :wink:

As for actual objects, I already said we weren't talking about that, but POD types…
26 Feb, 2008, KaVir wrote in the 23rd comment:
Votes: 0
DavidHaley said:
You might not think it makes a difference, but you started with a direct correction, and only later confirmed that it was in fact negligible.


I started with a correction because you implied something that wasn't true. Telling people that a problem doesn't exist because you think it's unlikely to affect them is not a good idea.

DavidHaley said:
So, all you're talking about is the creation of a temporary, and you really don't think that the optimizer should be trusted to deal with that kind of detail?


I explained this to you already: "As long as you're not using the value of the expression, you're right that there shouldn't be a difference - but that only applies to standard data types. If you've overloaded the prefix and postfix increment operators of an object, there will be a performance hit."

If you're not using the value of the expression, and it's a standard data type, the optimiser should deal with it.

If you are using the value of the expression, the optimiser will not deal with it.

If you're not using a standard data type, the optimiser will not deal with it.

This was in response to your statement "And regarding ++i vs. i++, it's one thing to believe in the compile-time difference (but as you say, not anymore), but people who think there's a runtime difference… well… sigh."

There is a difference, in certain situations. Once again, telling people that a problem doesn't exist because you think it's unlikely to affect them is not a good idea.
27 Feb, 2008, David Haley wrote in the 24th comment:
Votes: 0
KaVir said:
I started with a correction because you implied something that wasn't true. Telling people that a problem doesn't exist because you think it's unlikely to affect them is not a good idea.

I still wonder at why it's such a big deal with it is negligible. It would seem that to you it is in fact not negligible at all! Either that or you have a very different definition of the word "negligible" than I do.

If a difference is negligible, then it shouldn't concern MUD developers. :shrug: And if they worry about it, they are wasting their time, or imagining that it matters more than it actually does. That is why it is a bad thing to make people think that it matters, when in the same breath you say it's negligible.

KaVir said:
If you are using the value of the expression, the optimiser will not deal with it.

Yes, and if you are using the value, you might actually care about prefix vs. postfix…

KaVir said:
If you're not using a standard data type, the optimiser will not deal with it.

Err, how can you be so sure of that?

See above for what I think about making so much fuss about negligible differences.
27 Feb, 2008, David Haley wrote in the 25th comment:
Votes: 0
If I may make an analogy about intentionally giving out simplified information, it would be that you don't need to explain ASM to somebody when all they ask is how to do something simple in C. It's confusing and irrelevant, even if it is true in the absolute sense.

It's a lot like how you teach atomic layers (orbitals) to early chemistry students, or simplified Newtonian physics to early physics students. The real details, while true, are confusing and not yet relevant. And the differences between those theories and the real ones, for most cases the students deal with, are (wait for it) negligible.
27 Feb, 2008, Fizban wrote in the 26th comment:
Votes: 0
Quote
or even just as a generic loop counter.


That's THE most common use of 'i' that I probably see…
27 Feb, 2008, David Haley wrote in the 27th comment:
Votes: 0
Not to nitpick too much, but I'd argue that even when you see it as a loop counter, you're seeing it as some form of numeric counter…
27 Feb, 2008, Fizban wrote in the 28th comment:
Votes: 0
Quote
I still wonder at why it's such a big deal with it is negligible. It would seem that to you it is in fact not negligible at all! Either that or you have a very different definition of the word "negligible" than I do.


Each instance is negligable, as a whole, the codebase may very well be slower due to the difference even if each individual part seems negligable. The difference between pi and 3.14 is negligable, the difference from 314000000000 and 314159265358 is not nearly as negligable.
27 Feb, 2008, David Haley wrote in the 29th comment:
Votes: 0
Fizban said:
Each instance is negligable, as a whole, the codebase may very well be slower due to the difference even if each individual part seems negligable.

Look at the numbers and then come back about this… Let's assume that some "slow" operation requires two more assembly instructions. On a 1 MHz machine, that is 2 * 1/1,000,000 = 0.000002s = 0.002 ms = 2 ns. You would need 500 such operations before it even became a millisecond.

Now let's assume a more realistic processor speed, say 1 GHz. Now we're talking about 0.002 ns per operation. You need 500 before it becomes a nanosecond…

Now let's assume that you're doing something in loop that covers every mob. Let's assume you have, say, 15,000 mobs, and you need to do this operation once per mob. That's 15,000 * 0.002ns = 30ns = 0.030ms. 30,000 mobs means 60ns. Woopdedoop.

You would need to be doing something a lot before it became an issue. As I said, MUDs don't have the kind of inner loop that e.g. rendering engines do: you do not care about even a few extra milliseconds spent in the main loop.

Fizban said:
The difference between pie and 3.14 is negligable, the difference from 314000000000 and 314159265358 is not nearly as negligable.

This statement depends completely on what you are trying to do with these numbers. If you're trying to compute the position of some satellite of the Earth assuming circular orbit, or if you're trying to calculate the surface area of a large enough circle (not that large, incidentally) the difference between pi and 3.14 is not negligible at all. And the difference between the latter numbers might be meaningless in other contexts.


And I hate to nitpick but it's "negligible" not "negligable". Sorry. :biggrin:
27 Feb, 2008, KaVir wrote in the 30th comment:
Votes: 0
DavidHaley said:
I still wonder at why it's such a big deal with it is negligible. It would seem that to you it is in fact not negligible at all! Either that or you have a very different definition of the word "negligible" than I do.


It's not a "big deal", but it is a point I feel is worth clarifying. If you tell people that there's no difference, and they later overhear a professional software engineer mentioning that s/he uses C instead of C++ because the former is faster and uses less memory, they're going to have to decide for themselves between two conflicting views - and most people are likely to side with the view of someone they know is a professional over an anonymous internet poster.

If, on the other hand, you explain that there is a difference, but that it's usually negligible for muds, then when they hear the software engineer talking about why he's using C they're no longer forced to choose between two conflicting statements. Instead, they can think to themselves "It must be because of the type of development he does".

DavidHaley said:
If a difference is negligible, then it shouldn't concern MUD developers.


They should be aware of it. I remember seeing a benchmark for a rendering application where the C solution was around 7 times faster than the C++ version - and while text muds aren't going to perform calculations on anything close to that sort of scale, there are still certain bottlenecks where the heavy use of C++ features might be noticable, particularly when designing your software in a solid Object Oriented way (eg no public member variables, instead each variable has to be get/set via access methods).

DavidHaley said:
KaVir said:
If you're not using a standard data type, the optimiser will not deal with it.


Err, how can you be so sure of that?


Because the prefix and postfix increment operators are overloaded as different functions. The optimiser has no way to know whether their behavior is consistent with that of standard data types.
27 Feb, 2008, shasarak wrote in the 31st comment:
Votes: 0
drrck said:
I don't know of any popular high-level languages that are JIT-compiled by default, except Java. I know Ruby has a JIT implementation somewhere out there, and Perl/Python probably do as well, but they're all going to be interpreted for the vast majority of users without reimplementation.

Smalltalk has been JIT-compiled for decades. Java is not exactly a niche language. And you're also forgetting C# and any other language running on the .NET CLR - are you seriously trying to claim that no version of MS VisualStudio from 2001 onwards has been "popular"?
27 Feb, 2008, David Haley wrote in the 32nd comment:
Votes: 0
KaVir said:
It's not a "big deal", but it is a point I feel is worth clarifying.

KaVir said:
They should be aware of it.

I guess we simply disagree. I believe it is a negligible point (hell, you said so yourself), and therefore serves only to muddle the issue for new programmers. I compared it to the simplified models of physics and chemistry we teach students. You don't tell very young physics students all about how their model will have differences when compared to Einsteinian physics even though the differences will be small for most things they compute – it's confusing, irrelevant and counter-productive.

KaVir said:
I remember seeing a benchmark for a rendering application where the C solution was around 7 times faster than the C++ version

As we all know, all this shows is that the particular C code was 7x faster than the particular C++ code. It's not definitive proof that "C is 7x faster in general".

KaVir said:
(eg no public member variables, instead each variable has to be get/set via access methods).

Again, you seem to have very, very little faith in the optimizer. That kind of thing is inlined: how do you think Java gets away with getters all over the place?
27 Feb, 2008, David Haley wrote in the 33rd comment:
Votes: 0
shasarak said:
Smalltalk has been JIT-compiled for decades.

Self is another highly dynamic language that is almost as fast as many non-dynamic languages.
shasarak said:
Java is not exactly a niche language.

In fairness, Java and C# aren't exactly high-level languages on the same level as e.g. Python, Smalltalk, Lua, Lisp, etc. Higher than C/C++, perhaps, but not by that much when compared to C++ and not by nearly as much as other dynamic languages.
27 Feb, 2008, shasarak wrote in the 34th comment:
Votes: 0
DavidHaley said:
In fairness, Java and C# aren't exactly high-level languages on the same level as e.g. Python, Smalltalk, Lua, Lisp, etc. Higher than C/C++, perhaps, but not by that much when compared to C++ and not by nearly as much as other dynamic languages.

Java, maybe not, but C# is actually quite sophisticated, especially version 2.0 onwards. Anonymous delegates, for example, are (at heart) the same thing as Smalltalk blocks. It's highly reflective, and you can construct and compile new classes at run-time. You've got good, efficient garbage collection.

Okay, the syntax is painful, there are some annoying aspects to the class library (for example Streams and StringBuilders clearly ought to be in the same part of the tree but they aren't) and also some compiler niggles (static methods are mostly analogous to Smalltalk class methods, but, irritatingly, you can't override a static method on a subclass). And the whole boxing/unboxing thing seems rather pointless. But, on the whole, it's not too bad, especially if you like static typing.

The only really glaring deficit that I'm aware of is the inability to modify the base class library. I just love the fact that in Smalltalk you can actually make 2 + 2 equal 5 if you want to. :smirk:
27 Feb, 2008, Silenus wrote in the 35th comment:
Votes: 0
This might be slightly off topic given how this thread is evolving but I am curious what makes a language a VHL (very high level) language versus just a high level language. Are there particular defining characteristics that cause a language to bridge this gap i.e. between something like C/Fortran/C++/Prolog/Scheme to something like Ruby/Python/Perl? How would you classify languages in the ML/Haskell family? and how about Prolog derivatives such as XSB?

I am not trying to me contrarian I am actually genuinely curious.
27 Feb, 2008, KaVir wrote in the 36th comment:
Votes: 0
DavidHaley said:
I guess we simply disagree. I believe it is a negligible point (hell, you said so yourself), and therefore serves only to muddle the issue for new programmers. I compared it to the simplified models of physics and chemistry we teach students. You don't tell very young physics students all about how their model will have differences when compared to Einsteinian physics even though the differences will be small for most things they compute – it's confusing, irrelevant and counter-productive.


I'm not saying its necessary to explain the problem, only that you shouldn't tell people that there isn't a problem. That's like telling your physics and chemistry students "Don't worry, you can't blow yourself up" based on the fact that they're unlikely to do so. Even worse, when they read the works of professionals who explain how physics and chemistry can be used to blow people up, those students are likely to dismiss your views in general as being uneducated if not flat-out wrong.

DavidHaley said:
As we all know, all this shows is that the particular C code was 7x faster than the particular C++ code. It's not definitive proof that "C is 7x faster in general".


I certainly never claimed (or even implied) that it was, only that there are "…certain bottlenecks where the heavy use of C++ features might be noticable" (emphasis added).

Looking back at one of your earlier posts, you said "Somebody once told me that they did not want a C++ codebase because it would be slower and more memory intensive than C". In fact they were probably right, and only misunderstood how little speed and memory difference there would likely be. Instead of claiming that they were wrong, quitting the team, and making fun of them behind their back, a more constructive approach might have been to explain the possible impact and point out that it would be negligible.

DavidHaley said:
Again, you seem to have very, very little faith in the optimizer.


"Again"? Are you then claiming that an optimiser can distinguish between overloaded prefix and postfix increment operators?

DavidHaley said:
That kind of thing is inlined: how do you think Java gets away with getters all over the place?


It might be inlined. It was also only one example. My point was that "…there are still certain bottlenecks where the heavy use of C++ features might be noticable" within the context of a solid Object Oriented design.

The additional overhead is almost certainly negligible for mud development, as I've said since the start, but it's misleading to tell people that there's no extra overhead at all. And like the teacher who tells his students that it's not possible to blow themselves up with physics or chemistry, the danger is that people will simply assume you don't know what you're talking about, and dismiss your views on other issues as well.
27 Feb, 2008, drrck wrote in the 37th comment:
Votes: 0
shasarak said:
Smalltalk has been JIT-compiled for decades. Java is not exactly a niche language. And you're also forgetting C# and any other language running on the .NET CLR - are you seriously trying to claim that no version of MS VisualStudio from 2001 onwards has been "popular"?


I don't consider Smalltalk anywhere close to being "popular". I also agree that Java is not a niche language, which is why I disclaimed it and included it in my OP as one of the three main languages that are taught to beginning programmers (for good reason). As far as C# and other .NET languages go - no, they are not popular at all (relative to languages such as Perl, Python, Ruby, Lua, etc.), and as DavidHaley pointed out, they are also not exactly what I would consider high-level, either.
27 Feb, 2008, drrck wrote in the 38th comment:
Votes: 0
shasarak said:
Java, maybe not, but C# is actually quite sophisticated, especially version 2.0 onwards. Anonymous delegates, for example, are (at heart) the same thing as Smalltalk blocks. It's highly reflective, and you can construct and compile new classes at run-time. You've got good, efficient garbage collection.


I would consider Java more of a high-level language than C#, although I think C# (in most cases) is a more robust language. Its capability as a language is not necessarily directly related to whether or not it's high-level or not, though. And I guess most of this is a matter of personal opinion, as there is no measurable "level" for a language to determine whether it is high- or low-. For me, personally, the more common-sensical a language is, the higher-level it tends to be. For instance, compare the following:

C++
cout << itoa ( a, buf, 10 ) << endl;

Ruby
puts a.to_s

Which would you rather teach to a beginning programmer?
27 Feb, 2008, David Haley wrote in the 39th comment:
Votes: 0
Silenus said:
This might be slightly off topic given how this thread is evolving but I am curious what makes a language a VHL (very high level) language versus just a high level language. Are there particular defining characteristics that cause a language to bridge this gap i.e. between something like C/Fortran/C++/Prolog/Scheme to something like Ruby/Python/Perl? How would you classify languages in the ML/Haskell family? and how about Prolog derivatives such as XSB?

Fine questions. I don't have a precise definition for you, but here are some points. First off I don't think common-sense is a good metric because it is so dependent on habit. Here are some characteristics that I have seen mentioned over the years and in my prog. lang. courses:

  • The closer to the machine details you are, the more low-level you are. Dealing with precise memory addresses is a good way to be quite low-level.

  • Typically, but not always, the more you have to deal with explicit type conversion, such as converting integers to strings before being able to print them, the more likely you are to be low-level. Again, though, this isn't always the case.

  • The more you can treat functions as first-class values the more likely you are to be high-level. FCV functions means that you can use them like any other value. C allows function pointers, but functions are special names and cannot e.g. be assigned to. In Lua, for example, you can assign new functions to existing names, because the function name is a variable name like any other in the namespace. So, if you want print to be a no-op, you can simply assign an empty function to it.

  • Along the same lines, the capacity for anonymous functions (inline-defined functions if you prefer) pushes you towards the higher-level side of the spectrum.

  • The more you can express very complex operations very simply, the higher-level the language is.

  • Syntax that serves concepts, rather than actual operations, tends to mean something is higher-level. The Haskell example below is a good example. Languages that have native associate arrays (maps) are others: while indexing into them with a key is not an actual operation, and hides operations from you, it directly expresses a useful concept.

  • Along those lines, anything that hides operations from you in language constructs is higher-level than something that reveals the innards to you.

  • Any time you are encouraged to not think about operational details, but instead get on with the concepts (as in the quicksort example below), you are likelier to be higher-level.


Here is a very good example of high- vs. low-level programming. Quicksort in Haskell vs. C. Two lines in Haskell vs. quite a few in C! Additionally, the Haskell is arguably clearer than the C, barring people who know C very well.

The operation is quite simple: take the car of the list, call it x and the remainder xs. Then, filter (i.e. remove everything else) from the remainder everything smaller than x; put it in front of a new list. Then put x. Then filter from the remainder everything larger than x; put it at the end of the list. Quicksort the two new lists; the bigger list is now sorted.

Well, I think these are good starting points, at least.

I don't think that C/C++ are in the same boat as Prolog. Even though Prolog doesn't let you manipulate functions and so forth, the program is expressed dramatically different than in C++. In essence, you are writing down more of a specification than an actual series of operations. You trust the VM to do the right thing with that specification (in Prolog's case, do the right logical inferences).

KaVir said:
I'm not saying its necessary to explain the problem, only that you shouldn't tell people that there isn't a problem. That's like telling your physics and chemistry students "Don't worry, you can't blow yourself up" based on the fact that they're unlikely to do so.

We, uhh, were talking about negligible differences in assembly instruction counts, not potential core dumps. Your analogy is a little off… Why didn't you discuss the precise examples I gave of Newtonian vs. Einsteinian physics, or atomic orbitals? Those are very good examples where students are usually not told about the "real stuff" until fairly later in their careers…

KaVir said:
Instead of claiming that they were wrong, quitting the team, and making fun of them behind their back, a more constructive approach might have been to explain the possible impact and point out that it would be negligible.

I did. They didn't believe me, and started going off about the very stuff you did. I believe that you understand it much better than they did, but they obviously were very confused when they say saw somebody like you talking about all the speed differences. Their take-home message was "oh, wow, speed differences" not "oh, wow, negligible speed differences". Hence in part why I think your statements are true but misleading and should be avoided, or at least encased in additional layers of disclaimers.

I vote though for not turning this into more of a run-on argument than it already is becoming. :smile:
28 Feb, 2008, shasarak wrote in the 40th comment:
Votes: 0
Silenus said:
This might be slightly off topic given how this thread is evolving but I am curious what makes a language a VHL (very high level) language versus just a high level language. Are there particular defining characteristics that cause a language to bridge this gap i.e. between something like C/Fortran/C++/Prolog/Scheme to something like Ruby/Python/Perl? How would you classify languages in the ML/Haskell family? and how about Prolog derivatives such as XSB?

I am not trying to me contrarian I am actually genuinely curious.

Personally I wouldn't attempt any sort of quantitative definition of what constitutes "high level". At best, it's a relative concept. Originally C and FORTRAN were classed as "high level" languages because what they were being compared to was Assembler.

It's simply to do with the level of asbtraction at which the language operates. In Assembler your instructions correspond to the numbers processed by the CPU in a 1:1 fashion. In C you have higher-level abstractions like for loops, while loops, arrays, etc. but you're still quite closely tied to what is going on at a low level. Memory management, for example, has to be done manually: you have to worry about de-referencing pointers yourself. In a language like Smalltalk you no longer have to bother with the mechanics of memory handling: requests for, and deallocation of, memory are handled for you automagically and you (almost) never even have to be aware of it. And instead of dealing only with functions and primitive types, you deal in objects which are a higher-level abstraction and one step farther away from the raw machine code.

So, the further away you are from the CPU instructions, the more "high level" the language is. Generally, high level languages require steadily fewer lines of code to do increasingly more complex things.
20.0/51