Skip to content

JIT-startsWith and endsWith #711

@Uzlopak

Description

@Uzlopak

I wonder if a startsWith JIT makes any sense for this or any project?

true startsWith x 95,549,028 ops/sec ±0.93% (95 runs sampled)
true startsWith jit x 1,409,981,216 ops/sec ±0.23% (95 runs sampled)
true endsWith x 98,114,558 ops/sec ±0.36% (99 runs sampled)
true endsWith jit x 199,258,515 ops/sec ±0.30% (97 runs sampled)
false startsWith x 125,452,965 ops/sec ±0.57% (94 runs sampled)
false startsWith jit x 1,409,183,606 ops/sec ±0.44% (99 runs sampled)
false endsWith x 126,028,596 ops/sec ±0.55% (95 runs sampled)
false endsWith jit x 198,250,186 ops/sec ±0.55% (98 runs sampled)

'use strict'

const assert = require('assert')
const Benchmark = require('benchmark')

const test = 'Lorem Ipsum I dolor'
const startsWithJit = startsWithJitGen('Lorem')
const endsWithJit = endsWithJitGen('dolor')
const Lorem = 'Lorem'
const dolor = 'dolor'

const lorem = 'lorem'
const Dolor = 'Dolor'

assert.ok(startsWithJit('ol') === false)
assert.ok(startsWithJit('or') === false)
assert.ok(startsWithJit('Dolor') === false)
assert.ok(startsWithJit('dolor') === false)
assert.ok(startsWithJit('lorem') === false)
assert.ok(startsWithJit('Lorem') === true)

assert.ok(endsWithJit('ol') === false)
assert.ok(endsWithJit('or') === false)
assert.ok(endsWithJit('Dolor') === false)
assert.ok(endsWithJit('dolor') === true)

new Benchmark.Suite()
  .add('true startsWith', function () { test.startsWith(Lorem) })
  .add('true startsWith jit', function () { startsWithJit(test) })
  .add('true endsWith', function () { test.endsWith(dolor) })
  .add('true endsWith jit', function () { endsWithJit(test) })
  .add('false startsWith', function () { test.startsWith(lorem) })
  .add('false startsWith jit', function () { startsWithJit(test) })
  .add('false endsWith', function () { test.endsWith(Dolor) })
  .add('false endsWith jit', function () { endsWithJit(test) })
  .on('cycle', function (event) { console.log(String(event.target)) })
  .run()

function startsWithJitGen(sequence) {
  const chain = []

  chain.push('(typeof value === \'string\')')
  chain.push(`(value.length >= ${sequence.length})`)

  for (let i = 0, il = sequence.length; i < il; ++i) {
    chain.push(`(value[${i}] === '${sequence[i]}')`)
  }

  const fnBody = 'return ' + chain.join(' && ')
  return new Function('value', fnBody)
}

function endsWithJitGen(sequence) {
  const chain = []

  chain.push('(typeof value === \'string\')')
  chain.push(`(value.length >= ${sequence.length})`)

  for (let i = 0, il = sequence.length; i < il; ++i) {
    if (i === 0) {
      chain.push(`(value[len] === '${sequence[i]}')`)
      continue
    }
    chain.push(`(value[len + ${i}] === '${sequence[i]}')`)
  }

  const fnBody = `const len = value.length - ${sequence.length}; return ` + chain.join(' && ')
  return new Function('value', fnBody)
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    help wantedExtra attention is needed

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions