This article, "C Is Not a Low-Level Language; Your Computer is Not A Fast PDP-11", by David Chisnall of Cambridge, is a critical self-assessment of C, modern CPU architectures that pander to C, and modern C compiler writers, like himself.

The intertwined successes of UNIX and C was inevitable, given the nature of the computing technology in the late 1960s. But that instant, meteoric success continues to demand backward compatibility through the decades, and that backward compatibility engenders much forward restraint on future advances.

As a long-time fan of C and PDP-11/70, I find Chisnall's critiques painfully true. The same could be said of UNIX, my all-time favourite operating system. And x86, too, followed a similar path to immediate success and perpetual dominance.

The power of inertia is terrifying: even after 50 years, the current score of the computer architecture and programming language game remains "von Neumann 1 v Backus 0".

https://spawn-queue.acm.org/doi/pdf/10.1145/3212477.3212479

@AmenZwa @david_chisnall David, re:

> A processor designed purely for speed, not for a compromise between speed and C support [...]

How feasible do you think it would be to support existing C programs on a system like that through some set of bridging extensions to the C language (maybe something reminiscent of the extensions that were added to ObjC in order to support Swift)?

Does the answer to that question change if we assume that this new architecture supports CHERI or similar?

@JamesWidman @AmenZwa

I worked on an in-house architecture at Microsoft and the consensus was that a 20% speedup on the same process / design complexity with easy source compatibility is not worth it commercially. To bring a new CPU architecture to market that's much faster, you need at least a 2x, ideally a 10x speedup. The problem with doing a non-C-friendly architecture is that you mostly get speedups from removing things that you'd put on to make C fast. If you then also want to run C, you need to add them all back.

The places alternative designs have been successful are things like GPUs. GPUs are well over 10x faster than CPUs for workloads that work on GPUs. They're not displacing CPUs, but they are augmenting them, and a load of things moved to running on GPUs. I could imagine an architecture that's able to run GPU workloads maybe 70% as fast as a good GPU design, but also able to run CPU-like workloads written in a non-C-like language appearing as a more flexible accelerator and then gradually displacing more of the things that CPUs do. It may be that you could get to the point where nothing performance-critical then runs on the CPU and that would give you a path, but it's quite hard (both technically and economically).

@david_chisnall @JamesWidman

In my small corner of the DSP world, the Cortex CPUs and MCUs rule today. But the 80s were the heydays of the TMS320. The TMS320 was a purpose-built DSP CPU. The Cortex-M4F is an M3 augmented with an FPU, the MAC instruction, and a couple of vector facilities. The M3 is as pedestrian as an MCU can be. Yet, the general-purpose MCU, like the M4, with a couple of tweaks, can live happily in the narrow, specialised field, like DSP.

Oh, by the way, the Cortex-M family specifically targets C, with internal components designed to accommodate the way C compilers generate code, including C's calling convention of pushing the stack in printf-friendly reverse order: printf-style variadic argument passing specialisation on a MCU/DSP chip—fancy that!

This type of single-minded pursuit of design artificially restrain progress, as David pointed out.

In 1977, Backus pleaded—of all the places, at his own ACM award ceremony for his work on FORTRAN—to move away from the von Neumann bottleneck and its software reflection, PP languages. He even proposed his own "FP" language. In the mid 1980s, at the peak of LISP machines, Knight published an insightful article on the architectures designed for FP languages. But the industrial flywheel ensured that none of those ideas escaped academia.

Today, there is loads of opportunities for researchers to explore truly novel CPU architectures in affordable ways. Yet, the economic gravity of the industry keeps pulling the talent towards the spinning flywheel.

I don't have a solution in mind; I'm just complaining, bitterly....

«In 1977, Backus ... even proposed his own "FP" language. In the mid 1980s, at the peak of LISP machines, Knight published an insightful article on the architectures designed for FP languages. But the industrial flywheel ensured that none of those ideas escaped academia.»

