我一遍又一遍地重复下面这个成语。我读了一个大文件(有时,多达120万条记录!)并将输出存储到SQLite数据库中。将东西放入SQLite数据库似乎相当快。你知道吗
def readerFunction(recordSize, recordFormat, connection, outputDirectory, outputFile, numObjects):
insertString = "insert into NODE_DISP_INFO(node, analysis, timeStep, H1_translation, H2_translation, V_translation, H1_rotation, H2_rotation, V_rotation) values (?, ?, ?, ?, ?, ?, ?, ?, ?)"
analysisNumber = int(outputPath[-3:])
outputFileObject = open(os.path.join(outputDirectory, outputFile), "rb")
outputFileObject, numberOfRecordsInFileObject = determineNumberOfRecordsInFileObjectGivenRecordSize(recordSize, outputFileObject)
numberOfRecordsPerObject = (numberOfRecordsInFileObject//numberOfObjects)
loop1StartTime = time.time()
for i in range(numberOfRecordsPerObject ):
processedRecords = []
loop2StartTime = time.time()
for j in range(numberOfObjects):
fout = outputFileObject .read(recordSize)
processedRecords.append(tuple([j+1, analysisNumber, i] + [x for x in list(struct.unpack(recordFormat, fout))]))
loop2EndTime = time.time()
print "Time taken to finish loop2: {}".format(loop2EndTime-loop2StartTime)
dbInsertStartTime = time.time()
connection.executemany(insertString, processedRecords)
dbInsertEndTime = time.time()
loop1EndTime = time.time()
print "Time taken to finish loop1: {}".format(loop1EndTime-loop1StartTime)
outputFileObject.close()
print "Finished reading output file for analysis {}...".format(analysisNumber)
当我运行代码时,似乎“循环2”和“插入到数据库”是花费大量执行时间的地方。平均“循环2”时间为0.003s,但在某些分析中,它达到了50000次。将内容放入数据库所花的时间大致相同:0.004s。目前,我每次在loop2完成后都会插入数据库,这样就不必处理内存耗尽的问题。你知道吗
我能做些什么来加速“循环2”?你知道吗
这主要是一个I/O问题。你知道吗
您的大部分时间都是在读取文件中的少量增量位(即一次读取一条记录),然后使用
struct
解压这些单独的记录。这太慢了。相反,一次抓取你想要的文件的整个块,然后让struct.unpack
以C的速度翻滚。你知道吗您将需要做一点数学来计算
read
需要多少字节,并更改recordFormat
格式字符串来告诉struct
如何解包整个内容。你的例子中没有足够的信息让我更准确地告诉你应该怎么做。你知道吗我还要指出:
是不是写得更理智了
…但是如果您按照我上面的建议完全删除循环,则需要重构该行。(您可以使用
zip
和enumerate
在整个解包之后将数据预处理到每个结构成员上)编辑:示例。我把一百万个未签名的整数打包到一个文件中。
yours()
是你的方法,mine()
是我的方法。你知道吗时间安排:
所以,大约有两个数量级的差异。你知道吗
在循环2中我唯一看到的是错误地使用列表理解。你知道吗
不要在列表类型对象上使用
[x for x in list]
。因为你在这里做必要的迭代。它可以写成list
所以你应该这样写
我认为使用mmap模块来处理内存映射文件 也许能帮你节省两次时间。我发现它太小了或者 非常大的块不会节省很多,但是您可以尝试查看最佳大小。你知道吗
我对两个功能都计时:
编辑时间: 我认为,一个索引访问文件,而读取是允许使用线程并行读取多个记录。如果你有兴趣,我可以写一个例子。你知道吗
相关问题 更多 >
编程相关推荐