python的memoryview的理解

 python的memoryview提供了统一且安全的直接读或者写内存的途径。python里一切都是对象,而且简单的字符串操作都会引起内存拷贝和新对象的产生。memoryview正为减少内存拷贝,优化效率而来。

str和bytearray实现了memoryview协议,前者实现了只读,后者实现了读写。注意:在python3版本里,str不支持memoryview,而需要使用bytes。举个例子如下:

b = bytearray(b'abc')
m = memoryview(b)
b[0] = 'z'
print(m[0])  => z

从stackoverflow看来一个典型的效率用例:

import time
for n in (100000, 200000, 300000, 400000):
    data = 'x'*n
    start = time.time()
    b = data
    while b:
        b = b[1:]
    print 'bytes', n, time.time()-start

for n in (100000, 200000, 300000, 400000):
    data = 'x'*n
    start = time.time()
    b = memoryview(data)
    while b:
        b = b[1:]
    print 'memoryview', n, time.time()-start

运行结果如下: 

bytes 100000 0.240149021149
bytes 200000 1.04921603203
bytes 300000 2.66688489914
bytes 400000 4.83206987381
memoryview 100000 0.011647939682
memoryview 200000 0.0258820056915
memoryview 300000 0.0385529994965
memoryview 400000 0.0550448894501

发现两个小Tips:

1. memoryview对象如果不释放,那么即使绑定的对象释放了,内存也不会释放

b = bytearray(b'abc')
m = memoryview(b)
del b
print(m[0])

此时,可以del m,或者m.release() 来释放绑定的对象。

注意:memoryview的slice结果,还是memoryview,即:mm = m[:1],但b的引用计数并没有增加更多,而只有所有的memoryview被释放或者release之后,b 才会被释放,所以这里应该是有种类似共享指针(shared_ptr)的实现。

2.  通过del可以直接原地移动bytearray的内存

b = bytearray(b'abc')
b.append(b'z')
b.insert(0, b'z')
del b[:1]
del b[3:]

Java是最讨老板喜欢的开发语言,因为工作四、五年的老手和工作一、两年的新手写出来的代码是差不多的,工人的可替代性强,离职一个,立马再招一个就能顶上。我认为Python是最讨开发者喜欢的语言,从快速Demo调研到最终产品开发,从pure python实现到内嵌.so二进制模块,在追求效率和简洁的道路上,你总有新发现和新手段。

 

发表于 2018年01月17日 12:02   修改于 2021年02月19日 09:22   评论:0   阅读:5449  



回到顶部

首页 | 关于我 | 关于本站 | 站内留言 | rss
python logo   django logo   tornado logo