waffle

Waffle is a weblog.
The author of Waffle, some guy in Sweden, also occasionally writes stmts.net.

Lately on Waffle

At ARM’s Length

A few months ago, Intel gave up on trying to get Atom processors into the smallest of devices, after years of trying to achieve widespread success. Meanwhile, ARM processors have been getting more and more capable without giving up the power efficiency Intel apparently never came close to maintaining.

At this point, with an Apple interested in creating MacBook-style, er, MacBooks, it’s only a question of time until there will one day be a MacBook that can run non-x86/x86-64 applications. Instead of trying to predict when, I’m interested in figuring out “how”?

Bitcode. Although it would be more cumbersome and require introducing this technology to macOS, being able to recompile applications to a new target architecture is already mostly a solved problem and would finally give anyone a good reason to use the Mac App Store – giving you compatible versions without requiring developers to recompile their apps. Naturally, all of Apple’s own stuff would be Universal for x86-64 and 64-bit ARM, and naturally every developer could make their own apps Universal.

A double chip solution. Some parts of this would require some heroic engineering, like being able to have an operating system span, straddle or move across from one CPU to the other, but the potential to run the apps that are available in ARM versions on a separate ARM chip and let the x86 processor nap for a lot longer is irresistible.

Apple already makes a video adapter and a remote with ARM chips, and a beefier ARM chip could subsume some of the ancillary tasks that require separate chips today and possibly pay its weight in both board location and power budget even before we get to running apps.

The OS would likely run handily on ARM, and with the decade long effort to spread out tasks into isolated processes, running them on the most appropriate processor would suddenly be viable.

Rosett-me-not. Survivors of the 2006 Mac PowerPC to Intel transition may remember Rosetta, the dynamic binary translator that made it possible to run PowerPC apps mostly transparently and with some caveats. Survivors of the 1994 Mac 68k to PowerPC transition may remember the 68k emulator layer that was more capable and so efficient that when the Mac OS X strategy was first presented in 1998, a major point was made of how it was all finally going to be PowerPC native – the emulator had worked so well that parts of the OS had simply never been rewritten.

What this tells us is that the relative strengths of the architectures involved plays a role in the viability of providing emulation in the first place. Maybe by the time Apple cuts over, the ARM processor will be sufficiently able to emulate or translate the x86 instruction set at usable speeds for the intended devices, but I’m betting against that. For one thing, I think that ARM isn’t more energy efficient because of pixie dust but because of an instruction set that more easily lends itself to being implemented in an energy efficient way. Asking it to emulate the x86 instruction set has the air of snatching defeat from the jaws of victory, no matter how desirable being able to execute x86 instructions may be.

The Apple instruction set. Continuing from the previous points, one of the reasons that ARM has been able to progress is that it has been able to introduce new instruction sets and set a new cadence for compilers and other tools. You can continue to use the instructions you already use, or you can switch to these new ones and not only speed things up but save energy. One of the big ways power is saved in new processors is by shutting parts of the chip down when work isn’t happening. Apple’s “don’t call it PA Semi” department, led by Johny Srouji are becoming experts in making improvements to ARM designs and are surely keeping track of what an even more ideal processor would look like. Who’s to say that what I’ve been referring to as ARM won’t instead be a processor that works much more like ARM than x86, but which has new fundamentals and a new instruction set in addition to the ARM instruction sets (and may not even be backwards compatible with much of ARM at all)? I call it AppleArch and am hoping for a repeat of the reasonably correct forecasting of xlangSwift.

End note: I am pulling all of this completely out of my ass, and many are the subjects where I know only just enough to be dangerous, like following the unveiling of the Mill with equal interest and befuddlement. Treat me like an authority on your own peril. That said, it all seems to make sense to me.

WWDC 2016 Predictions

  • macOS.
  • watchOS 3 – simpler overall, custom watch faces and something else on the side button. (No new watch until later this year.)
  • tvOS 2 with pluggable Universal Search and integrated support/allowance for live TV.
  • Siri:
    • A passive Siri API, in the same way as the Spotlight API is passive – you get to put things in the right places or define static (code-signed property lists) phrases but not respond directly to Siri commands.
    • A way to embed Siri functionality, like speech recognition/synthesis or Spotlight.
  • X11 for iPhone. Just kidding.
  • iOS 10 with a new home screen.
  • App Store:
    • Mea culpa about unfocused, uneven history (followed no doubt by the unanimous awarding of a pony to me, with condolences); focus on recent developments.
    • Letting some developers have privileged or trusted access.
    • Some sort of widening in ad hoc/enterprise distribution for iOS, similar to Developer ID/Gatekeeper.
    • In-app purchases on Mac.
  • iMessage for Android.
  • Thunderbolt 3:
    • A new Retina MacBook Pro with Thunderbolt 3.
    • A bumped Mac Pro with Thunderbolt 3.
    • A Thunderbolt 3 5K Display with an embedded GPU.
  • International:
    • Touting the 60 countries that developers come from.
    • …followed by references to sports that no one outside of the US plays and to clubs that no one outside of the US has heard of.
    • At least one service or capability or upgrade that is only usable in the US.
    • Apple Pay to Germany and France.
  • Grab bag:
    • A major upgrade to Photos.
    • Tag support in iCloud Drive.
    • Eddy Cue’s outfit louder than auditorium PA system.

