Inherent code performance advantages of D over C?
Walter Bright
newshound2 at digitalmars.com
Fri Dec 6 15:56:48 PST 2013
On 12/6/2013 3:39 PM, H. S. Teoh wrote:
>> 1. D knows when data is immutable. C has to always make worst case
>> assumptions, and assume indirectly accessed data mutates.
>
> Does the compiler currently take advantage of this, e.g., in aliasing
> analysis?
I'm pretty sure dmd does, don't know about others.
>> 2. D knows when functions are pure. C has to make worst case assumptions.
>
> Does the compiler currently take advantage of this?
dmd does.
>> 3. Function inlining has generally been shown to be of tremendous
>> value in optimization. D has access to all the source code in the
>> program, or at least as much as you're willing to show it, and can
>> inline across modules. C cannot inline functions unless they appear
>> in the same module or in .h files. It's a rare practice to push many
>> functions into .h files. Of course, there are now linkers that can
>> do whole program optimization for C, but those are kind of herculean
>> efforts to work around that C limitation of being able to see only
>> one module at a time.
>
> To be frank, dmd's current inlining capabilities are rather
> disappointing. However, gdc IME has shown better track record in that
> area, so it looks promising.
This is about inherent language opportunities, not whether current
implementations fall short or not.
>> 4. C strings are 0-terminated, D strings have a length property. The
>> former has major negative performance consequences:
>>
>> a. lots of strlen()'s are necessary
>
> Yeah, this is a common C bottleneck that most obsessively-optimizing C
> coders overlook. Many a time profiling of my "optimal" code turned up
> surprising bottlenecks, like fprintf's in the wrong place, or strlen's
> in inner loops. D's strings may be "heavier" (in the sense that they
> require a length field as opposed to a mere pointer -- y'know, the kind
> of stuff obsessively-optimizing C coders lose sleep over), but it comes
> with so many advantages that it's more than worth the price.
Yup.
>> b. using substrings usually requires a malloc/copy/free sequence
>
> Yeah, string manipulation in C (and to a great extent C++) is a royal
> pain. It actually drove me to use Perl for non-performance critical
> string manipulating code for quite a good number of years. The heavy
> syntax required for using a regex library in C, the memory management
> nightmare of keeping track of substrings, all contribute to fragile
> code, increased development times, and poorer performance. Only
> obsessively-optimizing C coders can fail to see this (and I used to be
> among them). ;-)
I failed to recognize the problem for what it was for years, too. I think the 0
terminated string issue is a severe fault in C, and it was carried over into
C++'s std::string. C++ missed a big opportunity there.
>> 6. D's array slicing coupled with GC means that many
>> malloc/copy/free's normally done in C are unnecessary in D.
>
> It does mean we need to get our act together and improve the GC's
> performance, though. ;-)
The best memory allocation algorithm is one that doesn't do allocations at all.
While this may sound trite, I think it is a crucial insight. The mere existence
of the GC enables many allocations to not be done. The other thing is that D's
ranges can also be used to eliminate a lot of low level allocations.
> But this is a major advantage in array manipulation (esp. string
> manipulation) in D. In equivalent C code, best practices dictate that
> slicing should always be done by allocating a new array and copying,
> because otherwise you introduce intricate dependencies between pointers
> and your code either becomes wrong (leaks memory / has dangling
> pointers), or extremely convoluted (reinvent the GC with reference
> counting, etc.). Being able to freely slice any array you want without
> needing to keep track of every single pointer, is a big savings in
> development time, not to mention better runtime performance because you
> don't have to keep allocating & copying. All that copying does add up!
Exactly.
> There's also another aspect to this: being built into the language, D
> slices allows different pieces of code to freely exchange them without
> needing to worry about memory management. In equivalent C code, an
> efficient implementation of slices would require the use of custom
> structs (as a pair of pointers, or a pointer + length ala D), or
> specific function parameter conventions (e.g. always pass pointer +
> length). Since everyone will implement this in a slightly different way,
> it makes interoperating different bits of code a pain. One function
> takes a pointer + length, another function takes a pointer pair, a third
> function takes a custom struct that encapsulates the foregoing, and a
> fourth function takes *another* custom struct that does the same thing
> but with a different implementation -- so now to make the code work
> together, you have to insert intermediate layers of code to convert
> between the representations. It's a big development time sink, and yet
> another corner for bugs to hide in. In D, since slices are built-in,
> everybody takes a slice, no interconversion is necessary, and everybody
> is happy.
Yup.
More information about the Digitalmars-d
mailing list