Как получить буферы произвольного размера в nodejs, используя Nan
У меня есть приложение js для узла, которое выполняет некоторую обработку изображения на больших файлах с использованием Sharp, которое, в свою очередь, использует nan для взаимодействия с узлом. Когда я загружаю очень большое изображение, я получаю ошибку от Nan, которая говорит
node: ../node_modules/nan/nan.h:679: Nan::MaybeLocal<v8::Object> Nan::NewBuffer(char*, size_t, node::Buffer::FreeCallback, void*): Assertion `length <= imp::kMaxLength && "too large buffer"' failed.
Aborted (core dumped)
Вы можете увидеть линию 679 нан.ч здесь
Но в итоге это говорит об этом:
// arbitrary buffer lengths requires
// NODE_MODULE_VERSION >= IOJS_3_0_MODULE_VERSION
assert(length <= imp::kMaxLength && "too large buffer");
я имею
$ node -v
v4.4.6
Который вверху файла, который вы видите, должен быть более поздней версии, чем IOJS_3_0_MODULE_VERSION
, предоставляя буферы произвольной длины. Тем не менее, утверждение не окружено #ifdef
s. Кто-нибудь знает, как использовать буферы произвольной длины при использовании nan?
1 ответ
Сопровождающие NAN хотят обеспечить единообразное поведение во всех версиях узла, что, по-видимому, означает соблюдение ограничений более ранних версий узла ( обсуждение). Я полагаю, поэтому нет #ifdef
вокруг него, что позволило бы большие буферы для новых версий.
Если вы выделите память для буфера без использования NAN, то вы можете перейти к текущему значению kMaxLength 0x7fffffff
(т.е. лишний гигабайт по сравнению с тем, что ограничивает его NAN).
size_t len = 0x7fffffff;
char* bigbuf = (char*)malloc(len);
node::Buffer::New(v8::Isolate::GetCurrent(), bigbuf, len);
Я не уверен, где в вашем конвейере вы попали - это когда вы читаете с диска? Некоторые из этих методов могут быть полезны:
- Обработка ваших данных в потоке.
- Делать ввод / вывод из C++.
Чтение данных из файла по частям.
kMaxLength
это максимальный индекс, а не максимальный объем памяти, который может быть использован. Итак, если вы можете прочитать ваш большой буфер в более широкий TypedArray из C++ или из обработчика данных потока (используяtypedarray.set
), то вы можете вернуть, например,0x7fffffff
Uint32Array, который потребляет 8 589 934 588 байт.// Not tested var fs = require("fs"); var path = "/path/to/file"; var size = fs.statSync(path).size; var dest = new Uint32Array(size / Uint32Array.BYTES_PER_ELEMENT); var destOffset = 0; var rs = fs.createReadStream(path); rs.on("data", function (chunk) { var hunk = new Uint32Array(chunk.buffer, chunk.byteOffset, b.byteLength); dest.set(hunk, destOffset); destOffset += hunk.length; });