Previous: Transactions make errors survivable, Up: Tutorial [Contents][Index]
“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, called fork-motors
and
spawned in a-vat
:
scheme> ,enter-vat a-vat goblins[1]> (define fork-motors (spawn ^car-factory "Fork"))
Since asynchronous message passing with <-
works across
machines, it does not matter whether interactions with
fork-motors
are local or via objects communicating over the
network. This example treat fork-motors
as living on machine A,
and so the following interactions will happen with invocations
originating from machine B.
Now send a message to fork-motors
invoking the
'make-car
method, receiving back a promise for the car which
will be made, which will be 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 you have a promise to a future car reference, but not the reference itself. You 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 already shown (and following the pattern most other distributed programming systems use), you 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, you can simply message the promise of the car
directly. The first benefit can be observed from code compactness, in
that you do not need to do an on
of car-vow
to later
message our-car
; you 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 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 programmers to make plans and allows Goblins to optimize carrying out those steps as bulk operations over the network.
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, see both the Promise Pipelining page from erights.org and sections 2.5 and 16.2 of Mark Miller’s dissertation.
Previous: Transactions make errors survivable, Up: Tutorial [Contents][Index]