juanjoDiaz/json2csv

Performance improvement - RegExp caching

oliverfoster opened this issue · 2 comments

json2csv v7.0.4, in node v16.20.2

function stringFormatter(opts = {}) {
const quote = typeof opts.quote === "string" ? opts.quote : '"';
const escapedQuote = typeof opts.escapedQuote === "string" ? opts.escapedQuote : `${quote}${quote}`;
if (!quote || quote === escapedQuote) {
return (value) => value;
}
return (value) => {
if (value.includes(quote)) {
value = value.replace(new RegExp(quote, "g"), escapedQuote);
}
return `${quote}${value}${quote}`;
};
}
export {
stringFormatter as default
};

Can be replaced with:

// packages/formatters/src/string.ts
function stringFormatter(opts = {}) {
  const quote = typeof opts.quote === "string" ? opts.quote : '"';
  const escapedQuote = typeof opts.escapedQuote === "string" ? opts.escapedQuote : `${quote}${quote}`;
  if (!quote || quote === escapedQuote) {
    return (value) => value;
  }
  const cachedRex = new RegExp(quote, "g");
  return (value) => {
    if (value.includes(quote)) {
      value = value.replace(cachedRex, escapedQuote);
    }
    return `${quote}${value}${quote}`;
  };
}
export {
  stringFormatter as default
};

The performance improvement can be seen using:

import Benchmark from 'benchmark'

const quote = "\""
const escapedQuote = "'"
const cached = new RegExp(quote, 'g')

const suite = new Benchmark.Suite
suite
  .add('uncached', function () {
    const rex = new RegExp(quote, 'g')
    const str = "tes\"ting".replace(rex, escapedQuote)
  })
  .add('cached', function () {
    const str = "tes\"ting".replace(cached, escapedQuote)
  })
  // add listeners
  .on('cycle', function(event) {
    console.log(String(event.target));
  })
  .on('complete', function() {
    console.log('Fastest is ' + this.filter('fastest').map('name'));
  })
  // run async
  .run({ 'async': true });

Performance:
image

Great suggestion!

Fixed in dcaadcf

🥳