Setting smaller buffer size for sys.stdin?
我使用以下bash命令模式运行memcached:
1 | memcached -vv 2>&1 | tee memkeywatch2010098.log 2>&1 | ~/bin/memtracer.py | tee memkeywatchCounts20100908.log |
要尝试并跟踪不匹配的,请访问平台范围内的密钥集。
memtracer脚本在下面,可以根据需要工作,只有一个小问题。观察中间日志文件的大小,memtracer.py在memkeywatchymd.log之前不会开始获取输入。尺寸约为15-18K。在stdin中是否有更好的读取方法,或者可能有一种将缓冲区大小减少到1K以下以加快响应时间的方法?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | #!/usr/bin/python import sys from collections import defaultdict if __name__ =="__main__": keys = defaultdict(int) GET = 1 SET = 2 CLIENT = 1 SERVER = 2 #if < for line in sys.stdin: key = None components = line.strip().split("") #newConn = components[0][1:3] direction = CLIENT if components[0].startswith("<") else SERVER #if lastConn != newConn: # lastConn = newConn if direction == CLIENT: command = SET if components[1] =="set" else GET key = components[2] if command == SET: keys[key] -= 1 elif direction == SERVER: command = components[1] if command =="sending": key = components[3] keys[key] += 1 if key != None: print"%s:%s" % ( key, keys[key], ) |
您可以使用python的
1 2 | -u : unbuffered binary stdout and stderr (also PYTHONUNBUFFERED=x) see man page for details on internal buffering relating to '-u' |
手册页澄清了:
1 2 3 4 5 6 7 | -u Force stdin, stdout and stderr to be totally unbuffered. On systems where it matters, also put stdin, stdout and stderr in binary mode. Note that there is internal buffering in xread- lines(), readlines() and file-object iterators ("for line in sys.stdin") which is not influenced by this option. To work around this, you will want to use"sys.stdin.readline()" inside a"while 1:" loop. |
除此之外,不支持更改现有文件的缓冲区,但可以使用os.fdpopen使用与现有文件描述符相同的底层文件描述符创建新的文件对象,也可以使用不同的缓冲区。即。,
1 2 3 | import os import sys newin = os.fdopen(sys.stdin.fileno(), 'r', 100) |
应将
您只需使用
1 2 3 4 5 6 7 | import sys while True: line = sys.stdin.readline() if not line: break # EOF sys.stdout.write('> ' + line.upper()) |
这使我可以使用Ubuntu13.04上的python 2.7.4和python 3.3.1进行行缓冲读取。
1 2 3 4 | import sys for line in iter(sys.stdin.readline, ''): sys.stdout.write('> ' + line.upper()) |
或者提供
这在Python3.4.3中对我很有用:
1 2 3 4 | import os import sys unbuffered_stdin = os.fdopen(sys.stdin.fileno(), 'rb', buffering=0) |
buffering is an optional integer used to set the buffering policy. Pass 0 to switch buffering off (only allowed in binary mode), 1 to select line buffering (only usable in text mode), and an integer > 1 to indicate the size in bytes of a fixed-size chunk buffer.
换言之:
- 完全未缓冲的stdin需要二进制模式,并将零作为缓冲区大小传递。
- 行缓冲需要文本模式。
- 任何其他缓冲区大小似乎都可以在二进制和文本模式下工作(根据文档)。
我用python 2.7做这件事的唯一方法是:
1 | tty.setcbreak(sys.stdin.fileno()) |
从python非阻塞控制台输入。这将完全禁用缓冲并抑制回声。
编辑:关于Alex的答案,第一个建议(使用
第二个命题(用较小的缓冲区复制fd: