记录一个比较有趣的问题:在小文件非常多的情况下,会对性能有什么影响?
首先看写操作:
在写文件时,操作系统需要向硬盘管理系统发送IO请求,那么多个小文件,就意味着操作系统要向硬盘管理系统发送多次IO请求。随着文件数目上升,多个IO请求耗费的时间逐渐累加,最终甚至可以大于本身写数据所耗费的时间。(当然那么多的小文件,还会要为它们建立索引,索引也会耗费时间)
嘴上说无益,我们来做个写文件实验。比对生成102400个1KB的小文件(最终大小会是100MB)与直接生成100MB的大文件所耗费的时间:
#coding:utf-8
import os
import time
#author:Tammy Pi
#email:victory_pj@163.com
#compare the generate time of 102400 1KB minifile and 100MB big file
filenums = 102400
mini_filepath = 'd:/test/mini'
big_filepath = 'd:/test/big'
def write_file(filepath,filesize):
f = open(filepath,'w')
for i in range(0,filesize):
f.write('a')
f.flush()
f.close()
def create_minfiles():
for i in range(0,filenums):
fullpath = os.path.join("%s/%s.txt"%(mini_filepath,i))
write_file(fullpath,1024)
def create_bigfiles():
fullpath = os.path.join("%s/%s.txt"%(big_filepath,'big'))
write_file(fullpath,1024*1024*100)
if __name__ == '__main__':
time11 = time.time()
create_minfiles()
time12 = time.time()
print 'mini file generate time:',time12-time11
time21 = time.time()
create_bigfiles()
time22 = time.time()
print 'big file generate time:',time22-time21
下图是结果:
大概写小文件的时间会是大文件时间的8倍左右(10万文件级别的情况下)。
然后再看读操作:
为了公平起见,我们只比较直接读取单个文件耗费的时间,不比较遍历神马的。首先在一个目录下放102400个1KB的小文件,而只选择其中的1个进行读取;然后在另外一个目录下放1个1KB的小文件,而对它进行读取。然后比对这两个读操作所耗费的时间:
#coding:utf-8
import os
import time
#author:Tammy Pi
#email:victory_pj@163.com
#compare the generate time of 102400 1KB minifile and 100MB big file
filenums = 102400
mini_filepath = 'd:/test/mini/0.txt'
onfile_filepath = 'd:/test/onefile/0.txt'
def read_file(filepath):
f = open(filepath,'r')
content = f.read()
f.close()
if __name__ == '__main__':
time11 = time.time()
read_file(mini_filepath)
time12 = time.time()
print 'minifile read time:',time12-time11
time21 = time.time()
read_file(onfile_filepath)
time22 = time.time()
print 'onefile read time:',time22-time21
可以看到,在102400个文件中读取确定路径的文件也比在1个目录的文件夹中读取确定路径的文件耗费的时间长。这是由于,文件存储是需要创建目录/索引来记录它们在硬盘上的存储位置,如果文件数目超过一定大小,那么可能不止1级索引。那么查找时,就需要比如先找1级索引,然后再根据1级索引找2级索引,最后找到文件在硬盘上的存储位置,时间就耗费在这上面了。(注意,程序运行第一次的结果才可用,第一次运行后文件就已经被缓存了,此时的时间就没什么意义了)。
从上可以看出,读单个文件的性能都会下降;那么批量小文件复制、删除可以说是噩梦一般的耗时经历。
另外,再记录一点知识,不同的文件系统,对于单目录文件最大个数与单文件最大大小也是有限制的:
FAT32文件系统,单目录理论最大文件个数为65534个,但是实践中大概只能支持到2W+左右;
NTFS文件系统,单目录理论的最大文件个数没有限制;
FAT32文件系统,单文件最大大小为4GB左右(小于);NTFS文件系统,单文件最大文件大小为16TB左右(小于)。