『Python』内存分析_list和array的内存增长模式

『Python』内存分析_List对象内存占用分析

在Python中,列表是一个动态的指针数组,而array模块所提供的array对象则是保存相同类型的数值的动态数组。由于array直接保存值,因此它所使用的内存比列表少。列表和array都是动态数组,因此往其中添加新元素,而没有空间保存新的元素时,它们会自动重新分配内存块,并将原来的内存中的值复制到新的内存块中。为了减少重新分配内存的次数,通常每次重新分配时,大小都为原来的k倍。k值越大,则重新分配内存的次数越少,但浪费的空间越多。本节通过一系列的实验观察列表和array的内存分配模式。

一、通过getsizeof()计算列表的增长模式

step1

sys.getsizeof()可以获得列表所占用的内存大小。请编写程序计算一个长度为10000的列表,它的每个下标都保存列表增长到此下标时的大小:

import sys
# 【你的程序】计算size列表,它的每个小标都保存增长到此下标时size列表的大小
size = []
for i in range(10000):
    size.append(sys.getsizeof(size))

import pylab as pl
pl.plot(size, lw=2, c=‘b‘)
pl.show()

图中每个阶梯跳变的位置都表示一次内存分配,而每个阶梯的长度表示内存分配多出来的大小。

step2

请编写程序计算表示每次分配内存时列表的内存大小的resize_pos数组:

import numpy as np
#【你的程序】计算resize_pos,它的每个元素是size中每次分配内存的位置
# 可以使用NumPy的diff()、where()、nonzero()快速完成此计算。
size = []
for i in range(10000):
    size.append(sys.getsizeof(size))
size = np.array(size)
new_size = np.diff(size)

resize_pos = size[np.where(new_size)]
# resize_pos = size[np.nonzero(new_size)]

pl.plot(resize_pos, lw=2)
pl.show()
print ("list increase rate:")
tmp = resize_pos[25:].astype(np.float)  # ?
print (np.average(tmp[1:]/tmp[:-1]))  # ?

由图可知曲线呈指数增长,第45次分配内存时,列表的大小已经接近10000。

?为了计算增长率,只需要计算resize_pos数组前后两个值的商的平均值即可。

?为了提高精度,我们只计算后半部分的平均值,注意需要用astype()方法将整数数组转换为浮点数数组。程序的输出如下:

list increase rate:

    1.12754776209

【注】np.where索引定位的两种用法,np.nonzero非零值bool判断的用法,np.diff差分函数的用法。

step3

我们可以用scipy.optimize.curve_fit()对resize_pos数组进行拟合,拟合函数为指数函数:

请编写程序用上面的公式对resize_pos数组进行拟合:

from scipy.optimize import curve_fit
#【你的程序】用指数函数对resize_pos数组进行拟合
def func(x, a, b, c, d):
    return a * np.exp(b * x + c) + d
xdata = range(len(resize_pos))
ydata = resize_pos
popt, pcov = curve_fit(func, xdata, ydata) 

y = [func(i, *popt) for i in xdata]
pl.plot(xdata, y, lw=1, c=‘r‘)
pl.plot(xdata, ydata, lw=1, c=‘b‘)
pl.show()
print ("list increase rate by curve_fit:")
print (10**popt[1])

list increase rate by curve_fit:
    1.31158606108

【注意】本程序中对于scipy中的指数拟合做了示范。

二、通过运算时间估算array内存分配情况

遗憾的是,无论array对象的长度是多少,sys.getsizeof()的结果都不变。因此无法用上节的方法计算array对象的增长因子。

由于内存分配时会耗费比较长的时间,因此可以通过测量每次增加元素的时间,找到内存分配时的长度。请编写测量增加元素的时间的程序:

from array import array
import time
#【你的程序】计算往array中添加元素的时间times
times = []
times_step = []
arrays = [array(‘l‘) for i in range(1000)]
start = time.time()
for i in range(1000):
    start_step = time.time()
    [a.append(i) for a in arrays]
    end = time.time()
    times_step.append(end-start_step)
    times.append(end-start)

pl.figure()
pl.plot(times)
pl.figure()
pl.plot(times_step)
pl.show()

输出两幅图,前面的表示元素个数对应的程序总耗时,后面的表示每一次添加元素这一过程的耗时,注意,这张图只有在array数量较大时才是这个形状,数组数量不够时折线图差异很大。

进一步的,我们分析一下耗时显著大于附近点(极大值)的时刻的序列对应此时元素数量的折线图。

ts = np.array(times_step)
le = range(np.sum(ts>0.00025))
si = np.squeeze(np.where(ts>0.00025))
pl.plot(le,si,lw=2)
pl.show()

