Как получить буферы произвольного размера в 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, предоставляя буферы произвольной длины. Тем не менее, утверждение не окружено #ifdefs. Кто-нибудь знает, как использовать буферы произвольной длины при использовании 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), то вы можете вернуть, например, 0x7fffffffUint32Array, который потребляет 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;
    });
    
Другие вопросы по тегам