iis服务器助手广告广告
返回顶部
首页 > 资讯 > 前端开发 > JavaScript >比JSON.stringify快两倍的fast-json-stringify性能对比分析
  • 905
分享到

比JSON.stringify快两倍的fast-json-stringify性能对比分析

JSON.stringify对比fast-json-stringifyfast json stringify 2022-12-08 20:12:05 905人浏览 安东尼
摘要

目录前言JSON.stringify的性能瓶颈jsON.stringify 与遍历对比定制化更快的JSON.stringify更快的fast-json-stringify语法sche

前言

相信大家对JSON.stringify并不陌生,通常在很多场景下都会用到这个api,最常见的就是Http请求中的数据传输, 因为HTTP 协议是一个文本协议,传输的格式都是字符串,但我们在代码中常常操作的是 JSON 格式的数据,所以我们需要在返回响应数据前将 JSON 数据序列化为字符串。但大家是否考虑过使用JSON.stringify可能会带来性能风险?,或者说有没有一种更快的stringify方法。

JSON.stringify的性能瓶颈

由于 javascript 是动态语言,它的变量类型只有在运行时才能确定,所以 JSON.stringify 在执行过程中要进行大量的类型判断,对不同类型的键值做不同的处理。由于不能做静态分析,执行过程中的类型判断这一步就不可避免,而且还需要一层一层的递归,循环引用的话还有爆栈的风险。

我们知道,JSON.string的底层有两个非常重要的步骤:

  • 类型判断
  • 递归遍历

既然是这样,我们可以先来对比一下JSON.stringify与普通遍历的性能,看看类型判断这一步到底是不是影响JSON.stringify性能的主要原因。

JSON.stringify 与遍历对比

const obj1 = {}, obj2 = {}
for(let i = 0; i < 1000000; i++) {
    obj1[i] = i
    obj2[i] = i
}
function fn1 () {
    console.time('jsonStringify')
    const res = JSON.stringify(obj1) === JSON.stringify(obj2)
    console.timeEnd('jsonStringify')
}
function fn2 () {
    console.time("for");
    const res = Object.keys(obj1).every((key) => {
        if (obj2[key] || obj2[key] === 0) {
          return true;
        } else {
          return false;
        }
      });
    console.timeEnd("for");
}
fn1()
fn2()

从结果来看,两者的性能差距在4倍左右,那就证明JSON.string的类型判断这一步还是非常耗性能的。如果JSON.stringify能够跳过类型判断这一步是否对类型判断有帮助呢?

定制化更快的JSON.stringify

基于上面的猜想,我们可以来尝试实现一下:

现在我们有下面这个对象

const obj = {
  name: '南玖',
  hobby: 'fe',
  age: 18,
  chinese: true
}

上面这个对象经过JSON.stringify处理后是这样的:

JSON.stringify(obj)
// {"name":"南玖","hobby":"fe","age":18,"chinese":true}

现在假如我们已经提前知道了这个对象的结构

  • 键名不变
  • 键值类型不变

这样的话我们就可以定制一个更快的JSON.stringify方法

function myStringify(obj) {
    return `{"name":"${obj.name}","hobby":"${obj.hobby}","age":${obj.age},"chinese":${obj.chinese}}`
}
console.log(myStringify(obj) === JSON.stringify(obj))  // true

这样也能够得到JSON.stringify一样的效果,前提是你已经知道了这个对象的结构。

事实上,这是许多JSON.stringify加速库的通用手段:

  • 需要先确定对象的结构信息
  • 再根据结构信息,为该种结构的对象创建“定制化”的stringify方法
  • 内部实现依然是这种字符串拼接

更快的fast-json-stringify

fast-json-stringify 需要JSON Schema Draft 7输入来生成快速stringify函数。

这也就是说fast-json-stringify这个库是用来给我们生成一个定制化的stringily函数,从而来提升stringify的性能。

这个库的GitHub简介上写着比 JSON.stringify() 快 2 倍,其实它的优化思路跟我们上面那种方法是一致的,也是一种定制化stringify方法。

语法

const fastJson = require('fast-json-stringify')
const stringify = fastJson(mySchema, {
  schema: { ... },
  ajv: { ... },
  rounding: 'ceil'
})

schema: $ref 属性引用的外部模式。

ajv: ajv v8 实例对那些需要ajv.

rounding: 设置当integer类型不是整数时如何舍入。

