контекст pyzmq иногда медленно инициализируется - PullRequest
2 голосов
/ 16 февраля 2020

Я недавно начал использовать ZeroMQ и заметил, что иногда инициализация контекста ZeroMQ может занимать до 40 секунд . Обычно это намного быстрее, чем это.

Например:

import zmq

# the next line will sometimes take 40 seconds
# or so but is usually near instantaneous
with zmq.Context.instance() as context:
    # connect / bind to socket, do stuff
    pass

Такое поведение не зависит от того, использую я менеджер контекста или нет, например, следующие действия ведут себя так же, как указано выше:

import zmq

# the next line will sometimes take 40 seconds
# or so but is usually near instantaneous
context = zmq.Context.instance()

# connect / bind to socket, do stuff

context.term()

Это работает в Python 3.6.8 в Ubuntu 18.04.2

Мне не удалось установить sh какой-либо шаблон для замедлений.

Каковы возможные причины такого поведения?

Обновление

По предложению @ user3666197, я взял несколько таймингов и сумел заставить замедление проявиться во втором запуске. После этого все вернулось к «нормальному».

При втором запуске тестового сценария началось замедление:

 = zmq.Context()] took +      704 [us] to execute
 1.~                          704  us
 2.~                  131 766 816  us
 3.~                          145  us
 4.~                          137  us

Просмотр памяти на htop в то время не показывал память Заполнение вообще, но своп уже был активен.

Обновление 2

Использование сокращенной версии предложенного сценария @ user3666197:

import sys

import zmq
clock = zmq.Stopwatch()

clock.start()
foo = zmq.Context()
bar = clock.stop()
print("{0:>2s}: {1:>9d}".format(sys.argv[1], bar))
foo.term()

И вызов его на всех oop, например:

for x in $(seq 1 20);
do python3 test.zmq.py $x;
done

Я могу повторить проблему на исходном сервере , но мне еще не удалось обнаружить ее на другом сервере , что предполагает проблема (или что-то связанное с указанием c версии для дистрибутива и / или python версии, так как «хороший» сервер устарел).

Пока этого достаточно, но я вернусь к это позже и собрать достаточно информации, чтобы представить что-то сопровождающим.

1 Ответ

2 голосов
/ 16 февраля 2020

В случае, если кто-то никогда не работал с ZeroMQ,
здесь можно с первого взгляда "Принципы ZeroMQ * менее чем за Пять секунд "
, прежде чем углубляться в детали


Q : "Что такое возможно причины этого (присутствует только " иногда ") поведение? "
Я не смог установить sh любой паттерн замедления.

a ) эти 40 секунд,
, упомянутые выше, могут иметь смысл, но с Оперативная память для обмена операций ввода-вывода. Я не могу представить никакой другой причины для такого интервала времени (я никогда не замечал ничего близкого к 3/4 минутной задержки в ZeroMQ в течение моих последних ~ 10 лет с ZeroMQ, никогда)

b ) проверка реальности
всегда измеряет соответствующие фактические сроки исполнения до того, как будет выдвинуто любое требование:
давайте начнем быть систематизированными c и справедливыми в отношении повторяемых и документированных испытаний. случаи, хорошо?
Категории типа " иногда " не стоят, данные есть. Для начала мы можем использовать следующий шаблонный подход, чтобы определить причину root любой фактической задержки:

M = "[{0:_>40s}] took +{1:_>9d} [us] to execute"
N = 0
from zmq import Stopwatch; aClk = Stopwatch()
#------------------------------
pass;                      aClk.start()
import zmq
pass;                  _ = aClk.stop(); print( M.format( "IMPORT", _ ) )
#------------------------------
pass;                      aClk.start()
aCTX = zmq.Context()
pass;                  _ = aClk.stop(); print( M.format( "= zmq.Context()", _ ) )
#------------------------------
pass;                      aClk.start()
aCTX.term()
pass;                  _ = aClk.stop(); print( M.format( ".term()", _ ) )
#------------------------------
pass;                      aClk.start()
context = zmq.Context.instance()
pass;                  _ = aClk.stop(); print( M.format( "= zmq.Context.instance()", _ ) )
#------------------------------
pass;                      aClk.start()
context.term()
pass;                  _ = aClk.stop(); print( M.format( ".term()", _ ) )
#------------------------------
pass;                      aClk.start()
with zmq.Context.instance() as aCtxInCtxMGR:
     N +=1
