The future of computation
Computation is a macro-trend that we have trouble seeing. It is as if it started raining in the 1970’s and simply never stopped. What were once isolated puddles are joining to become oceans. ENIAC yields to Kubernetes.
We can describe computation in mechanical terms. Wikipedia says “Computation can be seen as a purely physical phenomenon occurring inside a closed physical system called a computer”. And that examples of such physical systems include not just digital computers but also mechanical or analog computers, DNA, or even ecosystems - such as natural computing. People like Wolfram and Carlo Rovelli also like to draw this parallel; deriving the rules of physics from a computational network model.
We can argue that “even rocks, walls, and buckets of water—contrary to appearances—are computing systems”. And we’ve always been surrounded by our tiny avatars of will. A farmer puts trillions of micro-organisms to work fermenting a vat of kombucha or employs a wily macro-scale sheepdog to corral the flock at days end. A droplet of mercury, a glass thimble and a roll of curved metal schedule a furnace. We’re no strangers to putting everything around us to work.
With our machines we think harder, see further, sense-make - finding connections between the previously disjoint. We manipulate the physical world in a fine grained way, extend our memories, replacing some atoms with just-in-time control surfaces, even convert “atoms to bits” entirely; capturing the essence of artifacts and discarding the so called container. We do all this at a velocity far in excess of human scale. In so doing our will is distributed into the fabric of reality.
What feels different today is that we’ve achieved a fidelity. We are able to express a task precisely and set it loose upon the world. In so doing computation has become a dominant force in our lives; taking a process that previously required our conscious attention and time and turning it into a reproducible, portable and reliable machine.
Of course we can criticize automation. The asymptote is a new ability, creating peril in multiple dimensions. Most obviously our daemons may escape our grasp (a topic that is sadly beyond our reach here). But there are other more specific critiques that we can raise.
Bridges to the world
Computation begins in hardware. Today almost all transistors are based on MOS silicon-gate technology (SGT). These are basically gate transistor made with highly-doped poly-crystalline silicon. From here assembler language instructions are exposed to the programmer, and in so doing we build a bridge from the physics of our world.
New hardware development is becoming almost whimsical. Creative inspiration may quickly be translated to an FPGA, an online circuit board layout tool, a plane ride to Hong Kong, to Shenzhen factory floor to Alibaba and Amazon. A constellation of devices constantly emerges from this fountainhead, light sensors, smart watches, security cameras, pet feeders, odor detectors, smart toasters, musical instruments. Just look around you.
But software is even more malleable than hardware; and it is in software that we place our burdens. We abstract over assembler with higher level grammars. Procedural logic in languages like Javascript, C, Rust, Python become a stable computational field for even the most ephemeral of human wishes. Best practices are shared, large repositories of source-code become available. Tensorflow, computer-vision libraries, semantic meaning extraction, contextual network graph analysis, public key cryptography. We have enormously complex machines as single method calls.
From this application frameworks, operating systems and larger ecosystems rise. Linux, Android, iOS, Java, Windows, HTML, Docker, the Internet, Ethereum. Each defines best practices, sets rules, limits, boundaries. How are dynamically loadable libraries permitted? How are threads scheduled? How are devices provisioned? How is user privacy protected? How shall a user interface be composed? Everybody seems to have their own opinion.
As these ecosystems grow developers are forced into certain pathways. There are strong incentives by ecosystem providers to control who may participate, what rewards they may reap, what customers they may reach, what tools and powers they may have. Often constraints are phrased as necessary to protect user privacy but often in fact excuses are coincident with retaining control; moat-building.
Challenges for Software Developers
It is hard for us as programmers to only express work once. Each device has different expressions of the same work.
You are spinning up EC2 instances, running Docker, Linux and Python on just in time provisioned servers in the cloud. Perhaps you are using newfangled CloudFlare workers in Rust to push computation to the edges. Or perhaps you’re using a “serverless” architecture like Google Firebase with either database permissions and constraints expressed in a yet another special mini grammar, or naked functions written in Javascript - all just to safely ferry user requests to your database. Or perhaps you’re using web3 under Metamask to trigger a smart contract on the Ethereum machine.
In all these scenarios you may be describing the exact same intent but in each phase transition the logic has to be re-encoded to the domain specific language, or you have to invent some kind of meta DSL to abstract your core concepts.
Toolchains aren’t just arbitrary. They are also embody best practices. They are a form of implicit knowledge; embedding within themselves a set of policies and opinions about how something should be done.
Walled Gardens especially have a power to require you to jump through hoops that direct energy back to themselves.
The Web is infamously difficult to develop for when you are trying to deal with cross server boundaries, trying to share cookies, get the users permission to use their microphone and so on. There’s such a fixation on security that one wonders if they’d prefer if nobody uses the web at all rather than be exposed to any security risks.
For large companies there’s a pernicious desire to push all new capabilities and support through committee. Inevitably toolchains end up with beefy foundations of things that “might be useful”. It’s difficult to pare a system back for say deployment to an embedded device, and it’s difficult to avoid dragging in all the superfluous embellishments that the vendors would like you to have.
According to Information Is Beautiful “Google Chrome (browser) runs on 6.7 million lines of code (upper estimate). A Chevy Volt uses 10 million lines. The Android operating system runs on 12-15 million lines. The Large Hadron Collider uses 50 million lines.Feb 8, 2017”.
Carful of Clowns
Toolchains these days consist of largely arbitrary baggage, providing policy, practices and capabilities you don’t need. There are inconsistent permission structures, vast mountains of tools, each of which are idiosyncratic, most of which are unused.
These become “features” that you have to mind, install, deploy and make part of your environment and thinking process. A huge stack of unwanted dependencies that you must support in order to deliver a small amount of work. Development becomes farcical.
The net result is that if you pick up any new software stack today and you may find that it is less an architecture and more like a carful of clowns. It’s as if you’re borrowing a friends car to go out and get some errands done but you look in the back seat and there’s a clown telling you that you have to turn left right away, or you stop at a stop light and another clown starts honking the horn. And you can only accomplish chores by carefully telling some of the clowns how to do it and hope they report back. You talk to your friends about this and everybody just shrugs and says “they just come with the car”, or they say “well this clown is super useful” or “oh just use this other clown to deal with that clown”. You go look at other cars, and soon you realize that every car is full of clowns, there’s really no way to avoid a carful of clowns in fact. Everybody who makes cars makes sure to stuff them full of clowns that they think you want, and you can’t really do anything about it.
Challenges for Hardware Vendors
Hardware vendors face a similar dilemma.
To expose new hardware capabilities in a standards based way is often difficult. While a hardware vendor can (with some work) provide custom device drivers for their hardware, those capabilities cannot easily be exposed to say web apps, or third party apps that may otherwise run on their device.
An AR glasses manufacturer can go through the labor of producing a new cutting edge headset, and they can install Android on that headset, and they can build device drivers to expose any novel capabilities to Android, but this is not itself good enough to create user adoption. Developers are reluctant to custom tailor work for a new piece of hardware.
The Oculus Quest is a good example. It took huge amounts of money to build an ecosystem, support developers, in depth, long enough, to ignite a spark - even though VR headsets already existed and were largely identical from a device perspective. The few quirks and differences in the controls and capabilities required in a sense introducing an entirely new stack.
Abstracting over hardware quirks
Hardware is by nature idiosyncratic. New sensors, new capabilities are embodied in the firmware. Software in theory is excellent at abstracting over hardware, but in practice we tend to see each hardware vendor adopting different software stacks. The same code patterns are written over and over for each new device, and interoperability is poor.
Apple enjoys a vertical integration from chip architecture to devices to user interfaces to consumer payment handling. By controlling participation at each stage of the stack Apple protects their brand and delivers a high quality experience. But this protective moat slows innovation. It is the perennial incumbents dilemma: to milk existing markets or to create new markets.
Android as a competitive mobile operating system does allow licensing, and as a result largely all new devices (notably AR headsets) are Android based. Of course by allowing more turbulence in a design funnel, both the ups and downs are increased. There are many more mediocre Android platforms and notable failures.
Contrasting to the web
A browser is in a sense an operating system. It acts as supervisor for page based applications, managing their state, providing them thread time, providing local storage. All system services; devices, keyboard, bluetooth, GPU must pass through boundaries setup by the browser. But unlike iOS or Android the web doesn’t require a developer to have their work approved by a private company.
As a result we see playful exploration and creative programming. Many different ideas from different parties are constantly emerging. Different stakeholders and different software technologies can come together quickly. And a developer can instantly share their ideas as an URL with anybody else anywhere on earth.
The web of course is a mess in some senses. It is characterized by a set of kludgy declarative grammars such as HTML, CSS, and a hodgepodge of procedural grammars such as Javascript, Java, WASM and so on. It’s also difficult today for even large teams of programmers to write a new browser. Supporting the entire past, including all the quirks, is extremely difficult. Chrome largely dominates. And other companies such as Apple have a vested interest in making the web as weak as they can get away with.
And what we don’t see on the web is performance, or even good support for new hardware. Standards such as WebXR languish far behind actual devices and vertical market support. A developer can wait a year and make a mediocre experience on the web or just “go native” and move 10x as fast. The web becomes a playground for “old technology”; technology that has stabilized. The phrasing of the web, the phrasing of web-browsers, the specific requirements around user security and safety are all contributing factors around the slowness of the web to innovate.
But does it have to be this way? Can we have both? Can we have an approach that lets people play but also allows for new device support - in a performant way? Without device capabilities going through committee?
A different approach is needed. Instead of a “massive base of functionality” what is needed is a formalization of dynamic late binding, permissions and capabilities. Dynamic loading of modules, management of what is loaded, an ability for durable and persistent dependencies.
Joining the computational oceans
As creative builders we want to be able to approach new concepts with tools in hand, using software design patterns and principles that we can use to drive that new hardware quickly.
On clients there’s an argument for some kind of browser like, or browser centric, well-scoped hypervisor or microkernel that can run not only portable rich apps but also device drivers - in a containerized way.
And we see similar patterns in cloud solutions such as Kubernetes and Docker and in the Lucet project from Fastly.
In a sense this begins to look like there is a pressure for shared foundations, similar to say package managers such as npm, or the way Ubuntu manages packages. Similar in capability to say iOS, or Android - but not controlled by one party.
Standards bodies see this and comment on it as well. The IEEE Standards Association has started to look for ways to simplify development. The ByteCode Alliance has been promoting Web Assembly (WASM) as an antidote to Java bytecode; similar in capability but without the technical and legal baggage.
Given a “neutral” platform for computation, that people can put in their pocket, we could imagine a world of new applications, both large and small, to service needs that we are only beginning to identify.
If we had such foundations, then the question becomes what kinds of future experiences could we build that we can’t build today? What would the future of our tools be?