# 5.2.4监控机器性能

> 译者： [https://sicp.comp.nus.edu.sg/chapters/105](https://sicp.comp.nus.edu.sg/chapters/105)

仿真不仅对验证建议的机器设计的正确性有用，而且对测量机器的性能也很有用。 例如，我们可以在仿真程序中安装&lt;quote&gt;仪表&lt;/quote&gt;，该仪表测量计算中使用的堆栈操作数。 为此，我们修改了模拟堆栈，以跟踪寄存器在堆栈中保存的次数和堆栈达到的最大深度，并向堆栈的界面添加一条消息以打印统计信息，如下所示。 我们还通过在`make_new_machine`中将`the_ops`初始化为

```js
list(list("initialize-stack", () => stack("initialize")),
     list("print-stack-statistics", () => stack("print-statistics")));
```

这是`make_stack`的新版本：

```js
function make_stack() { 
    let s = null;
    let number_pushes = 0;
    let max_depth = 0;
    let current_depth = 0;

    function push(x) {
        s = pair(x, s);
        number_pushes = number_pushes + 1;
        current_depth = current_depth + 1;
        max_depth = math_max(current_depth, math_max);
    }

    function pop() {
        if (is_null(s)) {
            error("Empty stack: POP");

        } else {
            const top = head(s);
            s = tail(s);
            current_depth = current_depth - 1;

            return top;
        }
    }

    function initialize() {
        s = null;
        number_pushes = 0;
        max_depth = 0;
        current_depth = 0;

        return "done";
    }

    function print_statistics() {
        display(accumulate((b, a) => stringify(a) + b,
                           list("\n", "total-pushes = ", number_pushes,
                                "\n", "maximum-depth = ", max_depth)));
    }

    function dispatch(message) {
        return message === "push"
            ? push
            : message === "pop"
            ? pop()
            : message === "initialize"
            ? initialize()
            : message === "print-statistics"
            ? print_statistics()
            : error(message, "Unknown request: STACK");
    }

    return dispatch;
}
```

练习 [5.15](105#ex_5.15)[5.19](105#ex_5.19) 描述了可以添加到寄存器计算机模拟器的其他有用的监视和调试功能。

<exercise>Measure the number of pushes and the maximum stack depth required to compute ![n!](img/9dc6259785da3af5bb9d517f330964af.jpg) for various small values of ![n](img/493731e423d5db62086d0b8705dda0c8.jpg) using the factorial machine shown in Figure <ref name="fig:fact-machine">[5.11](99#fig_5.11)</ref>. From your data determine formulas in terms of ![n](img/493731e423d5db62086d0b8705dda0c8.jpg) for the total number of push operations and the maximum stack depth used in computing ![n!](img/9dc6259785da3af5bb9d517f330964af.jpg) for any ![n%20%3E%201](img/7e0f0014bb76cd0cfd31c1ce37ce0acf.jpg). Note that each of these is a linear function of ![n](img/493731e423d5db62086d0b8705dda0c8.jpg) and is thus determined by two constants. In order to get the statistics printed, you will have to augment the factorial machine with instructions to initialize the stack and print the statistics. You may want to also modify the machine so that it repeatedly reads a value for ![n](img/493731e423d5db62086d0b8705dda0c8.jpg), computes the factorial, and prints the result (as we did for the GCD machine in figure <ref name="fig:gcd-with-io">[5.4](96#fig_5.4)</ref>), so that you will not have to repeatedly invoke `get_register_contents`, `set_register_contents`, and start.<button class="btn btn-secondary solution_btn" data-toggle="collapse" href="#no_solution_105_1_div">Add solution</button>There is currently no solution available for this exercise. This textbook adaptation is a community effort. Do consider contributing by providing a solution for this exercise, using a Pull Request in [Github](https://github.com/source-academy/sicp).</exercise><exercise>Add _instruction counting_ to the register machine simulation. That is, have the machine model keep track of the number of instructions executed. Extend the machine model's interface to accept a new message that prints the value of the instruction count and resets the count to zero.<button class="btn btn-secondary solution_btn" data-toggle="collapse" href="#no_solution_105_1_div">Add solution</button>There is currently no solution available for this exercise. This textbook adaptation is a community effort. Do consider contributing by providing a solution for this exercise, using a Pull Request in [Github](https://github.com/source-academy/sicp).</exercise><exercise>Augment the simulator to provide for _instruction tracing_. That is, before each instruction is executed, the simulator should print the text of the instruction. Make the machine model accept `trace_on` and `trace_off` messages to turn tracing on and off.<button class="btn btn-secondary solution_btn" data-toggle="collapse" href="#no_solution_105_1_div">Add solution</button>There is currently no solution available for this exercise. This textbook adaptation is a community effort. Do consider contributing by providing a solution for this exercise, using a Pull Request in [Github](https://github.com/source-academy/sicp).</exercise><exercise>Extend the instruction tracing of exercise <ref name="ex:reg-machine-instruction-trace">[5.16](105#ex_5.16)</ref> so that before printing an instruction, the simulator prints any labels that immediately precede that instruction in the controller sequence. Be careful to do this in a way that does not interfere with instruction counting (exercise <ref name="ex:instruction-count">[5.15](105#ex_5.15)</ref>). You will have to make the simulator retain the necessary label information.<button class="btn btn-secondary solution_btn" data-toggle="collapse" href="#no_solution_105_1_div">Add solution</button>There is currently no solution available for this exercise. This textbook adaptation is a community effort. Do consider contributing by providing a solution for this exercise, using a Pull Request in [Github](https://github.com/source-academy/sicp).</exercise><exercise>Modify the `make_register` function of section <ref name="sec:machine-model">[5.2.1](102)</ref> so that registers can be traced. Registers should accept messages that turn tracing on and off. When a register is traced, assigning a value to the register should print the name of the register, the old contents of the register, and the new contents being assigned. Extend the interface to the machine model to permit you to turn tracing on and off for designated machine registers.<button class="btn btn-secondary solution_btn" data-toggle="collapse" href="#no_solution_105_1_div">Add solution</button>There is currently no solution available for this exercise. This textbook adaptation is a community effort. Do consider contributing by providing a solution for this exercise, using a Pull Request in [Github](https://github.com/source-academy/sicp).</exercise><exercise>Alyssa P. Hacker wants a _breakpoint_ feature in the simulator to help her debug her machine designs. You have been hired to install this feature for her. She wants to be able to specify a place in the controller sequence where the simulator will stop and allow her to examine the state of the machine. You are to implement a function `set_breakpoint(![machine](img/81264b0c4245e889b186409afc4d6ba0.jpg), ![label](img/728d445fc7e434bce80e0277d7736475.jpg), ![n](img/493731e423d5db62086d0b8705dda0c8.jpg));` that sets a breakpoint just before the ![n](img/493731e423d5db62086d0b8705dda0c8.jpg)th instruction after the given label. For example,

```js
set_breakpoint(gcd_machine, "test-b", 4);
```

installs a breakpoint in `gcd_machine` just before the assignment to register a. When the simulator reaches the breakpoint it should print the label and the offset of the breakpoint and stop executing instructions. Alyssa can then use `get_register_contents` and `set_register_contents` to manipulate the state of the simulated machine. She should then be able to continue execution by saying `proceed_machine(![machine](img/81264b0c4245e889b186409afc4d6ba0.jpg));` She should also be able to remove a specific breakpoint by means of `cancel_breakpoint(![machine](img/81264b0c4245e889b186409afc4d6ba0.jpg), ![label](img/728d445fc7e434bce80e0277d7736475.jpg), ![n](img/493731e423d5db62086d0b8705dda0c8.jpg));` or to remove all breakpoints by means of `cancel_all_breakpoints(![machine](img/81264b0c4245e889b186409afc4d6ba0.jpg));`<button class="btn btn-secondary solution_btn" data-toggle="collapse" href="#no_solution_105_1_div">Add solution</button>There is currently no solution available for this exercise. This textbook adaptation is a community effort. Do consider contributing by providing a solution for this exercise, using a Pull Request in [Github](https://github.com/source-academy/sicp).</exercise>