问题
pytesseract.image_to_string()
当我通过supervisordd运行脚本时花费了太多时间,但是当直接在shell中运行时(在同一服务器上并与supervisor脚本同时运行)几乎立即执行。
除了花费太多时间之外,这些进程还显示出较高的 CPU 使用率。
pytesseract.image_to_string()
通过 Supervisord 运行所需的时间:~30s 通过 Bash 运行
所需的时间pytesseract.image_to_string()
:0.1s
仅当有大量进程pytesseract.image_to_string()
正在通过supervisord 执行(大约22 个实例)运行时,才会出现此问题。如果我减少实例数量(减少到 10 个左右),通过supervisord 执行的脚本也会顺利运行。
系统信息
操作系统:Ubuntu 18.04.2 LTS(仿生)
Supervisord:版本3.3.1
Tesseract:版本4.0.0-beta.1
Python:版本3.6
PyTesseract:版本0.2.5
ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 127357
max locked memory (kbytes, -l) 16384
max memory size (kbytes, -m) unlimited
open files (-n) 8096
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 127357
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
如果您需要更多信息,请告诉我。
编辑1(或者我知道这个问题的根源不是)
我相当确定这不是 Supervisord 的问题。
当我从 ssh shell 运行一个实例时,函数 ( pytesseract.image_to_string()
) 执行得很顺利(即只需要 0.1 秒),而有 10 个实例通过 Supervisord 运行。
当我从新的 ssh shell 启动另一个实例时,这两个实例(从 ssh 启动的实例)在大多数情况下都运行顺利。
当我从新的 ssh shell 启动另一个实例时,所有三个实例都开始阻塞,需要大约 10 秒才能执行该函数。随着我通过 shell 添加更多实例,这个时间不断增加。
所以即使使用 shell 也可以复制该问题。
更多信息
我运行了该程序,strace -T -f
但我无法弄清楚到底是什么导致了时间峰值。
对于需要 1s 的函数调用
Top 10 system calls sorted by time taken
1.504530 [pid 29921] <... wait4 resumed> [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 30166
0.503915 [pid 29932] <... select resumed> ) = 0 (Timeout)
0.503472 [pid 29932] <... select resumed> ) = 0 (Timeout)
0.500524 [pid 29933] <... select resumed> ) = 0 (Timeout)
0.500515 [pid 29933] <... select resumed> ) = 0 (Timeout)
0.500514 [pid 29932] <... select resumed> ) = 0 (Timeout)
0.500512 [pid 29933] <... select resumed> ) = 0 (Timeout)
0.069869 [pid 30169] <... futex resumed> ) = ? ERESTARTSYS (To be restarted if SA_RESTART is set)
0.035989 [pid 30167] <... futex resumed> ) = 0
0.016002 [pid 30168] <... futex resumed> ) = 0
对于需要 9 秒的函数调用
Top 10 system calls sorted by time taken
9.795787 [pid 29921] <... wait4 resumed> [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 30106
0.515960 [pid 29933] <... select resumed> ) = 0 (Timeout)
0.511955 [pid 29933] <... select resumed> ) = 0 (Timeout)
0.507979 [pid 29932] <... select resumed> ) = 0 (Timeout)
0.507968 [pid 29932] <... select resumed> ) = 0 (Timeout)
0.505257 [pid 29932] <... select resumed> ) = 0 (Timeout)
0.503988 [pid 29932] <... select resumed> ) = 0 (Timeout)
0.503978 [pid 29932] <... select resumed> ) = 0 (Timeout)
0.503975 [pid 29932] <... select resumed> ) = 0 (Timeout)
0.503974 [pid 29932] <... select resumed> ) = 0 (Timeout)
答案1
在 tesseract 中禁用多重处理解决了该问题。可以通过OMP_THREAD_LIMIT=1
环境设置来完成。
看https://github.com/tesseract-ocr/tesseract/issues/898#issuecomment-315202167
答案2
在Python进程中:
import os
os.environ['OMP_THREAD_LIMIT'] = '1'
它修复了线程开销。