ZHCADC4A September 2011 – March 2014
动态链接会造成性能损失。通过 PLT 调用的导入函数会产生额外调用的开销,类似于蹦床函数。如果通过 GOT 访问函数的地址,则还存在间接访问以载入其地址的开销。
通过 DP 寻址的 near 数据不会有任何损失。对于 far 数据,DP 相对寻址需要三条指令,而与位置有关的绝对寻址需要两条指令。对于通过 GOT 寻址的对象,存在额外引用 GOT 以载入地址的开销。
符号抢占显著加剧了 GOT 损失。编译器和静态链接器必须将任何可能被抢占的符号(即共享库中定义的任何全局符号)视为导入符号。即使是本地定义的函数也必须通过 PLT 调用,从而排除内联或专门化。本地定义的变量必须通过 GOT 间接访问。这些限制适用于编译器生成的代码,因此即使符号最终未被抢占,损失通常也无法恢复。
由于抢占而造成的损失仅适用于共享库。可执行文件(不是库)中定义的符号不能被抢占。
系统采用多种技术来减轻这些影响。在某些遵循 DLL 模型的系统(Windows、Palm、Symbian)中,除非明确声明,定义的符号不被视为导出符号。
在 UNIX 系统(包括 Linux)中,所有外部符号都可能为动态链接,这意味着编译器必须为所有此类符号生成低效的 GOT 间接寻址。为了减轻这种影响,UNIX 模型采用“作为自有导入”模型,如节 15.9所述。
工具链可以采用其他特定于供应商的方法来减轻抢占损失,例如通过选项或声明说明符来改变外部符号的默认可见性。
DSBT 模型引入了开销(因为导出函数必须保存和恢复 DP),即 3 条指令和 2 个存储器引用的成本。表本身也具有数据大小开销,它向每个可执行文件和库的数据段添加 N+1 个字,其中 N 是应用使用的任何库的最大索引。