我正在对我的系统进行压力测试,以确定文件系统可以承受多少惩罚。一个测试涉及对单个小(因此可能是高度缓存)文件的重复读取以确定开销。
以下python 3.6.0脚本生成两个结果列表:
import random, string, time
stri = bytes(''.join(random.choice(string.ascii_lowercase) for i in range(100000)), 'latin-1')
inf = open('bench.txt', 'w+b')
inf.write(stri)
for t in range(0,700,5):
readl = b''
start = time.perf_counter()
for i in range(t*10):
inf.seek(0)
readl += inf.read(200)
print(t/10.0, time.perf_counter()-start)
print()
for t in range(0,700,5):
readl = b''
start = time.perf_counter()
for i in range(3000):
inf.seek(0)
readl += inf.read(t)
print(t/10.0, time.perf_counter()-start)
inf.close()
绘制时,我得到以下图表:
我发现这些结果非常奇怪。第二个测试(图中的蓝色,可变读取长度参数)开始线性增加,这是预期的,然后在一个点后它决定更快地爬升。更令人惊讶的是,第一次测试(粉红色,可变重复计数和固定读取长度)也显示了令人感兴趣的疯狂离开,因为读取功能的大小在那里保持固定。它也非常不规则,最好是头疼。运行测试时我的系统处于空闲状态。
在一定数量的重复之后,会出现如此严重的性能下降的合理原因是什么?
修改
readl
是一个字节数组的事实显然是一个主要的性能问题。将其切换为字符串可以极大地改善一切。然而,即使使用字符串,通过比较调用读取和搜索功能也是一个次要因素。以下是测试1的更多测试变体(可变重复)。省略了测试2,因为其结果完全由字节数组性能差异完全解释:
import random, string, time
strs = ''.join(random.choice(string.ascii_lowercase) for i in range(100000))
strb = bytes(strs, 'latin-1')
inf = open('bench.txt', 'w+b')
inf.write(strb)
#bytes and read
for t in range(0,700,5):
readl = b''
start = time.perf_counter()
for i in range(t*10):
inf.seek(0)
readl += inf.read(200)
print(t/10.0, '%f' % (time.perf_counter()-start))
print()
#bytes no read
for t in range(0,700,5):
readl = b''
start = time.perf_counter()
for i in range(t*10):
readl += strb[0:200]
print(t/10.0, '%f' % (time.perf_counter()-start))
print()
#string and read
for t in range(0,700,5):
readl = ''
start = time.perf_counter()
for i in range(t*10):
inf.seek(0)
readl += inf.read(200).decode('latin-1')
print(t/10.0, '%f' % (time.perf_counter()-start))
print()
#string no read
for t in range(0,700,5):
readl = ''
start = time.perf_counter()
for i in range(t*10):
readl += strs[0:200]
print(t/10.0, '%f' % (time.perf_counter()-start))
print()
inf.close()