Previous: , Up: Tutorial   [Contents]


4.7 Promise pipelining

“Machines grow faster and memories grow larger. But the speed of light is constant and New York is not getting any closer to Tokyo.”

— Mark S. Miller, Robust Composition: Towards a Unified Approach to Access Control and Concurrency Control

Promise pipelining provides two different features at once:

Consider the following car factory, which makes cars carrying the company name of the factory:

;; Create a "car factory", which makes cars branded with
;; company-name.
(define (^car-factory bcom company-name)
  ;; The constructor for cars we will create.
  (define (^car bcom model color)
    (methods                      ; methods for the ^car
     ((drive)                    ; drive the car
      (format #f "*Vroom vroom!*  You drive your ~a ~a ~a!"
              color company-name model))))
  ;; methods for the ^car-factory instance
  (methods                        ; methods for the ^car-factory
   ((make-car model color)       ; create a car
    (spawn ^car model color))))

Here is an instance of this car factory, which we will call fork-motors, which we will spawn on a-vat:

scheme> ,enter a-vat
goblins[1]> (define fork-motors
              (spawn ^car-factory "Fork"))

Since asynchronous message passing with <- works across machines, it does not matter whether interacitons with fork-motors are local or via objects communicating over the network. We will treat fork-motors as living on machine A, and so the following interactions will happen with invocations originating from machine B.

Let’s send a message to fork-motors invoking the 'make-car method, receiving back a promise for the car which will be made, which we shall name car-vow (-vow being the conventional suffix given for promises in Goblins):

goblins[1]> ,q
scheme> ,enter-vat b-vat
;; Interaction on machine B, communicating with fork-motors on A
goblins[1]> (define car-vow
              (<- fork-motors 'make-car "Explorist" "blue"))

So we have a promise to a future car reference, but not the reference itself. We would like to drive the car as soon as it rolls off the lot of the factory, which of course involves sending a message to the car.

Without promise pipelining, making use of the tools we have already shown (and following the pattern most other distributed programming systems use), we would end up with something like:

;; Interaction on machine B, communicating with A
goblins[1]> (on car-vow                    ; B->A: first resolve the car-vow
                (lambda (our-car)          ; A->B: car-vow resolved as our-car
                  (on (<- our-car 'drive)  ; B->A: now we can message our-car
                      (lambda (val)        ; A->B: result of that message
                        (format #f "Heard: ~a\n" val)))))

With promise pipelining, we can simply message the promise of the car directly. The first benefit can be observed from code compactness, in that we do not need to do an on of car-vow to later message our-car, we can simply message car-vow directly:

;; Interaction on machine B, communicating with A
goblins[1]> (on (<- car-vow 'drive)       ; B->A: send message to future car
                (lambda (val)             ; A->B: result of that message
                  (format #t "Heard: ~a\n" val)))

While clearly a considerable programming convenience, the other advantage of promise pipelining is a reduction of round-trips, whether between our event-loop vats or across machines on the network.

This can be understood by looking at the comments to the right of the two above code interactions. The message flow in the first case looks like:

B => A => B => A => B

The message flow in the second case looks like:

B => A => B

In other words, machine B can say to machine A: “Make me a car, and as soon as that car is ready, I want to drive it!”

With this in mind, the promise behind Mark Miller’s quote at the beginning of this section is clear.1 If two objects are on opposite ends of the planet, round trips are unavoidably expensive. Promise pipelining both allows us to make plans as programmers and allows for Goblins to optimize carrying out those steps as bulk operations over the network.


Footnotes

(1)

Like so many examples in this document, the designs of promise pipelining and the explanation of its value come from the E programming language, the many contributors to its design, and Mark S. Miller’s extraordinary work documenting that work and its history. If you find this section interesting, both the the Promise Pipelining page from erights.org and sections 2.5 and 16.2 of Mark Miller’s dissertation.


Previous: , Up: Tutorial   [Contents]