LAN 経由で機能するサーバー用に Python で記述されたクライアントがあります。アルゴリズムの一部はソケット読み取りを集中的に使用しており、C++ で記述されたほぼ同じものよりも約 3 ~ 6 倍遅く実行されています。Pythonソケットの読み取りを高速化するためのソリューションは何ですか?
簡単なバッファリングが実装されており、ソケットを操作するためのクラスは次のようになります。
import socket
import struct
class Sock():
def __init__(self):
self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.recv_buf = b''
self.send_buf = b''
def connect(self):
self.s.connect(('127.0.0.1', 6666))
def close(self):
self.s.close()
def recv(self, lngth):
while len(self.recv_buf) < lngth:
self.recv_buf += self.s.recv(lngth - len(self.recv_buf))
res = self.recv_buf[-lngth:]
self.recv_buf = self.recv_buf[:-lngth]
return res
def next_int(self):
return struct.unpack("i", self.recv(4))[0]
def next_float(self):
return struct.unpack("f", self.recv(4))[0]
def write_int(self, i):
self.send_buf += struct.pack('i', i)
def write_float(self, f):
self.send_buf += struct.pack('f', f)
def flush(self):
self.s.sendall(self.send_buf)
self.send_buf = b''
PS: プロファイリングは、大部分の時間がソケットの読み取りに費やされていることも示しています。
編集:データは既知のサイズのブロックで受信されるため、ブロック全体を一度に読み取ることができます。だから私はこれに私のコードを変更しました:
class Sock():
def __init__(self):
self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.send_buf = b''
def connect(self):
self.s.connect(('127.0.0.1', 6666))
def close(self):
self.s.close()
def recv_prepare(self, cnt):
self.recv_buf = bytearray()
while len(self.recv_buf) < cnt:
self.recv_buf.extend(self.s.recv(cnt - len(self.recv_buf)))
self.recv_buf_i = 0
def skip_read(self, cnt):
self.recv_buf_i += cnt
def next_int(self):
self.recv_buf_i += 4
return struct.unpack("i", self.recv_buf[self.recv_buf_i - 4:self.recv_buf_i])[0]
def next_float(self):
self.recv_buf_i += 4
return struct.unpack("f", self.recv_buf[self.recv_buf_i - 4:self.recv_buf_i])[0]
def write_int(self, i):
self.send_buf += struct.pack('i', i)
def write_float(self, f):
self.send_buf += struct.pack('f', f)
def flush(self):
self.s.sendall(self.send_buf)
self.send_buf = b''
recv
このコードでは、ソケットからの接続が最適に見えます。しかし、今next_int
でnext_float
は 2 番目のボトルネックになり、解凍するだけで呼び出しごとに約 1 ミリ秒 (3000 CPU サイクル) かかります。C++ のように高速化することはできますか?