局部原理及调用说明
Principle of Locality and Call Instructions
在讨论局部性原则时,我的教科书是这样表述的:
Except for branch and call instructions, which constitute only a small
fraction of all program instructions, program execution is sequential.
Hence, in most cases, the instruction to be fetched immediately
follows the last instruction fetched.
作为新手,我觉得这很难相信。我遇到的所有代码都高度填充了调用指令。事实上,在我看来,调用指令实际上执行了程序中最实质性的操作。
尽管调用指令在程序中起着重要作用,但如果有人能详细说明为什么这个概念是正确的,我将不胜感激。
我在我的电脑上随机选择了一个二进制文件,cargo
包管理器。那我:
- 用
otool -tvV cargo > assembly
反汇编
- 只得到说明:
cat assembly | awk '{print }' > instructions
- 计算每条指令:
sort instructions | uniq -c | sort -n > count
我将 Libreoffice Calc 中的结果处理成每条指令出现的列表。以下是每个占程序 1% 以上的操作(这些总和高达 86%,因此我为了 brewity 而丢弃了大量的杂散操作):
| 34.83% | movq |
| 7.30% | leaq |
| 7.00% | callq |
| 6.90% | je |
| 5.61% | movl |
| 4.86% | cmpq |
| 3.77% | testq |
| 3.11% | jmp |
| 2.23% | jne |
| 2.17% | popq |
| 2.05% | pushq |
| 1.69% | addq |
| 1.29% | cmpl |
| 1.20% | movabsq |
| 1.18% | movb |
| 1.05% | xorl |
这里肯定有很多分支和调用(callq
、jmp
、je
、jne
),但也有很多内存操作。内存操作相对较慢,占程序运行时间的很大一部分。 movq
只是一个内存操作,却占了程序的三分之一以上!
CPU 缓存用于将最近引用的内存数据保持在靠近 CPU 核心的位置,从而加快以后对相同数据的内存操作。他们之所以可以这样做,是因为 Principle of Locality 表明对同一内存的操作通常会在时间上接近(时间局部性)。所以可以缓存内存数据,因为您可能很快就会再次需要它。
在讨论局部性原则时,我的教科书是这样表述的:
Except for branch and call instructions, which constitute only a small fraction of all program instructions, program execution is sequential. Hence, in most cases, the instruction to be fetched immediately follows the last instruction fetched.
作为新手,我觉得这很难相信。我遇到的所有代码都高度填充了调用指令。事实上,在我看来,调用指令实际上执行了程序中最实质性的操作。
尽管调用指令在程序中起着重要作用,但如果有人能详细说明为什么这个概念是正确的,我将不胜感激。
我在我的电脑上随机选择了一个二进制文件,cargo
包管理器。那我:
- 用
otool -tvV cargo > assembly
反汇编
- 只得到说明:
cat assembly | awk '{print }' > instructions
- 计算每条指令:
sort instructions | uniq -c | sort -n > count
我将 Libreoffice Calc 中的结果处理成每条指令出现的列表。以下是每个占程序 1% 以上的操作(这些总和高达 86%,因此我为了 brewity 而丢弃了大量的杂散操作):
| 34.83% | movq |
| 7.30% | leaq |
| 7.00% | callq |
| 6.90% | je |
| 5.61% | movl |
| 4.86% | cmpq |
| 3.77% | testq |
| 3.11% | jmp |
| 2.23% | jne |
| 2.17% | popq |
| 2.05% | pushq |
| 1.69% | addq |
| 1.29% | cmpl |
| 1.20% | movabsq |
| 1.18% | movb |
| 1.05% | xorl |
这里肯定有很多分支和调用(callq
、jmp
、je
、jne
),但也有很多内存操作。内存操作相对较慢,占程序运行时间的很大一部分。 movq
只是一个内存操作,却占了程序的三分之一以上!
CPU 缓存用于将最近引用的内存数据保持在靠近 CPU 核心的位置,从而加快以后对相同数据的内存操作。他们之所以可以这样做,是因为 Principle of Locality 表明对同一内存的操作通常会在时间上接近(时间局部性)。所以可以缓存内存数据,因为您可能很快就会再次需要它。