Simulation is useful not only for verifying the correctness of a
proposed machine design but also for measuring the machine's
performance. For example, we can install in our simulation program a
meter
that measures the number of stack operations used in a
computation. To do this, we modify our simulated stack to keep track
of the number of times registers are saved on the stack and the
maximum depth reached by the stack, and add a message to the stack's
interface that prints the statistics, as shown below.
We also add an operation to the basic machine model to print the
stack statistics, by initializing
the-ops
the_ops
in
make-new-machine
make_new_machine
to
| Original | Python |
| (list (list 'initialize-stack (lambda () (stack 'initialize))) (list 'print-stack-statistics (lambda () (stack 'print-statistics)))) | llist(llist("initialize_stack", lambda: stack("initialize")), llist("print_stack_statistics", lambda: stack("print_statistics"))) |
| Original | Python |
| (define (make-stack) (let ((s '()) (number-pushes 0) (max-depth 0) (current-depth 0)) (define (push x) (set! s (cons x s)) (set! number-pushes (+ 1 number-pushes)) (set! current-depth (+ 1 current-depth)) (set! max-depth (max current-depth max-depth))) (define (pop) (if (null? s) (error "Empty stack - - POP") (let ((top (car s))) (set! s (cdr s)) (set! current-depth (- current-depth 1)) top))) (define (initialize) (set! s '()) (set! number-pushes 0) (set! max-depth 0) (set! current-depth 0) 'done) (define (print-statistics) (newline) (display (list 'total-pushes '= number-pushes 'maximum-depth '= max-depth))) (define (dispatch message) (cond ((eq? message 'push) push) ((eq? message 'pop) (pop)) ((eq? message 'initialize) (initialize)) ((eq? message 'print-statistics) (print-statistics)) (else (error "Unknown request - - STACK" message)))) dispatch)) | def make_stack(): stack = None number_pushes = 0 max_depth = 0 current_depth = 0 def push(x): nonlocal stack, number_pushes, current_depth, max_depth stack = pair(x, stack) number_pushes = number_pushes + 1 current_depth = current_depth + 1 max_depth = math_max(current_depth, max_depth) return "done" def pop(): nonlocal stack, current_depth if is_null(stack): error("empty stack -- pop") else: top = head(stack) stack = tail(stack) current_depth = current_depth - 1 return top def initialize(): nonlocal stack, number_pushes, max_depth, current_depth stack = None number_pushes = 0 max_depth = 0 current_depth = 0 return "done" def print_statistics(): display("total pushes = " + stringify(number_pushes)) display("maximum depth = " + stringify(max_depth)) def dispatch(message): return (push if message == "push" else pop() if message == "pop" else initialize() if message == "initialize" else print_statistics() if message == "print_statistics" else error("unknown request -- stack", message)) return dispatch |
Exercises 5.14 through 5.18 describe other useful monitoring and debugging features that can be added to the register-machine simulator.
| Original | Python |
| (set-breakpoint $machine$ $label$ $n$) | set_breakpoint($machine$, $label$, $n$) |
| Original | Python |
| (set-breakpoint gcd-machine 'test-b 4) | set_breakpoint(gcd_machine, "test_b", 4) |
| Original | Python |
| (proceed-machine $machine$) | proceed_machine($machine$) |
| Original | Python |
| (cancel-breakpoint $machine$ $label$ $n$) | cancel_breakpoint($machine$, $label$, $n$) |
| Original | Python |
| (cancel-all-breakpoints $machine$) | cancel_all_breakpoints($machine$) |