原文地址:https://www.cnblogs.com/hellcat/p/8795841.html

时间: 2024-10-27 06:02:39

『Python』内存分析_list和array的内存增长模式的相关文章

『Python』内存分析_List对象内存占用分析

『Python』内存分析_下_list和array的内存增长模式 list声明后结构大体分为3部分,变量名称--list对象(结构性数据+指针数组)--list内容,其中id表示的是list对象的位置, v引用变量名称,v[:]引用list对象,此规则对python其他序列结构也成立,以下示范可用id佐证, a=b时,a和b指向同一个list对象 a=b[:]时,a的list对象和b的list对象指向同一个list内容 Q1:元素存储地址是否连续 首先见得的测试一下list对象存储的内容(结构3

『Python』常用函数实践笔记

库安装: 1).pip & conda 2).在win10下手动安装python库的方法: 『python』计算机视觉_OpenCV3库安装 原生: list.append():添加元素到list末尾 list.extend():使用一个list扩展另一个list 字典列表化:字典是有顺序的,而且list字典等于list字典的key dict = {'c':1,'b':2,'a':3} list(dict) # Out[13]: # ['c', 'b', 'a'] list(dict.keys(

『Python』Numpy学习指南第九章_使用Matplotlib绘图

坐标轴调节以及刻度调节参见:『Python』PIL&plt图像处理_矩阵转化&保存图清晰度调整 数据生成: 1 import numpy as np 2 import matplotlib.pyplot as plt 3 4 func = np.poly1d(np.array([1,2,3,4])) 5 func1 = func.deriv(m=1) # 求一阶导数 6 func2 = func.deriv(m=2) # 求二阶导数 7 8 x = np.linspace(-10,10,3

『Python』高阶特性

python高级特性 1.集合的推导式 列表推导式,使用一句表达式构造一个新列表,可包含过滤.转换等操作. 语法:[exp for item in collection if codition] 字典推导式,使用一句表达式构造一个新列表,可包含过滤.转换等操作. 语法:{key_exp:value_exp for item in collection if codition} 集合推导式 语法:{exp for item in collection if codition} 嵌套列表推导式 2.

『Python』MachineLearning机器学习入门_极小的机器学习应用

一个小知识: 有意思的是,scipy囊括了numpy的命名空间,也就是说所有np.func都可以通过sp.func等价调用. 简介: 本部分对一个互联网公司的流量进行拟合处理,学习最基本的机器学习应用. 导入包&路径设置: import os import scipy as sp import matplotlib.pyplot as plt data_dir = os.path.join( os.path.dirname(os.path.realpath(__file__)), "..

『Python』Numpy学习指南第三章__常用函数

感觉心情渐渐变好了,加油! np.eye(2)np.savetxt('eye.txt',i2)c,v = np.loadtxt('data.csv', delimiter=',', usecols=(6,7), unpack=True) 1 # __*__coding=utf-8__*__ 2 3 import numpy as np 4 5 # 单位矩阵生成 6 i2 = np.eye(2) 7 print(i2) 8 9 # 保存为txt 10 np.savetxt('eye.txt',i2

『Python』skimage图像处理_旋转图像

一段简短的实现图像旋转的代码,使用了skimage库,据说和PIL相比,skimage对numpy等科学计算库的支持更好,这里是为了完成师兄给的帮他修改程序的任务,如果以后有需求的话可能会对python图像处理库做个梳理或者根据自己的需求做个筛选后深入了解一下. 1 from skimage import io,transform 2 import matplotlib.pyplot as plt 3 4 5 '''图片旋转''' 6 7 img2 = io.imread('./bg-body-

『Python』 爬取 WooYun 论坛所有漏洞条目的相关信息

每个漏洞条目包含: 乌云ID,漏洞标题,漏洞所属厂商,白帽子,漏洞类型,厂商或平台给的Rank值 主要是做数据分析使用:可以分析某厂商的各类型漏洞的统计:或者对白帽子的能力进行分析..... 数据更新时间:2016/5/27漏洞条目:104796条 数据截图如下: 数据网盘链接: 链接:http://pan.baidu.com/s/1bpDNKOv 密码:6y57 爬虫脚本: # coding:utf-8 # author: anka9080 # version: 1.0 py3 import

『Python』PIL图像处理_矩阵转化

应师兄要求改图,因为使用了PIL包把图片对象转化为numpy的矩阵,截取以及处理很好玩且方便,特此记录: 1 import numpy as np 2 from PIL import Image 3 import matplotlib.pyplot as plt 4 5 img = Image.open('./7b6021ef9e6892dcf14dc5dd269afaada763fedc13b29-iHXENu_fw658.jpeg') 6 plt.imshow(img) 7 plt.show