为什么`xclip .bashrc`比ruby中的系统(“xclip .bashrc”)需要更长的时间?

时间:2013-10-08 01:25:35

标签: ruby linux xclip

irb(main):001:0> require 'benchmark'
=> true
irb(main):002:0> puts Benchmark.measure { system "xclip .bashrc" }
  0.000000   0.000000   0.000000 (  0.008030)
=> nil
irb(main):003:0> puts Benchmark.measure { `xclip .bashrc` }
  0.000000   0.000000   0.000000 ( 33.215158)
=> nil
irb(main):004:0> RUBY_VERSION
=> "2.0.0"

我已经阅读了互联网上关于从ruby脚本调用shell命令的各种方法的所有内容,但我无法弄清楚为什么Kernel#`Kernel#system需要更长的时间。

更新

Kernel#`仅在xclip时速度慢得多。所有其他命令几乎都需要相同的时间。

2 个答案:

答案 0 :(得分:3)

我怀疑xclip只需要很长时间就可以在你使用反引号来终止时终止。这与选择有关。如果没有通过-sel提供任何选择,它将默认为XA_PRIMARY,它通常用于通过鼠标中键实现复制和粘贴。

运行时

$ xclip text.txt

内容可通过XA_PRIMARY获得,这意味着您可以通过鼠标中键或$ xclip -o粘贴内容。当你在Ruby中执行它时,它开始变得奇怪了:

ruby -e '`xclip text.txt`

如果你什么都不做,它永远不会终止。当您在X11系统中选择某些内容时,它会终止,例如在控制台或其他任何位置。只需选择,用鼠标标记。如果不这样做,它会在某个时刻挂起和/或超时。

使用详细模式时可以观察到相同的行为:

$ xclip -verbose text.txt

Connected to X server.
Using UTF8_STRING.
Reading text.txt...
Waiting for selection requests, Control-C to quit
  Waiting for selection request number 1

当您选择某些内容时,会再次提供选择请求。

一个很好的分析工具是strace-f选项也用于跟踪分叉)

$ strace -f ruby -e '`xclip text.txt`'

...
poll([{fd=3, events=POLLIN|POLLOUT}], 1, 4294967295) = 1 ([{fd=3, revents=POLLOUT}])
writev(3, [{"\20\0\3\0\4\0\200\2INCR", 12}, {NULL, 0}, {"", 0}], 3) = 12
poll([{fd=3, events=POLLIN}], 1, 4294967295) = 1 ([{fd=3, revents=POLLIN}])
recvfrom(3, "\1\0\f\0\0\0\0\0\235\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 4096,                                                                      0, NULL, NULL) = 32
recvfrom(3, 0x165e964, 4096, 0, 0, 0)   = -1 EAGAIN (Resource temporarily unavailable)
recvfrom(3, 0x165e964, 4096, 0, 0, 0)   = -1 EAGAIN (Resource temporarily unavailable)
poll([{fd=3, events=POLLIN}], 1, 4294967295

在最后一行中它会挂起,直到做出选择。 poll()用于等待文件描述符处的文件事件。它将在某个时刻终止,但是4,294,967,295 ms相当长。仅使用strace -f xclip text.txt即可跟踪它。

您可以通过ls -l /proc/PID/fd查看文件描述符。编号为3的文件描述符是xclip等待您选择的文件描述符。

调试如此困难的原因是,如果使用strace xclip text.txt立即终止,而不是strace -f text.txt终止。你想跟踪叉子的那一刻它不再起作用了。这与Ruby的问题相同。它试图跟踪输出,因为Kernel#`想要返回输出。这可能与票证#9 Not closing stdout when setting clipboard from stdin有关。

这是我的理论。你想要遵循xclip输出的那一刻,无论是使用Ruby从标准输出读取,还是strace来追踪分支,标准输出都不会关闭,直到你创建一个选择。

这不能很好地解释它,但它表明它不需要对Ruby做任何事情。我将创建一个仅关注xclip而不是Ruby背景的问题。

答案 1 :(得分:-1)

您需要提供更多详细信息,了解您使用xclip进行的操作。 B / c(因为)我的ruby 1.9.3使用“echo hello”表示差异很小。

$ irb
irb(main):001:0> require 'benchmark'
=> true
irb(main):002:0> puts Benchmark.measure {  `echo hello` }
  0.000000   0.000000   0.000000 (  0.001471)
=> nil
irb(main):003:0> puts Benchmark.measure { system "echo hello" }
hello
  0.000000   0.000000   0.000000 (  0.001598)
=> nil
irb(main):004:0> RUBY_VERSION
=> "1.9.3"