From a1e464cc5eb02802237ce90e7341f1940988718e Mon Sep 17 00:00:00 2001 From: Lovell Fuller Date: Sun, 15 Jan 2023 18:43:50 +0000 Subject: [PATCH] Switch to sequential read as default where possible --- docs/api-constructor.md | 2 +- docs/changelog.md | 2 ++ lib/constructor.js | 3 +-- lib/input.js | 2 +- src/pipeline.cc | 12 +++++++----- test/bench/perf.js | 4 ++-- 6 files changed, 14 insertions(+), 11 deletions(-) diff --git a/docs/api-constructor.md b/docs/api-constructor.md index 24ea9366..bf4858bb 100644 --- a/docs/api-constructor.md +++ b/docs/api-constructor.md @@ -25,7 +25,7 @@ Implements the [stream.Duplex](http://nodejs.org/api/stream.html#stream_class_st | [options.failOn] | string | "'warning'" | when to abort processing of invalid pixel data, one of (in order of sensitivity): 'none' (least), 'truncated', 'error' or 'warning' (most), highers level imply lower levels, invalid metadata will always abort. | | [options.limitInputPixels] | number \| boolean | 268402689 | Do not process input images where the number of pixels (width x height) exceeds this limit. Assumes image dimensions contained in the input metadata can be trusted. An integral Number of pixels, zero or false to remove limit, true to use default limit of 268402689 (0x3FFF x 0x3FFF). | | [options.unlimited] | boolean | false | Set this to `true` to remove safety features that help prevent memory exhaustion (JPEG, PNG, SVG, HEIF). | -| [options.sequentialRead] | boolean | false | Set this to `true` to use sequential rather than random access where possible. This can reduce memory usage and might improve performance on some systems. | +| [options.sequentialRead] | boolean | true | Set this to `false` to use random access rather than sequential read. Some operations will do this automatically. | | [options.density] | number | 72 | number representing the DPI for vector images in the range 1 to 100000. | | [options.pages] | number | 1 | number of pages to extract for multi-page input (GIF, WebP, AVIF, TIFF, PDF), use -1 for all pages. | | [options.page] | number | 0 | page number to start extracting from for multi-page input (GIF, WebP, AVIF, TIFF, PDF), zero based. | diff --git a/docs/changelog.md b/docs/changelog.md index 8fc71464..8fd6c306 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -6,6 +6,8 @@ Requires libvips v8.14.0 ### v0.32.0 - TBD +* Default to using sequential rather than random access read where possible. + * Replace GIF output `optimise` / `optimize` option with `reuse`. * Add `progressive` option to GIF output for interlacing. diff --git a/lib/constructor.js b/lib/constructor.js index f0a06e46..87a56f83 100644 --- a/lib/constructor.js +++ b/lib/constructor.js @@ -124,8 +124,7 @@ const debuglog = util.debuglog('sharp'); * (width x height) exceeds this limit. Assumes image dimensions contained in the input metadata can be trusted. * An integral Number of pixels, zero or false to remove limit, true to use default limit of 268402689 (0x3FFF x 0x3FFF). * @param {boolean} [options.unlimited=false] - Set this to `true` to remove safety features that help prevent memory exhaustion (JPEG, PNG, SVG, HEIF). - * @param {boolean} [options.sequentialRead=false] - Set this to `true` to use sequential rather than random access where possible. - * This can reduce memory usage and might improve performance on some systems. + * @param {boolean} [options.sequentialRead=true] - Set this to `false` to use random access rather than sequential read. Some operations will do this automatically. * @param {number} [options.density=72] - number representing the DPI for vector images in the range 1 to 100000. * @param {number} [options.pages=1] - number of pages to extract for multi-page input (GIF, WebP, AVIF, TIFF, PDF), use -1 for all pages. * @param {number} [options.page=0] - page number to start extracting from for multi-page input (GIF, WebP, AVIF, TIFF, PDF), zero based. diff --git a/lib/input.js b/lib/input.js index e6c7aece..ed8d9558 100644 --- a/lib/input.js +++ b/lib/input.js @@ -36,7 +36,7 @@ function _createInputDescriptor (input, inputOptions, containerOptions) { failOn: 'warning', limitInputPixels: Math.pow(0x3FFF, 2), unlimited: false, - sequentialRead: false + sequentialRead: true }; if (is.string(input)) { // filesystem diff --git a/src/pipeline.cc b/src/pipeline.cc index 2e1fca6f..93d93518 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -399,7 +399,7 @@ class PipelineWorker : public Napi::AsyncWorker { } // Join additional color channels to the image - if (baton->joinChannelIn.size() > 0) { + if (!baton->joinChannelIn.empty()) { VImage joinImage; sharp::ImageType joinImageType = sharp::ImageType::UNKNOWN; @@ -504,7 +504,7 @@ class PipelineWorker : public Napi::AsyncWorker { } // Affine transform - if (baton->affineMatrix.size() > 0) { + if (!baton->affineMatrix.empty()) { MultiPageUnsupported(nPages, "Affine"); std::vector background; std::tie(image, background) = sharp::ApplyAlpha(image, baton->affineBackground, shouldPremultiplyAlpha); @@ -1644,9 +1644,11 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) { baton->trimThreshold > 0.0 || baton->normalise || baton->position == 16 || baton->position == 17 || - baton->angle % 360 != 0 || - fmod(baton->rotationAngle, 360.0) != 0.0 || - baton->useExifOrientation + baton->angle != 0 || + baton->rotationAngle != 0.0 || + baton->tileAngle != 0 || + baton->useExifOrientation || + !baton->affineMatrix.empty() ) { baton->input->access = VIPS_ACCESS_RANDOM; } diff --git a/test/bench/perf.js b/test/bench/perf.js index 4492d541..90762618 100644 --- a/test/bench/perf.js +++ b/test/bench/perf.js @@ -535,10 +535,10 @@ async.series({ } }); } - }).add('sharp-sequentialRead', { + }).add('sharp-random-access-read', { defer: true, fn: function (deferred) { - sharp(inputJpgBuffer, { sequentialRead: true }) + sharp(inputJpgBuffer, { sequentialRead: false }) .resize(width, height) .toBuffer(function (err) { if (err) {