Not just the industrial flywheel.

Imperative programming is easier than functional,
and procedural is easier than declarative.
Easier as the path of least immediate resistance, but it matters.

(If this is included in the Industrial flywheel, then scratch my first sentence above.)

@AmenZwa @david_chisnall @JamesWidman

@vnikolov @AmenZwa @JamesWidman

I'm curious what this claim is based on. There are a lot of 'X is easier' claims, but they generally include a lot of survival bias: people were taught X, then they learned Y. The ones who couldn't understand X never got to see Y, so you're left with a population that can do X, of which some prefer Y, but all of them can do X so X must be easier.

For example, I remember the thing I found most confusing when I started learning to program was that subroutines executed synchronously. My mental model was that a subroutine call started something running and eventually it would finish. It took me years to get to grips with the idea that these things happened synchronously.

You're told that programs are like recipes, but every single recipe I've read has instructions like 'start the pot simmering' and 'meanwhile...' Each step is a thing that happens in a distinct time, but with interdependencies and steps that are atomic with respect to the rest of the process.

This is why I like our Behaviour-Oriented Concurrency model: it directly corresponds to things that you see in recipes, and a lot more people can follow a recipe than can write code.

When Concurrency Matters: Behaviour-Oriented Concurrency | Proceedings of the ACM on Programming Languages

Expressing parallelism and coordination is central for modern concurrent programming. Many mechanisms exist for expressing both parallelism and coordination. However, the design decisions for these two mechanisms are tightly intertwined. We believe ...

Proceedings of the ACM on Programming Languages

My claim, or perhaps thesis, is based on the accumulation of my observations on the multitude of programs that I have seen.
I don't think the explanation of the prevalence of imperative and procedural programs is only that their authors never heard of other ways to do it.

Another thing that feeds my intuition about the above is the introduction of things like the IO monad in Haskell.

And it is a much bigger topic, of course.

@david_chisnall @AmenZwa @JamesWidman

@vnikolov
I learned assembly in the early 1980s, as was common in those days. Over the next five or so years, I learned C, LISP, Smalltalk, and ML. This was unusual, and perhaps unwise, by conventional wisdom. It was surely a mess trying to juggle PP, OO, and FP concepts nearly simultaneously, when my only mental reference were circuits and signals. These days, my favourite is dependently typed FP, as expressed in my Fortran modernisation article.
https://amenzwa.github.io/stem/PL/FortranModernisation/

I agree with you that the imperative paradigm (machine, procedural, and objective) is easier for novices to pick up, compared to the declarative paradigm (functional, relational, and logical). By “easier”, I mean the transition from none to some level of comprehension is shorter. This observation is based on my teaching undergraduate CS students C, ML, and Prolog in the 1990s and my continued instructional efforts in industry teaching OCaml, Haskell, Scala, etc., to Java aficionados.

I also observe that in the 80s and 90s, CS curricula were far narrower (naturally) and there was a lot of theoretical background given: computability, complexity, category, and so on, even if only at the shallow introductory depths. That is no longer true amongst ordinary CS curricula. Most students are focusing on Python and PyTorch.🤦‍♂️ So, when I teach Haskell to a gaggle of JavaScript and Python industry experts, it stresses them. My 90s undergraduate students, who were more accustomed to theoretical concepts, learned ML (granted a far simpler language) with less dread and resistance.

@david_chisnall @JamesWidman

A Forlorn Hope of Fortran Modernisation · Amen Zwa, Esq.

@AmenZwa

Indeed.
And your final paragraph is about yet another important part of this picture.

At least, JavaScript has `const' and Python has several kinds of immutable data structures, some small stepping stones.

@david_chisnall @JamesWidman

@vnikolov
Also, Python 3’s “Typing” library helps, a little. And I advise my mentees who still live and breathe JavaScript to switch to TypeScript, or at least use Flow, instead.

@david_chisnall @JamesWidman