microlinkhq / browserless

The headless Chrome/Chromium driver on top of Puppeteer.
https://browserless.js.org
MIT License
1.63k stars 81 forks source link

perf(screenshot): use sampling for `is-white` #570

Closed Kikobeats closed 7 months ago

Kikobeats commented 7 months ago

in this way, it cuts the duration from ~400ms → ~200ms

Also tested sharp implementation it but seems to be slower:

benchmark.js

'use strict'

const sharp = require('sharp')
const jimp = require('jimp')

const withSharp = async buffer => {
  const image = sharp(buffer)
    .flatten({ background: { r: 255, g: 255, b: 255 } })
    .toColorspace('srgb')
  const { data, info } = await image.raw().toBuffer({ resolveWithObject: true })
  const firstPixel = data.subarray(0, 3) // Only consider RGB channels

  for (let i = 0; i < info.height; i++) {
    for (let j = 0; j < info.width; j++) {
      const idx = (i * info.width + j) * 3 // Only consider RGB channels
      const pixel = data.subarray(idx, idx + 3) // Only consider RGB channels
      if (!pixel.equals(firstPixel)) {
        return false
      }
    }
  }

  return true
}

const withJimp = async buffer => {
  const image = await jimp.read(buffer)
  const firstPixel = image.getPixelColor(0, 0)
  const height = image.getHeight()
  const width = image.getWidth()

  for (let i = 0; i < height; i++) {
    for (let j = 0; j < width; j++) {
      if (firstPixel !== image.getPixelColor(j, i)) return false
    }
  }

  return true
}

const buffer = require('fs').readFileSync('./test/fixtures/white-5k.png')

/**
 * Run:
 * $ hyperfine -L useSharp false,true 'node bench.js {useSharp}'
 */
async function main () {
  const now = Date.now()
  const useSharp = process.argv[2] === 'true'
  const fn = useSharp ? withSharp : withJimp
  await fn(buffer)
  console.log(Date.now() - now)
}

main()

results

hyperfine -L useSharp false,true 'node bench.js {useSharp}'
Benchmark 1: node bench.js false
  Time (mean ± σ):     513.2 ms ±   5.3 ms    [User: 516.2 ms, System: 59.3 ms]
  Range (min … max):   506.8 ms … 524.8 ms    10 runs

Benchmark 2: node bench.js true
  Time (mean ± σ):     943.0 ms ±   2.4 ms    [User: 976.5 ms, System: 54.3 ms]
  Range (min … max):   938.8 ms … 947.7 ms    10 runs

Summary
  'node bench.js false' ran
    1.84 ± 0.02 times faster than 'node bench.js true'