largeArrayMechanism:设置应该用于处理大型(默认情况下20000或更多项目数组的机制

scheme

这其实就是我们上面所说的定制化对象结构,比如还是这个对象:

const obj = {
  name: '南玖',
  hobby: 'fe',
  age: 18,
  chinese: true
}

它的JSON scheme是这样的:

{
  type: "object",
  properties: {
    name: {type: "string"},
    hobby: {type: "string"},
    age: {type: "integer"},
    chinese: {type: 'boolean'}
  },
  required: ["name", "hobby", "age", "chinese"]
}

AnyOf 和 OneOf

当然除了这种简单的类型定义,JSON Schema 还支持一些条件运算,比如字段类型可能是字符串或者数字,可以用 oneOf 关键字:

"oneOf": [
  {
    "type": "string"
  },
  {
    "type": "number"
  }
]

fast-json-stringify支持JSON 模式定义的anyOf和**oneOf关键字。**两者都必须是一组有效的 JSON 模式。不同的模式将按照指定的顺序进行测试stringify在找到匹配项之前必须尝试的模式越多,速度就越慢。

anyOf和oneOf使用ajv作为 JSON 模式验证器来查找与数据匹配的模式。这对性能有影响——只有在万不得已时才使用它。

关于 JSON Schema 的完整定义,可以参考 Ajv 的文档,Ajv 是一个流行的 JSON Schema验证工具,性能表现也非常出众。

当我们可以提前确定一个对象的结构时,可以将其定义为一个 Schema,这就相当于提前告诉 stringify 函数,需序列化的对象的数据结构,这样它就可以不必再在运行时去做类型判断,这就是这个库提升性能的关键所在。

简单使用

const fastJson = require('fast-json-stringify')
const stringify = fastJson({
  title: 'myObj',
  type: 'object',
  properties: {
    name: {
      type: 'string'
    },
    hobby: {
      type: 'string'
    },
    age: {
      description: 'Age in years',
      type: 'integer'
    },
    chinese: {
      type: 'boolean'
    }
  }
})
console.log(stringify({
  name: '南玖',
  hobby: 'fe',
  age: 18,
  chinese: true
}))
// 

生成 stringify 函数

fast-json-stringify是跟我们传入的scheme来定制化生成一个stringily函数,上面我们了解了怎么为我们对象定义一个scheme结构,接下来我们再来了解一下如何生成stringify

这里有一些工具方法还是值得了解一下的:

const asFunctions = `
function $asAny (i) {
    return JSON.stringify(i)
  }
function $asNull () {
    return 'null'
  }
function $asInteger (i) {
    if (isLong &amp;&amp; isLong(i)) {
      return i.toString()
    } else if (typeof i === 'bigint') {
      return i.toString()
    } else if (Number.isInteger(i)) {
      return $asNumber(i)
    } else {
      return $asNumber(parseInteger(i))
    }
  }
function $asNumber (i) {
    const num = Number(i)
    if (isNaN(num)) {
      return 'null'
    } else {
      return '' + num
    }
  }
function $asBoolean (bool) {
    return bool &amp;&amp; 'true' || 'false'
  }
  // 省略了一些其他类型......
`

从上面我们可以看到,如果你使用的是 any 类型,它内部依然还是用的 JSON.stringify。 所以我们在用TS进行开发时应避免使用 any 类型,因为如果是基于 TS interface 生成 JSON Schema 的话,使用 any 也会影响到 JSON 序列化的性能。

然后就会根据 scheme 定义的具体内容生成 stringify 函数的具体代码。而生成的方式也比较简单:通过遍历 scheme,根据不同数据类型调用上面不同的工具函数来进行字符串拼接。感兴趣的同学可以在gitHub上查看源码

总结

事实上fast-json-stringify只是通过静态的结构信息将优化与分析前置了,通过开发者定义的scheme内容可以提前知道对象的数据结构,然后会生成一个stringify函数供开发者调用,该函数内部其实就是做了字符串的拼接。

  • 开发者定义 Object 的 JSON scheme
  • stringify 库根据 scheme 生成对应的模版方法,模版方法里会对属性与值进行字符串拼接
  • 最后开发者调用生成的stringify 方法

以上就是比JSON.stringify快两倍的fast-json-stringify性能对比分析的详细内容,更多关于JSON.stringify对比fast-json-stringify的资料请关注编程网其它相关文章!

--结束END--

本文标题: 比JSON.stringify快两倍的fast-json-stringify性能对比分析

本文链接: https://www.lsjlt.com/news/174318.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 比JSON.stringify快两倍的fast-json-stringify性能对比分析
    目录前言JSON.stringify的性能瓶颈JSON.stringify 与遍历对比定制化更快的JSON.stringify更快的fast-json-stringify语法sche...
    99+
    2022-12-08
    JSON.stringify对比fast-json-stringify fast json stringify
  • php中implode explode serialize json msgpack性能对比的示例分析
    小编给大家分享一下php中implode explode serialize json msgpack性能对比的示例分析,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!php有什么用php是一个嵌套的缩写名称,是英文超级文本...
    99+
    2023-06-14
  • Oracle 与spark-local 模式的性能对比分析
    这篇文章将为大家详细讲解有关Oracle 与spark-local 模式的性能对比分析,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。Oracle中的查询如果...
    99+
    2024-04-02
  • c++的glog与spdlog的性能对比测试分析
    目录问题:测试内容:测试环境:glog测试代码如下:spdlog异步测试代码:普通io流写入测试代码:总结:问题: 之前看到有的博文说glog性能很好,效率很高,当时第一反应是&ld...
    99+
    2024-04-02
  • Java对比两个实体的差异分析
    目录对比两个实体的差异可以用与一下方法比较两个实体类及属性差异工具类(简版)思路对比两个实体的差异 对比2个实体的值是否一致 可以用与一下方法 package com.xx; i...
    99+
    2024-04-02
  • Python中字典和列表性能的对比分析
    本篇文章为大家展示了Python中字典和列表性能的对比分析,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。Python列表和字典前面我们了解了 “大O表示法” 以及对不同的算法的评估,下面来讨论下 P...
    99+
    2023-06-15
  • 性能分析:回流与重绘的消耗对比
    性能消耗:回流和重绘的对比分析,需要具体代码示例 前言:在Web开发中,性能优化一直是一个重要的话题。在网页渲染过程中,最常见的性能消耗就是回流(reflow)和重绘(repaint)。本文将对回流和重绘进行详细对比分析,并给出...
    99+
    2024-01-26
    性能 重绘 回流
  • Go和Python Web服务器性能对比分析
    本篇内容介绍了“Go和Python Web服务器性能对比分析”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!...
    99+
    2024-04-02
  • Java for循环和foreach循环的性能对比分析
    目录for循环和foreach循环的性能对比普通for循环语法foreach 循环语法for与foreach循环效率比较对于数组来说对于链表来说小结一下吧for循环和foreach循...
    99+
    2024-04-02
  • Golang 相比 Python 的并发性能分析
    golang 的管道机制比 python 的线程机制提供更好的并发性能。管道消除了锁和线程创建开销,从而实现更快的执行速度。 Golang 与 Python 的并发性能分析 引言 并发...
    99+
    2024-05-12
    python golang
  • PHP和NumPy:两种编程算法的对比分析?
    PHP和NumPy:两种编程算法的对比分析 在计算机科学领域,编程算法是解决问题的关键。在这个领域里,PHP和NumPy是两种非常常见的编程算法。虽然它们在不同的领域中使用,但它们都是非常强大和灵活的工具。在这篇文章中,我们将比较PHP和N...
    99+
    2023-10-25
    numpy 编程算法 numy
  • Oracle,Open JDK等四大JVM性能对比的示例分析
    这篇文章将为大家详细讲解有关Oracle,Open JDK等四大JVM性能对比的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。市面上可供选择的JVM发行版还是有不...
    99+
    2024-04-02
  • Golang中slice删除元素的性能实例对比分析
    本篇内容主要讲解“Golang中slice删除元素的性能实例对比分析”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Golang中slice删除元素的性能实例对比分析”吧!我的电脑配置:☁ &nb...
    99+
    2023-07-02
  • Windows下PHP和NumPy的性能对比:谁更快速?
    在当今大数据时代,越来越多的开发者开始尝试使用不同的编程语言和工具来处理数据。PHP和NumPy都是两个非常流行的工具,它们都可以用来进行数据分析和处理。但是,它们的性能如何?在Windows下,哪一个更快速?本文将对这个问题进行探讨。 ...
    99+
    2023-07-23
    windows 大数据 numy
  • MySQL快速对比数据技巧的示例分析
    小编给大家分享一下MySQL快速对比数据技巧的示例分析,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!在MySQL运维中,研发同事想对比下两个不同实例上的数据并找出差异,除主键外还需要对比每...
    99+
    2024-04-02
  • golang函数类型的性能比较分析
    在 go 语言中,函数类型对性能有显著影响。性能比较显示,普通函数最优(147.08 m ops),其次是匿名函数(158.01 m ops),最后是闭包(10.02 m ops)。这些...
    99+
    2024-04-28
    函数类型 性能比较 golang 作用域
  • 如何进行nGrinder原理分析及性能工具对比
    这篇文章的内容主要围绕如何进行nGrinder原理分析及性能工具对比进行讲述,文章内容清晰易懂,条理清晰,非常适合新手学习,值得大家去阅读。感兴趣的朋友可以跟随小编一起阅读吧。希望大家通过这篇文章有所收获!在介绍nGrinder之前,有必要...
    99+
    2023-06-05
  • PHP 数组键值翻转:不同方法的性能对比分析
    php数组键值翻转方法性能对比表明:array_flip() 函数在大型数组(超过 100 万个元素)下比 for 循环性能更优,耗时更短。手动翻转键值的 for 循环方法耗时相对较长。...
    99+
    2024-05-03
    性能 数组
  • oracle中使用索引与不使用索引的性能对比分析
    oracle中使用索引与不使用索引的性能对比分析,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。前言Oracle存储索引的数据结构是B*树。...
    99+
    2024-04-02
  • MessagePack和System.Text.Json序列化和反序列化性能及对比分析
    本博客将测试MessagePack 和System.Text.Json 序列化和反序列化性能项目文件: Program.cs代码: using BenchmarkDotNet.Ru...
    99+
    2023-01-28
    MessagePack 和System.Text.Json 序列化和反序列化 MessagePack 和System.Text.Json 序列化和反序列化
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作