Python语言的最大优势可以说是在其易用性上,但是内存占用和优化相对C/C++等语言而言却显得比较劣势。平时在处理一些任务时我们可能需要主动考虑代码运行过程中的内存占用问题,特别是图像/视频等数据处理时,避免真正运行上线后内存占用过大导致崩溃。
这里用到一个标准库函数:sys.getsizeof(object[, default])
可以看到,这个函数对任何对象都是可用的。所有内建对象返回的结果都是正确的,但对于第三方扩展不一定正确。而且只计算直接分配给对象的内存消耗,不计算它所引用的对象的内存消耗。
举个栗子🌰🐿:
有一个720*1280大小的视频已经将所有帧抽取出来保存在video文件夹中,一共509帧。
(1)采用OpenCV读取第一帧,并计算其大小:
import cv2
import sys
im =cv2.imread('./video/frame_0001.png')
print(sys.getsizeof(im)+' Bytes')
print(sys.getsizeof(im)/1024/1024+' MB')
打印结果:
2764928 Bytes
2.6368408203125 MB
由于OpenCV读取出来以720*1280*3
的int8型numpy数组保存,可以计算:
720*1280*3 = 2764800 Bytes= 2.63671875 MB
通过对numpy元素进行计算出的大小与sys.getsizeof
方法计算相近,sys.getsizeof
方法多出的128Bytes是由于numpy还需存储一些额外信息。
(2)采用glob+OpenCV读取所有帧存进一个list,并计算其大小:
import cv2
import sys
import glob
img_list = glob.glob('./video/*.png')
cnt = 0#对每帧占用内存数逐帧相加
imgs = []#存放读取出的图片
for img in img_list:
x=cv2.imread(img)
cnt+=sys.getsizeof(x)/1024/1024
imgs.append(x)
print(sys.getsizeof(imgs)+' Bytes')#并非实际占用内存大小
print(sys.getsizeof(imgs)/1024/1024+' MB')
print('cnt: '+cnt+' MB')
real_memory = (sys.getsizeof(imgs)+ len(imgs) * sys.getsizeof(imgs[0]))/1024/1024 #实际占用内存大小
print("size of img list real memory: %s MB" % real_memory)
9032 Bytes
0.00861358642578125 MB
cnt: 2784.50390625 MB
size of img list real memory: 2784.512519836426 MB
可以看到,如果List中放的是复杂元素,直接使用sys.getsizeof
是无法得到真正内存占用的,需要根据实际单个元素大小递归计算。
特别注意:
代码中如果采用numpy存储图片需要注意内存占用,避免内存的大量消耗。