【问题标题】:generating pretty and/or less system-intensive measuring-points生成漂亮和/或系统密集度较低的测量点
【发布时间】:2016-06-02 10:24:02
【问题描述】:

我使用 C 语言并制作 apache 模块,并使用 strace 作为调试时间的主要工具。这是我放在一起的代码。如果变量名不符合标准,我深表歉意。

#include <stdio.h>
int main(){
    long ct2,ct; //counters
    int a=0; //dummy value
    FILE *f0=fopen("/","r"); //measuring point
    ct2=10;
    while (--ct2>0){
      ct=5000000;
      while (--ct>0){
        if (!!a){
          printf("%d",a);
        }
      }
    }
    FILE *f=fopen("/","r");  //measuring point
    ct2=10;
    while (--ct2>0){
      ct=5000000;
      while (--ct>0){
        if (a){
          printf("%d",a);
        }
      }
    }
    FILE *f2=fopen("/","r");  //measuring point
    return 0;
}

这段代码可以编译。然后我通过 strace 运行它(通过在终端中输入:strace -r -ttt ./a.out),我看到了:

 0.000000 execve("./a.out", ["./a.out"], [/* 47 vars */]) = 0
 0.000315 brk(0)                    = 0x804a000
 0.000124 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
 0.000144 open("/etc/ld.so.cache", O_RDONLY) = 3
 0.000116 fstat64(3, {st_mode=S_IFREG|0644, st_size=139721, ...}) = 0
 0.000138 mmap2(NULL, 139721, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7ece000
 0.000114 close(3)                  = 0
 0.000109 open("/lib/libc.so.6", O_RDONLY) = 3
 0.000113 read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\360d\1"..., 512) = 512
 0.000130 fstat64(3, {st_mode=S_IFREG|0755, st_size=1575187, ...}) = 0
 0.000131 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7ecd000
 0.000122 mmap2(NULL, 1357360, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb7d81000
 0.000119 mmap2(0xb7ec7000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x146) = 0xb7ec7000
 0.000146 mmap2(0xb7eca000, 9776, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb7eca000
 0.000139 close(3)                  = 0
 0.000112 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7d80000
 0.000119 set_thread_area({entry_number:-1 -> 6, base_addr:0xb7d806c0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
 0.000217 mprotect(0xb7ec7000, 4096, PROT_READ) = 0
 0.000108 munmap(0xb7ece000, 139721) = 0
 0.000174 brk(0)                    = 0x804a000
 0.000099 brk(0x806b000)            = 0x806b000
 0.000110 open("/", O_RDONLY)       = 3
 0.203487 open("/", O_RDONLY)       = 4
 0.202225 open("/", O_RDONLY)       = 5
 0.000133 exit_group(0)             = ?

最后我可以说:

 0.000110 open("/", O_RDONLY)       = 3
 0.203487 open("/", O_RDONLY)       = 4
 0.202225 open("/", O_RDONLY)       = 5

回到我设置的三个测点。

我希望能够在我的代码中调整测量点线,这样当我运行 strace 时,我可以像现在一样找到我的测量点,但是系统在哪里进行的操作较少。除了文件调用之外,我没有从 strace 中看到与我的程序相关的任何其他内容。

我在想,如果 C 中有一个内置的 MeasureMe 函数,我可以用它来代替代码中的测量点线,那么 strace 可以输出:

 0.000110 MeasureMe called in code
 0.203487 MeasureMe called in code
 0.202225 MeasureMe called in code

我有什么办法可以用 Strace 解决这个问题吗?

我之所以询问 strace 而不是 gdb,是因为我使用它来调试对我的 apache 服务器的请求,就像本视频中的人所做的那样,我将能够看到 apache 模块的运行:

https://www.youtube.com/watch?v=eF-p--AH37E

知道如何解决这个问题吗?还是我必须继续尝试打开不存在的文件?

【问题讨论】:

  • 您可以通过使用open(..., O_PATH) 来降低open() 系统调用的成本。

标签: c performance performance-testing strace


【解决方案1】:

我收集到您当前使用的是open("/",O_RDONLY) [或open("/i_do_not_exist",O_RDONLY)] 作为“跟踪点”。不幸的是,因为您使用的是strace,所以您只能使用系统调用。但是,一种方法可以达到你想要的效果。


对于在源代码的各个点手动插入的跟踪点,您需要/想要的是:

  1. 任何不会伤害任何东西的独特系统调用
  2. 很容易与真实代码区分开来[即使是可能返回错误的代码,例如打开文件或使用access 检查是否存在]
  3. 最小开销/最快执行

实际上,dup 在一个坏的领域很好地填补了账单:

dup(-10000);

它将返回EBADF。它作为跟踪点很容易区分,因为大多数“坏”的真实dup 调用将是dup(-1)

您可以拥有任意数量的这些。实际的参数变成了“tracepoint number”:

dup(-10001);  // tracepoint 1
...
dup(-10002);  // tracepoint 2
...
dup(-10003);  // tracepoint 3

输出将如下所示:

     0.000044 dup(-10001)               = -1 EBADF (Bad file descriptor)
     0.000022 dup(-10002)               = -1 EBADF (Bad file descriptor)
     0.000019 dup(-10003)               = -1 EBADF (Bad file descriptor)

我通常将它封装在一个宏中:

#ifdef DEBUG
#define TRACEPOINT(_tno)        tracepoint(_tno)
#else
#define TRACEPOINT(_tno)        /**/
#endif

void
tracepoint(int tno)
{
    dup(-10000 - tno);
}

然后,我添加如下内容:

TRACEPOINT(1);  // initialization phase
...
TRACEPOINT(2);  // execution phase
...
TRACEPOINT(3);  // cleanup/shutdown

现在,我将编写一个 perlpython 脚本来读取源文件,提取给定跟踪点的 cmets,并将它们附加到 strace 输出文件中的匹配行:

     0.000044 TRACEPOINT(1) initialization phase
     0.000022 TRACEPOINT(2) execution phase
     0.000019 TRACEPOINT(3) cleanup/shutdown

更复杂的后处理脚本版本可以做各种各样的事情:

  1. 跟踪时间戳并将一个跟踪点与前一个跟踪点之间的时间差附加到跟踪行
  2. 将文件名和行号信息添加到跟踪点行
  3. 跟踪给定跟踪点的命中次数 [类似于 gdb 和断点]
  4. 生成与跟踪点相关的摘要报告

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-19
    • 2011-02-27
    • 1970-01-01
    • 1970-01-01
    • 2014-04-21
    相关资源
    最近更新 更多