2019年2月2日土曜日

ZeroMQでソケット通信

はじめに


Python3 + ZeroMQでソケット通信を試してみます。

PythonでZeroMQを使うためのpyzmqのドキュメントは、
https://pyzmq.readthedocs.io/en/latest/
https://learning-0mq-with-pyzmq.readthedocs.io/en/latest/index.html
が、ZeroMQそのものの説明は
http://zguide.zeromq.org/page:all
が参考になります。

次の4パターン

  • Pair (Exclusive pair)
  • Client/Server (Request-reply)
  • Publish/Subscribe (Pub-sub)
  • Push/Pull (Pipeline)
が使えるようです。今回は、Publish/Subscribeで試します。せっかくなので、送受信にかかる時間も測定してみます。

コード


Publisher側のコードです。socket.send_pyobj でpythonのオブジェクトをそのまま渡すだけです。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import zmq
import time
import numpy as np

context = zmq.Context.instance()
socket = context.socket(zmq.PUB)
socket.bind("ipc://aaa")

w = np.ones(160) # numpy array to be sent
while True:
    t = time.perf_counter()
    socket.send_pyobj([t, w])
    print(t)
    time.sleep(1)

次に、Subscriber側のコードです。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import zmq
import time

context = zmq.Context.instance()
socket = context.socket(zmq.SUB)
socket.connect("ipc://aaa")
socket.subscribe('') # Recieve all topics

while True:
    start, w = socket.recv_pyobj()
    end = time.perf_counter()
    print("{0} ms".format((end-start)*1000.0))
pythonオブジェクトの送信から受信までの時間をms単位で出力するようにしています。

実行結果


実行は、端末を2つ立ち上げて、上記のコードをpythonで実行するだけです。

実行してみると、Subscriber側では、
115.46662700129673 ms
0.5929949984420091 ms
0.9222489970852621 ms
0.7364909979514778 ms
0.5779260027338751 ms
0.5179920044611208 ms
0.5140290013514459 ms
0.5147350020706654 ms
0.5380119982874021 ms
0.5411919992184266 ms
0.5420840025180951 ms
0.5289019973133691 ms
0.8248919984907843 ms
0.9655120011302643 ms
0.7765349946566857 ms
0.6397230026777834 ms
0.7840489997761324 ms
1.0322410016669892 ms
0.7769410003675148 ms
0.774603002355434 ms
0.7632400011061691 ms
0.7989099976839498 ms
0.8185699989553541 ms
0.8329580014105886 ms
と出力されました。おおむね1ms以下で送信できているようです。ただ通信したいだけの用途なら十分な速さですね。

送信データ量を増やす


numpy arrayを作るところを1000倍してみたところ、
w = np.ones(160000)
さすがに3ms前後かかるようになりました。
118.689604998508 ms
6.79611799569102 ms
3.675059000670444 ms
3.75746200006688 ms
3.62611300079152 ms
3.6894719960400835 ms
2.672021997568663 ms
3.772675001528114 ms
3.641210001660511 ms
3.5925789998145774 ms
3.0622690028394572 ms

通信をtcpに変更


さらに、通信を次のようにtcpに変更してみました。
[Publisher]
socket.bind("tcp://*:5556")

[Subscriber]
socket.connect("tcp://localhost:5556")
すると、
117.72498200298287 ms
6.720707002386916 ms
4.039794999698643 ms
3.9917790054460056 ms
4.0376230026595294 ms
3.933735999453347 ms
3.9876959999674 ms
4.071578005095944 ms
4.004092996183317 ms
となりました。ipcよりtcpのほうが若干遅いようです。

0 件のコメント :