У меня есть огромный объект, который служит картой с 2,7 миллионами ключей. Я пытаюсь записать объект в файловую систему, чтобы сохранить его и не пересчитывать каждый раз, когда мне это нужно. На другом этапе мне нужно снова прочитать объект. Мне нужно иметь доступ ко всему объекту в памяти, так как он должен служить картой.
Для записи я конвертирую объект в массив и передаю его в файловую систему с помощью функции ниже. Причина, по которой я сначала преобразую его в массив, заключается в том, что потоковая передача массива вместо объекта выглядит значительно быстрее. Письменная часть занимает около минуты, и это нормально. Выходной файл имеет размер 4,8 ГБ.
Проблема, с которой я сталкиваюсь, заключается в попытке прочитать файл. Для этого я создаю поток чтения и анализирую содержимое. Тем не менее, по какой-то причине, я, кажется, достиг своего рода ограничения памяти. Я использовал различные подходы для чтения и анализа, и все они работают до тех пор, пока не будет прочитано около 50% данных (в настоящее время процесс узла на моей машине занимает 6 ГБ памяти, что немного ниже установленного мной предела). С этого момента время чтения значительно увеличивается в 10 раз, возможно, потому что узел близок к использованию максимального предела выделенной памяти (6144 МБ). Такое чувство, что я делаю что-то не так.
Главное, чего я не понимаю, - это то, почему запись не является проблемой, в то время как чтение происходит, хотя на этапе записи весь массив также хранится в памяти. Я использую узел v8.11.3
.
Итак, подведем итог:
- У меня есть большой объект, который мне нужно сохранить в файловой системе в виде массива с использованием потоков
- Запись работает нормально
- Чтение работает до тех пор, пока не будет прочитано около 50% данных, затем время чтения значительно увеличится
Как я могу читать файл более эффективно?
Я пробовал различные библиотеки, такие как stream-to-array , read-json-stream , JSONStream
пример объектадля записи:
{ 'id': ['some_other_id_1', 'some_other_id_2'] }
затем преобразуется в массив перед записью:
[{ 'id': ['some_other_id_1', 'some_other_id_2'] }]
функция для записи массива в файловую систему с использованием потоков:
import * as fs from 'fs'
import * as jsonStream from 'JSONStream'
import * as streamifyArray from 'stream-array'
async function writeFileAsStreamFromArray(pathToFile: string, fileContent: any[]): Promise<void> {
return new Promise((resolve, reject) => {
const fileWriterStream = fs.createWriteStream(pathToFile)
const stringifierStream = jsonStream.stringify()
const readStream = streamifyArray(fileContent)
readStream.pipe(stringifierStream)
stringifierStream.pipe(fileWriterStream)
fileWriterStream.on('finish', () => {
console.log('writeFileAsStreamFromArray: File written.')
stringifierStream.end()
resolve()
})
fileWriterStream.on('error', (err) => {
console.log('err', err)
reject(err)
})
})
}
*Функция 1035 * для получения массива из потока с помощью jsonStream:
async function getArrayFromStreamUsingJsonStream(pathToFile: string): Promise<any[]> {
return new Promise(async (resolve, reject) => {
const readStream = fs.createReadStream(pathToFile)
const parseStream = jsonStream.parse('*')
const array = []
const start = Date.now()
const transformer = transform((entry) => {
array.push(entry)
if ((array.length % 100000) === 0) {
const end = (Date.now() - start) / 1000
console.log('array', array.length, end)
}
})
readStream.pipe(parseStream)
parseStream.pipe(transformer)
readStream.on('end', () => {
console.log('getArrayFromStreamUsingJsonStream: array created')
parseStream.end()
resolve(array)
})
readStream.on('error', (error) => {
reject(error)
})
})
}
Временные журналы (после 1200000 записей я отменил выполнение, так как оно длилось вечно):
array 100000 6.345
array 200000 12.863
array 300000 21.177
array 400000 29.638
array 500000 35.884
array 600000 42.079
array 700000 48.74
array 800000 65.662
array 900000 89.805
array 1000000 120.416
array 1100000 148.892
array 1200000 181.921
...
Ожидаемый результат: Следуетбыть более производительным, чем сейчас. Это вообще возможно? Или я упускаю что-то очевидное?
Любая помощь очень ценится !!