pass;                  _ = aClk.stop(); print( M.format( "with … as aCtxInCtxMGR:", _ ) )
#------------------------------
pass;                      aClk.start()
aCTX = zmq.Context(  0 )
pass;                  _ = aClk.stop(); print( M.format( "= zmq.Context(  0 )", _ ) )
#------------------------------
pass;                      aClk.start()
aCTX.term()
pass;                  _ = aClk.stop(); print( M.format( ".term()", _ ) )
#------------------------------
pass;                      aClk.start()
aCTX = zmq.Context( 10 )
pass;                  _ = aClk.stop(); print( M.format( "= zmq.Context( 10 )", _ ) )
#------------------------------
pass;                      aClk.start()
aCTX.term()
pass;                  _ = aClk.stop(); print( M.format( ".term()", _ ) )
#------------------------------
pass;                      aClk.start()
aCTX = zmq.Context( 20 )
pass;                  _ = aClk.stop(); print( M.format( "= zmq.Context( 20 )", _ ) )
#------------------------------
pass;                      aClk.start()
aCTX.term()
pass;                  _ = aClk.stop(); print( M.format( ".term()", _ ) )
#------------------------------
pass;                      aClk.start()
aCTX = zmq.Context( 50 )
pass;                  _ = aClk.stop(); print( M.format( "= zmq.Context( 50 )", _ ) )
#------------------------------
pass;                      aClk.start()
aCTX.term()
pass;                  _ = aClk.stop(); print( M.format( ".term()", _ ) )
#------------------------------
pass;                      aClk.start()
aCTX = zmq.Context( 99 )
pass;                  _ = aClk.stop(); print( M.format( "= zmq.Context( 99 )", _ ) )
#------------------------------
pass;                      aClk.start()
aCTX.term()
pass;                  _ = aClk.stop(); print( M.format( ".term()", _ ) )
#------------------------------

и так далее
и правдоподобно


Ваш фактический пробег может варьироваться
(и будет)

[__________________________________IMPORT] took +_____1198 [us] to execute
[_________________________= zmq.Context()] took +_____1523 [us] to execute
[________________= zmq.Context.instance()] took +_____1348 [us] to execute
[_________________with … as aCtxInCtxMGR:] took +_____7909 [us] to execute
[_____________________= zmq.Context(  0 )] took +______966 [us] to execute
[_____________________= zmq.Context( 10 )] took +______944 [us] to execute
[_____________________= zmq.Context( 20 )] took +______936 [us] to execute
[_____________________= zmq.Context( 50 )] took +______962 [us] to execute
[_____________________= zmq.Context( 99 )] took +_____1015 [us] to execute

[__________________________________IMPORT] took +______879 [us] to execute
[_________________________= zmq.Context()] took +_____1076 [us] to execute
[_________________________________.term()] took +______881 [us] to execute
[________________= zmq.Context.instance()] took +_____1105 [us] to execute
[_________________________________.term()] took +______896 [us] to execute
[_________________with … as aCtxInCtxMGR:] took +_____1474 [us] to execute
[_____________________= zmq.Context(  0 )] took +_____1163 [us] to execute
[_________________________________.term()] took +______982 [us] to execute
[_____________________= zmq.Context( 10 )] took +_____2646 [us] to execute
[_________________________________.term()] took +______873 [us] to execute
[_____________________= zmq.Context( 20 )] took +_____2689 [us] to execute
[_________________________________.term()] took +______981 [us] to execute
[_____________________= zmq.Context( 50 )] took +_____2772 [us] to execute
[_________________________________.term()] took +______910 [us] to execute
[_____________________= zmq.Context( 99 )] took +_____1086 [us] to execute
[_________________________________.term()] took +_____1010 [us] to execute
...