In a thoughtful comment to my post analyzing Apple’s refusal to allow non-native apps–the ones built with Flash, .NET, any type of cross-compiler, etc.–on its devices, Andrew Martin argued:
I would argue that knowing a “lower-level” high-level language like C would help a developer write more efficient programs (regardless of how efficiently the compilation occurs). Of course this isn’t necessarily true in all cases
It’s an interesting point and, since it didn’t fit the discussion on the page, I moved it over here.
The argument that knowing a way to program at a lower level of abstraction helps you write more efficient programs is as old as programming. Assembly-language programmers said that to C programmers, C programmers said it to C++ programmers, Java programmers now say it to Ruby programmers, etc.
Efficiency is a complex metric with as many constituent parts as there are resources one cares about in a given situation: time, space (RAM, virtual memory, disk space), I/O, OS-level resources (processes, threads, handles, semaphores, ports, channels, …), etc. To understand the issues, one has to look at what aspects of a programming language affect efficiency (however this is defined). Some key factors are the built-in constructs, data structures, frameworks. For example, C++ templates allow for compile-time optimization that is practically impossible to replicate using C. An extreme example of this is template meta-programming, which I’ve had some great results with. The same is true of some Objective-C capabilities such as dynamic binding and message passing, which are not practically replicable in C. Another, and very different, example would be Flash which is very good at vector graphics, animation, etc. It doesn’t just have built in libraries that support this–its programming model, which includes things such as frames, and runtime environment, down to its bytecode architecture if I’m not mistaken, have special, optimized constructs that support these capabilities. Matching that using, say, Java would require excellent graphics/animation libraries and, even then, the fact that the JVM architecture is not optimized for vector graphics & animation may be a significant disadvantage.
Another factor, and reason why it is becoming less and less true that knowing a lower-level language helps a programmer write more efficient programs, is the quality of optimization, be that static (compile-time) or dynamic (run-time). People have a very limited ability to perform the type of optimizations software can. We don’t have the information management power to do static analysis (code & data flows as well as instruction/data layout) well and we tend not to have the time and skills to do dynamic analysis (profiling), especially when one considers the added complexities of such things as varying workloads, parallelism and predictive execution. Worse, our psychology drives us to premature optimization.
It is legitimate to ask what does the last point have to do with lower vs. higher-level languages since both are benefiting from better compilers. The answer lies in the division of responsibilities. In a lower-level language like C it is often much more difficult for a compiler to make big assumptions about the impact of code execution on data structures. In a higher-level language, the compiler and/or runtime environment have more responsibilities but that also allows them to do more because they, and not the developer, are in control and that gives them the flexibility to move data structures around, to parallelize without fear of race conditions and unsafe data structure access, to not recycle memory until necessary, etc. For example, a dynamically-optimizing garbage collector may beat C memory management, even if the C program is compiled using a dynamically optimizing compiler.
In the future, the main way to write more efficient programs that don’t just work through massive but relatively dumb parallelism will be to use programming models that maximize the expression of intent with the minimum of implementation-specific constraints, allowing the hardware and software around developers’ code to maximally help.