mzh/blog

Python标准库小窥[2]: memoryview

要讲memoryview,就要讲它的主要应用场合—-缓冲区(buffer) 要讲buffer前就要讲讲Python的字符处理:Python中的字符是不能修改的 例如 当你需要收集从socket.recv上来的代码时,大部分的人都选择了拼接字符串

while not self.sock.closed:
     data = ''
     while len(data) < 1024:
         d = self.sock.recv(12)
         if not d: return;
         data += d

殊不知,由于Python字符串的特点,这实际上是将data复制一份,然后于d进行拼接,然后再赋值给data。 当字符大小有1M左右的时候,这种复制的效率会下降10%左右(其他大小没有测试过,但是应该是字符越大,复制的效率就越低,毕竟要重新分配内存区域并填满是很费事的) 而且网络传输有个特点,就是客户端想传多大都可以,所以就会出现只传输部分数据的情况,这时,socket.recv循环次数增多,导致字符缓冲区复制的操作次数增多。 所以,对于已知缓冲区大小下,可以先分配大小的缓冲区,然后依次写入相应数据即可(不需要复制了)。 改装上面的栗子,我们假定已知缓冲区应该有1KB

buf = bytearray(1024)
mv = memoryview(buf)
i = 0
while i < 1024:
    i = self.sock.recv_into(mv)
    if not i: return; # remote closed
    if i < 1024:
        mv = mv[i:1024]
        i += i

即可