Dyna-might

Brent Simmons:

When I talk about dynamic programming on iOS and Mac, I mean this:

  1. An app can learn about its structure at runtime.

  2. An app can do things based on what it knows about its structure.

  3. An app can make changes to its structure.

Brent is explaining this in an effort to see that the worthwhile qualities of Objective-C are not sacrificed to the gods of method call devirtualization. But his criteria are interesting. Almost everything about it is possible in nearly every language – some things are just major pains in the ass.

For example, in C#, my day time language (and increasingly night time), all of them are possible. 1 is easy due to reflection, 2 is easy due to reflection and the type system and 3 is easy if you share a predilection for hand-writing IL, where IL is the ungodly Intermediary Language used by the CLR virtual machine. (Okay, it’s a little bit easier with the modern Roslyn compiler which has an API for compiling C# code and loading code in memory, but the process for unloading it or replacing it is an emphatic “uh, let me get back to you on that”.)

Swift started out not very dynamic at all, but is at least now largely introspectable through “mirrors”, which I’m told is a sane(r) form of reflection. In Objective-C, the Objective-C runtime API’s information is willfully obtuse, because guess what, it’s the same API used to implement all the behind the scenes shenanigans to make message passing and classes and metaclasses and instance creation and method adding a thing in the first place, and it’s been optimized out the wazoo. Hello, Type Encoding and goodbye, scrutability.

In Swift, mirrors are comically loosely-typed-feeling, but still hard to decipher and still technically an API in flux. I have tried to write a dynamic JSON deserializer-and-class-populator and it was not self-describing. In C#, the reflection metadata is almost annoyingly precise and a task like that is just about as easy as that sort of thing will ever be likely to get.

The question isn’t really whether dynamism is needed. Many sharp brains have pointed out that the frameworks underlying Cocoa today would not be readily implementable in the pure Swift. Brent does a good job explaining why “just writing the code to solve the problem while using Swift idiomatically below” is a step backwards. Drew Crawford explains why there sometimes really really is no other solution.

What I’m wondering is whether there’s some amount of room for a third way. All of this, or at least parts, may be completely insane. I have not done any engineering of compilers or runtimes before.

What no one wants or likes is to have to wire up everything yourself. Code generation is a partial solution for this, but ginormous switch statements and lookup tables are also considered wildly inelegant. Brent quotes Guy English: “If you see a switch statement or dispatch table they blew it. Boilerplate that needs to be managed is a stagnant pool for nasty bugs.”

But lookup tables are exactly how message passing works. The problem isn’t that they exist, it’s any solution where, as Guy reminds us, you have to manage and see boilerplate.

So what if Swift let you code classes that looked like Swift but behaved dynamically? What if Swift let the virtualness of methods bleed out into runtime, and it could gradually be bolted down as the application ran, depending on the actual types, actual objects, actual methods, actual messages passed, call site by call site? What if that metadata was allowed to remain, could be used later and maybe even be extended?

I know that Swift creates “witness” intermediaries to make sure the right usage or definition of a method is captured. What if sending the foo:bar: message could be translated into a special failable method call on a compiler-construed catch-all protocol extension, for example, ensuring that sending it down a responder chain wouldn’t cause everything to come tumbling down?

I know that the Java HotSpot VM was capable of doing specialization optimizations that it could back out of whenever the optimizations stopped making sense – does that really take a JIT to do and not “just” (LLVM committers are given free permission to sneer knowingly now) some self-healing trampolines? What if suddenly sending that message to a proxy object would still end up working fine, without selling out the potentially much faster optimized version that is already being run 500 times per second? Objective-C was compiled because C was compiled. Swift is compiled by choice. What’s to say that it has to continue to follow the one-big-compilation model, or compile all the code, or compile only the code apparent when the build starts?

What if dynamic things could be dynamic, and Swift could be good at them too?

What if I’m full of shit and/or out of my depth here? The things I mention are things that to my intuition seem like puzzle pieces that could snap together. But I’m just following a few things I have read a bit about and mentioning them in the vicinity of each other. If it turns out that I’m wrong, well, I fully expect to be.

What I also expect is there to be a dialogue right now about these kinds of details by people who know what they’re talking about, about how Swift could actually become more dynamic without copying the flaws of its progenitors and without selling out the feel, mechanics and (most of the) performance of the language. I’m not seeing too much of it, and even if nothing came of it I’d love to read those sorts of thoughts too – even just a description about how and why my spitballing is logically inconsistent grasping at straws and the language design equivalent of alphabet soup, if that’s what it boiled down to.

Older posts »