我正在调试客户在生产系统上遇到的系统负载问题,他们制作了一个测试应用程序来模拟负载以重现该问题:

在这种特殊的工作量中,编码员要做的一件事是:

while(1)
  initialize inotify
  watch a directory for events
  receive event
  process event
  remove watch
  close inotify fd

奇怪的是,高系统负载来自inotify fd的close():
inotify_init()                          = 4 <0.000020>
inotify_add_watch(4, "/mnt/tmp/msys_sim/QUEUES/Child_032", IN_CREATE) = 1 <0.059537>
write(1, "Child [032] sleeping\n", 21)  = 21 <0.000012>
read(4, "\1\0\0\0\0\1\0\0\0\0\0\0\20\0\0\0SrcFile.b8tlfT\0\0", 512) = 32 <0.231012>
inotify_rm_watch(4, 1)                  = 0 <0.000044>
close(4)                                = 0 <0.702530>
open("/mnt/tmp/msys_sim/QUEUES/Child_032", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 4 <0.000031>
lseek(4, 0, SEEK_SET)                   = 0 <0.000010>
getdents(4, /* 3 entries */, 32768)     = 88 <0.000048>
getdents(4, /* 0 entries */, 32768)     = 0 <0.000009>
write(1, "Child [032] dequeue [SrcFile.b8t"..., 37) = 37 <0.000011>
unlink("/mnt/tmp/msys_sim/QUEUES/Child_032/SrcFile.b8tlfT") = 0 <0.059298>
lseek(4, 0, SEEK_SET)                   = 0 <0.000011>
getdents(4, /* 2 entries */, 32768)     = 48 <0.000038>
getdents(4, /* 0 entries */, 32768)     = 0 <0.000009>
close(4)                                = 0 <0.000012>
inotify_init()                          = 4 <0.000020>
inotify_add_watch(4, "/mnt/tmp/msys_sim/QUEUES/Child_032", IN_CREATE) = 1 <0.040385>
write(1, "Child [032] sleeping\n", 21)  = 21 <0.000903>
read(4, "\1\0\0\0\0\1\0\0\0\0\0\0\20\0\0\0SrcFile.mQgUSh\0\0", 512) = 32 <0.023423>
inotify_rm_watch(4, 1)                  = 0 <0.000012>
close(4)                                = 0 <0.528736>

是什么原因可能导致close()调用花费大量时间?我可以识别出两种可能的情况:
  • 每次
  • 关闭并重新初始化inotify
  • /mnt/tmp/msys_sim/SOURCES中有256K个文件(平面),并且/mnt/tmp/msys_sim/QUEUES/Child_032中的特定文件被硬链接(hard link)到该目录中的一个文件。但是上述过程
  • 从未打开SOURCES

    使用inotify错误是人为的吗?我能指出什么:“您在做什么错!”?
    perf top的输出(我一直在寻找这个!)
    Events: 109K cycles
     70.01%  [kernel]      [k] _spin_lock
     24.30%  [kernel]      [k] __fsnotify_update_child_dentry_flags
      2.24%  [kernel]      [k] _spin_unlock_irqrestore
      0.64%  [kernel]      [k] __do_softirq
      0.60%  [kernel]      [k] __rcu_process_callbacks
      0.46%  [kernel]      [k] run_timer_softirq
      0.40%  [kernel]      [k] rcu_process_gp_end
    

    甜的!我怀疑某个地方发生了自旋锁,发生这种情况时,整个系统会变得非常隐蔽。

    最佳答案

    通常,伪代码inotify循环如下所示:

    initialize inotify
    watch a directory | file for events
    
    while(receive event) {
      process event
    }
    
    [ remove watch ]
    close inotify fd
    

    不需要在每个循环上都删除监视并重新初始化inotify。

    关于linux - 正确使用linux inotify-每次都重新打开吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/20554806/

    10-11 17:48