我有100个CSV文件,每个大约50.000.000行,每个包含3个单元格。
每一行都需要触发一个事件来进行一些计算。使用npm read-line库(通过管道读取CSV),我可以获得每秒大约1,000.000个处理周期(1个节点线程)。
但是这个过程做了很多步骤,只是为了得到一些数字
- 打开csv文件流
- 将每个块字符串化
- 在块 中搜索新行n
- 将该行拆分为数组(3个单元格)
- parseFloat every cell
因此,为了更快地解析它们,我认为将csv文件转换为二进制文件会有所帮助。所以我创建了一个二进制Float64Array缓冲文件,因为单元格中的所有值都是浮点数。
let counter = 0 ;;
rows.forEach(function (row) {
row.forEach(function(cell) {
buffer.writeDoubleLE(cell, counter++ * Float64Array.BYTES_PER_ELEMENT);
})
});
writeStream.write(buffer)
writeStream.end()
那么它只需要执行以下步骤
- 打开bin文件流
将每个流缓冲区块(chunk = 3 cells)转换为ArrayBuffer到Array64Float
fs.createReadStream(fileName, {highWaterMark: 24}) //.pause() .on('data', chunk => { //this._stream.pause(); this._bufferOffset = 0; this.emit('tick', new Float64Array(chunk.buffer, chunk.byteOffset, chunk.byteLength / Float64Array.BYTES_PER_ELEMENT)); }) .on('close', () => { let nextFile = this._getNextBINFilePath(); if (!nextFile) { return this.emit('end'); } this._initTestStream(); })
到目前为止一切顺利。我可以读取二进制文件并在Float64Array中逐行解析其内容。
但由于某些原因,它似乎比读取csv(文本)文件慢,按行分割,用逗号分割,在单元格上执行parseFloat。
我没有看到二进制,缓冲区和类型数组的更大的画面吗?
谢谢
我认为每个(小)块的瓶颈是new Float64Array
。
你可以使用3个Float64参数代替,或者直接在块上工作。
或者在更大的块上使用Float64Array
,并使用相同的Float64Array
重复调用该函数。