notes-computer-programming-nock-nockJets

Nock 'jets'

" How does Nock obtain native CPU performance, if it can’t call native code? This is actually a much more pressing problem in Nock than in conventional virtual machines, like the JVM, because naive Nock is hopelessly inefficient. Nock is defined in a page of pseudocode, and a naive interpreter can be written in a page of any language. But since Nock’s only arithmetic operator is increment, decrement in your one-page interpreter is an O(n) operation. Addition is O(n^2). And so on.

The programmer cannot solve this problem by calling a C function, because Nock can’t do that. In theory, an optimizing Nock interpreter might be able to analyze the code and reduce it to a simpler equivalent. But this would be a true research problem.

Instead, a practical Nock engine simply recognizes code it knows and substitutes equivalent C functions, or “jets.” For instance, in theory there are many different ways to express decrement in Nock, but in practice the Nock interpreter will execute only one: the decrement function in the Hoon kernel. Therefore, the only Nock decrement that must be optimized is the code that Hoon generates when it compiles its own decrement. All others will suck, so don’t roll your own. Code recognition, as opposed to code analysis, is not a research problem.

Jet propulsion separates mechanism and policy, transferring the task of achieving native performance from the programmer to the sysadmin. The Hoon programmer must still use hints to mark functions for jet recognition, but cannot control or discern how these functions are actually executed. Of course, a correct jet is indistiguishable in every way, except timing, from naive Nock. The 200-word spec defines the result, not the algorithm.

We can see a jet as a sort of “functional device driver.” For instance, an OpenGL? programmer today has no idea whether her GL operations are implemented in software or by a GPU. This abstraction is essential to modern graphics programming.

When we compare jets to native calls, what are the pros and cons? Jets have only one disadvantage: high-performance code must be written twice, once in Hoon and once in C. Indeed, from the C programmer’s perspective, Hoon is a specification language for your C functions. Hoon specifications are executable, of course, so you can test the two implementations against each other - again, transparently to the programmer. Moreover, the jet can even fail in special cases and drop back to the interpreter.

Hoon ships with a Nock that jet-propels most of the Hoon kernel, including most of the Hoon compiler. If you’re wondering how we wrote Hoon in Hoon when we didn’t have Hoon, the answer is that we wrote Hoon in C and evolved this C code into a mere jet. This process is not recommended unless absolutely necessary - by far the best way to write the jet pair is to write the Hoon first. " -- http://web.archive.org/web/20131005165939/http://www.urbit.org/2013/08/22/Chapter-0-intro.html