使用gdb准确获得断点间代码运行时间的方法和对emacs windows上进程启动的研究

先介绍一个技巧,就是如何用gdb准确获得断点间代码运行时间,昨天用这个方法分析了emacs windows版本上进程启动相关代码

比如我现在想准确测量emacs源码中 callproc.c第678行到925行的运行时间,
1 先在678行和925行都下断点,程序跑起来,停在678行
2 然后在本地创建一个文件,写入如下内容

python import time
python starttime=time.time()
finish
python endtime=time.time()
python print (endtime-starttime)

3 在gdb中source这个文件,如下就获得了这段代码的运行时间

4 自己修改脚本,可以灵活测量多种不同的情况,比如一些异步的操作,这里就不细说了


对emacs windows上进程启动的研究
首先是单独做了一些测试,
执行的命令为 git --version ,执行一百次
结果如下(这里参考我的另一个cmdproxy的帖子做了优化,不做的话会慢差不多零点几秒)

1 windows emacs shell-command 7.51s
2 linux emacs shell-command 0.25s
3 windows 下用system函数执行 3.76s
4 linux 下用system函数执行 0.15s
5 windows emacs call-process 5.67s
6 linux emacs call-process 0.07s

然后分析emacs的源码,使用二分法,测量时间,最后可以定位到,执行call-process,主要的时间就花在了callproc.c的678行到924行
678行执行了emacs_spawn,最终是调用了CreateProcess启动进程,
924行执行了wait_for_termination,最终是调用了WaitForMultipleObjects等待这个进程结束
这里也不涉及之前提到的模拟机制。

于是写如下代码进行测试


#include <stdio.h>
#include <stdlib.h>
#include <chrono>
#include <iostream>
#include <windows.h>

using namespace std;
using namespace std::chrono;

void f() {
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    DWORD status;
    TCHAR cmd[MAX_PATH] = TEXT("git.exe --version");

    for (int i = 0; i < 100; ++i) {
        ZeroMemory(&si, sizeof(si));
        si.cb = sizeof(si);
        ZeroMemory(&pi, sizeof(pi));

        if (!CreateProcess(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
        {
            printf("wrong1\n");
            return;
        }

        WaitForSingleObject(pi.hProcess, INFINITE);

        GetExitCodeProcess(pi.hProcess, &status);

        CloseHandle(pi.hProcess);
        CloseHandle(pi.hThread);
    }

}
int main() {
    auto t0 = std::chrono::steady_clock::now();
    f();
    auto t1 = std::chrono::steady_clock::now();

    cout << nanoseconds{t1 - t0}.count() << "ns\n";
    std::this_thread::sleep_for(1s);
    std::cout << std::chrono::duration_cast<std::chrono::milliseconds>(t1 - t0).count() << "ms\n";

}

最终也花了3秒左右,网上也查了不少资料,都没啥办法,已经是最简化的代码了。看来这块没啥办法了。

11 个赞