Skip to content

Break the json-accelerator advantage #786

@cesco69

Description

@cesco69

I have made a benchmark for compare fast-json-stringify vs json-accelerator

index.js

import { bench, run, barplot, summary, compact, do_not_optimize } from 'mitata';
import fastJson from 'fast-json-stringify';
import {createAccelerator } from "json-accelerator";

const schema = {
  title: 'Example Schema',
  type: 'object',
  properties: {
    firstName: {
      type: 'string'
    },
    lastName: {
      type: 'string'
    },
    age: {
      type: 'integer'
    }
  }
};

const fjs = fastJson(schema);
const accelerator = createAccelerator(schema);

const value = {
  firstName: 'Matteo',
  lastName: 'Collina',
  age: 32,
};

compact(() => {
  barplot(() => {
    summary(() => {
      bench('fast-json-stringify', () => do_not_optimize(fjs(value)));
      bench('json-accelerator', () => do_not_optimize(accelerator(value)));
      bench('JSON.stringify', () => do_not_optimize(JSON.stringify(value)));
    })
  })
})

run()

json-accelerator seem 1.39x faster than fast-json-stringify

> node --expose-gc --allow-natives-syntax index.js --iterations=50000

clk: ~3.82 GHz
cpu: Intel(R) Core(TM) i9-10940X CPU @ 3.30GHz
runtime: node 24.0.1 (x64-win32)

benchmark                   avg (min … max) p75 / p99    (min … top 1%)
------------------------------------------- -------------------------------
fast-json-stringify          177.89 ns/iter 200.00 ns 600.00 ns ▆▁█▁▁▁▁▁▁▁▁
json-accelerator             128.24 ns/iter 130.40 ns 277.17 ns ▄█▂▁▁▁▁▁▁▁▁
JSON.stringify               189.20 ns/iter 197.90 ns 224.56 ns █▂▂▃▄▄▂▁▁▁▁

                             ┌                                            ┐
         fast-json-stringify ┤■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 177.89 ns
            json-accelerator ┤ 128.24 ns
              JSON.stringify ┤■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 189.20 ns
                             └                                            ┘

summary
  json-accelerator
   1.39x faster than fast-json-stringify
   1.48x faster than JSON.stringify

The stringify function builded by json-accelerator is really simple, it uses JSON.stringify on individual properties with a little optimization only strings:

function anonymous(v) {
  return `{"firstName":"${/["\b\t\n\v\f\r\/]/.test(v.firstName)?JSON.stringify(v.firstName).slice(1,-1):v.firstName}","lastName":"${/["\b\t\n\v\f\r\/]/.test(v.lastName)?JSON.stringify(v.lastName).slice(1,-1):v.lastName}","age":${JSON.stringify(v.age)}}`
}

on the string just check for special chars, eg:

/["\b\t\n\v\f\r\/]/.test(v.firstName) ? JSON.stringify(v.firstName).slice(1,-1) : v.firstName 

the stringify function of fast-json-stringify is more complex

function anonymous0 (input) {
      const obj = (input && typeof input.toJSON === 'function')
    ? input.toJSON()
    : input

      if (obj === null) return JSON_STR_EMPTY_OBJECT

      let value
let json = JSON_STR_BEGIN_OBJECT
let addComma = false

      value = obj["firstName"]
      if (value !== undefined) {
        !addComma && (addComma = true) || (json += JSON_STR_COMMA)
        json += "\"firstName\":"

        if (typeof value !== 'string') {
          if (value === null) {
            json += JSON_STR_EMPTY_STRING
          } else if (value instanceof Date) {
            json += JSON_STR_QUOTE + value.toISOString() + JSON_STR_QUOTE
          } else if (value instanceof RegExp) {
            json += serializer.asString(value.source)
          } else {
            json += serializer.asString(value.toString())
          }
        } else {
          json += serializer.asString(value)
        }

      }

      value = obj["lastName"]
      if (value !== undefined) {
        !addComma && (addComma = true) || (json += JSON_STR_COMMA)
        json += "\"lastName\":"

        if (typeof value !== 'string') {
          if (value === null) {
            json += JSON_STR_EMPTY_STRING
          } else if (value instanceof Date) {
            json += JSON_STR_QUOTE + value.toISOString() + JSON_STR_QUOTE
          } else if (value instanceof RegExp) {
            json += serializer.asString(value.source)
          } else {
            json += serializer.asString(value.toString())
          }
        } else {
          json += serializer.asString(value)
        }

      }

      value = obj["age"]
      if (value !== undefined) {
        !addComma && (addComma = true) || (json += JSON_STR_COMMA)
        json += "\"age\":"
        json += serializer.asInteger(value)
      }

    return json + JSON_STR_END_OBJECT

    }

maybe fast-json-stringify could take a simpler approach like json-accelerator?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions