为什么动态链接需要花费这么多时间?

问题描述 投票:-1回答:1

所以我写了一个非常基本的虚拟机,它运行在一小部分c-上。我正在分析它,试图看看瓶颈是什么,结果让我很困惑。 73%的时间用于dl_relocate_object函数。在该函数中,85%用于_dl_lookup_symbol_x。

我对动态库的内部结构知之甚少,但我觉得有些不对劲。基于一点点搜索,这意味着75%的时间,我的程序正在通过动态库搜索函数。这对我来说听起来很荒谬。

当我静态链接二进制文件时,速度提高了2倍,最差函数变为我的VM :: run函数,为90%。在该功能中,75%用于ifstream。

基本上我想知道是否有人知道为什么会发生这种情况或是否正常。当我动态链接时,我的程序运行速度与程序的解释版本大致相同,该程序必须是lex并解析原始文本。

这是我的代码:

#include <iostream>
#include <vector>
#include <fstream>

using namespace std;

enum opcodes{halt, loadInt, storeVar, loadVar, readVar, writeInt, writeString,
add, sub, mul, divide, eq, neq, leq, ls, gr, geq, notVal, andVal, orVal};

class VM {
    unsigned long pc;
    vector<int> stack;
    ifstream imem;
    char buf[1024*64];
    int var[256];
  public:
    VM(char* file){
        imem.open(file);
        imem >> noskipws;
        imem.rdbuf()->pubsetbuf(buf, 1024*64);
    }
    void run(){
        int x, y;
        char c;
        char instruction;
        while(imem >> instruction){
            switch(instruction){
                case halt:
                    goto exit_loop;
                case writeString:
                    imem >> c;
                    while(c != 0){
                        cout << c;
                        imem >> c;
                    }
                    cout << endl;
                    break;
                case loadInt:
                    imem >> c;
                    x = (c << 24);
                    imem >> c;
                    x |= (c << 16);
                    imem >> c;
                    x |= (c << 8);
                    imem >> c;
                    x |= c;
                    stack.push_back(x);
                    break;
                case storeVar:
                    imem >> c;
                    var[(int)c] = stack.back();
                    stack.pop_back();
                    break;
                case loadVar:
                    imem >> c;
                    stack.push_back(var[(int)c]);
                    break;
                case readVar:
                    imem >> c;
                    cin >> var[(int)c];
                    break;
                case writeInt:
                    x = stack.back();
                    stack.pop_back();
                    cout << x << endl;
                    break;
                case add:
                    y = stack.back();
                    stack.pop_back();
                    x =stack.back();
                    stack.pop_back();
                    stack.push_back(x + y);
                    break;
                case sub:
                    y = stack.back();
                    stack.pop_back();
                    x =stack.back();
                    stack.pop_back();
                    stack.push_back(x - y);
                    break;
                case mul:
                    y = stack.back();
                    stack.pop_back();
                    x =stack.back();
                    stack.pop_back();
                    stack.push_back(x * y);
                    break;
                case divide:
                    y = stack.back();
                    stack.pop_back();
                    x =stack.back();
                    stack.pop_back();
                    stack.push_back(x / y);
                    break;
                case eq:
                    y = stack.back();
                    stack.pop_back();
                    x =stack.back();
                    stack.pop_back();
                    stack.push_back((int)(x == y));
                    break;
                case neq:
                    y = stack.back();
                    stack.pop_back();
                    x =stack.back();
                    stack.pop_back();
                    stack.push_back((int)(x != y));
                    break;
                case leq:
                    y = stack.back();
                    stack.pop_back();
                    x =stack.back();
                    stack.pop_back();
                    stack.push_back((int)(x <= y));
                    break;
                case ls:
                    y = stack.back();
                    stack.pop_back();
                    x =stack.back();
                    stack.pop_back();
                    stack.push_back((int)(x < y));
                    break;
                case gr:
                    y = stack.back();
                    stack.pop_back();
                    x =stack.back();
                    stack.pop_back();
                    stack.push_back((int)(x > y));
                    break;
                case geq:
                    y = stack.back();
                    stack.pop_back();
                    x =stack.back();
                    stack.pop_back();
                    stack.push_back((int)(x >= y));
                    break;
                case notVal:
                    x = stack.back();
                    stack.pop_back();
                    stack.push_back((int)(!x));
                    break;
                case andVal:
                    y = stack.back();
                    stack.pop_back();
                    x =stack.back();
                    stack.pop_back();
                    stack.push_back((int)(x && y));
                    break;
                case orVal:
                    y = stack.back();
                    stack.pop_back();
                    x =stack.back();
                    stack.pop_back();
                    stack.push_back((int)(x || y));
                    break;
                default:
                    cout << "Error: Unknown Instruction" << endl;
                    goto exit_loop;
            }
        }
        exit_loop: ;
    };
};

int main(int argc, char** argv) {
    if(argc <= 1){
        cout << "Bad input" << endl;
    }
    VM vm(argv[1]);
    vm.run();
}

注意,我已经尝试在VM初始化期间将整个文件加载到char []中,然后在运行期间使用char []而不是ifstream。我也尝试使用int []作为堆栈。这些变化都没有任何区别。

c++ linux performance static-linking dynamic-linking
1个回答
0
投票

感谢上面的一些评论和这个链接Is a DLL slower than a static link?我决定用更大的输入测试并获得预期的结果。显然循环迭代非常快,即使进行1_000次迭代,动态链接仍然占用大部分时间。通过1_000_000次迭代,代码按预期执行。静态和动态都在非常相似的时间运行。此外,在查看1_000_000条指令时,它的运行速度比解释器快9倍。

旁注,我最初在while循环后有说明,这就是为什么我有goto。我后来删除了它们。我想现在已经过时了。

© www.soinside.com 2019 - 2024. All rights reserved.