最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

比JSON.stringify快兩倍的fast-json-stringify性能對比分析

 更新時間:2022年12月05日 14:40:42   作者:前端南玖  
這篇文章主要為大家介紹了比JSON.stringify快兩倍的fast-json-stringify性能對比分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

前言

相信大家對JSON.stringify并不陌生,通常在很多場景下都會用到這個API,最常見的就是HTTP請求中的數(shù)據(jù)傳輸, 因為HTTP 協(xié)議是一個文本協(xié)議,傳輸?shù)母袷蕉际亲址?,但我們在代碼中常常操作的是 JSON 格式的數(shù)據(jù),所以我們需要在返回響應(yīng)數(shù)據(jù)前將 JSON 數(shù)據(jù)序列化為字符串。但大家是否考慮過使用JSON.stringify可能會帶來性能風(fēng)險??,或者說有沒有一種更快的stringify方法。

JSON.stringify的性能瓶頸

由于 JavaScript 是動態(tài)語言,它的變量類型只有在運行時才能確定,所以 JSON.stringify 在執(zhí)行過程中要進行大量的類型判斷,對不同類型的鍵值做不同的處理。由于不能做靜態(tài)分析,執(zhí)行過程中的類型判斷這一步就不可避免,而且還需要一層一層的遞歸,循環(huán)引用的話還有爆棧的風(fēng)險。

我們知道,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()

從結(jié)果來看,兩者的性能差距在4倍左右,那就證明JSON.string的類型判斷這一步還是非常耗性能的。如果JSON.stringify能夠跳過類型判斷這一步是否對類型判斷有幫助呢?

定制化更快的JSON.stringify

基于上面的猜想,我們可以來嘗試實現(xiàn)一下:

現(xiàn)在我們有下面這個對象

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

上面這個對象經(jīng)過JSON.stringify處理后是這樣的:

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

現(xiàn)在假如我們已經(jīng)提前知道了這個對象的結(jié)構(gòu)

  • 鍵名不變
  • 鍵值類型不變

這樣的話我們就可以定制一個更快的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一樣的效果,前提是你已經(jīng)知道了這個對象的結(jié)構(gòu)。

事實上,這是許多JSON.stringify加速庫的通用手段:

  • 需要先確定對象的結(jié)構(gòu)信息
  • 再根據(jù)結(jié)構(gòu)信息,為該種結(jié)構(gòu)的對象創(chuàng)建“定制化”的stringify方法
  • 內(nèi)部實現(xiàn)依然是這種字符串拼接

更快的fast-json-stringify

fast-json-stringify 需要JSON Schema Draft 7輸入來生成快速stringify函數(shù)。

這也就是說fast-json-stringify這個庫是用來給我們生成一個定制化的stringily函數(shù),從而來提升stringify的性能。

這個庫的GitHub簡介上寫著比 JSON.stringify() 快 2 倍,其實它的優(yōu)化思路跟我們上面那種方法是一致的,也是一種定制化stringify方法。

語法

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

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

ajv: ajv v8 實例對那些需要ajv.

rounding: 設(shè)置當(dāng)integer類型不是整數(shù)時如何舍入。

largeArrayMechanism:設(shè)置應(yīng)該用于處理大型(默認(rèn)情況下20000或更多項目)數(shù)組的機制

scheme

這其實就是我們上面所說的定制化對象結(jié)構(gòu),比如還是這個對象:

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

當(dāng)然除了這種簡單的類型定義,JSON Schema 還支持一些條件運算,比如字段類型可能是字符串或者數(shù)字,可以用 oneOf 關(guān)鍵字:

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

fast-json-stringify支持JSON 模式定義的anyOf和**oneOf關(guān)鍵字。**兩者都必須是一組有效的 JSON 模式。不同的模式將按照指定的順序進行測試。stringify在找到匹配項之前必須嘗試的模式越多,速度就越慢。

anyOf和oneOf使用ajv作為 JSON 模式驗證器來查找與數(shù)據(jù)匹配的模式。這對性能有影響——只有在萬不得已時才使用它。

關(guān)于 JSON Schema 的完整定義,可以參考 Ajv 的文檔,Ajv 是一個流行的 JSON Schema驗證工具,性能表現(xiàn)也非常出眾。

當(dāng)我們可以提前確定一個對象的結(jié)構(gòu)時,可以將其定義為一個 Schema,這就相當(dāng)于提前告訴 stringify 函數(shù),需序列化的對象的數(shù)據(jù)結(jié)構(gòu),這樣它就可以不必再在運行時去做類型判斷,這就是這個庫提升性能的關(guān)鍵所在。

簡單使用

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 函數(shù)

fast-json-stringify是跟我們傳入的scheme來定制化生成一個stringily函數(shù),上面我們了解了怎么為我們對象定義一個scheme結(jié)構(gòu),接下來我們再來了解一下如何生成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 類型,它內(nèi)部依然還是用的 JSON.stringify。 所以我們在用TS進行開發(fā)時應(yīng)避免使用 any 類型,因為如果是基于 TS interface 生成 JSON Schema 的話,使用 any 也會影響到 JSON 序列化的性能。

然后就會根據(jù) scheme 定義的具體內(nèi)容生成 stringify 函數(shù)的具體代碼。而生成的方式也比較簡單:通過遍歷 scheme,根據(jù)不同數(shù)據(jù)類型調(diào)用上面不同的工具函數(shù)來進行字符串拼接。感興趣的同學(xué)可以在GitHub上查看源碼

總結(jié)

事實上fast-json-stringify只是通過靜態(tài)的結(jié)構(gòu)信息將優(yōu)化與分析前置了,通過開發(fā)者定義的scheme內(nèi)容可以提前知道對象的數(shù)據(jù)結(jié)構(gòu),然后會生成一個stringify函數(shù)供開發(fā)者調(diào)用,該函數(shù)內(nèi)部其實就是做了字符串的拼接。

  • 開發(fā)者定義 Object 的 JSON scheme
  • stringify 庫根據(jù) scheme 生成對應(yīng)的模版方法,模版方法里會對屬性與值進行字符串拼接
  • 最后開發(fā)者調(diào)用生成的stringify 方法

以上就是比JSON.stringify快兩倍的fast-json-stringify性能對比分析的詳細內(nèi)容,更多關(guān)于JSON.stringify對比fast-json-stringify的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • JS判斷微信掃碼的方法

    JS判斷微信掃碼的方法

    這篇文章通過代碼給大家介紹了JS判斷是否是微信掃碼的方法,非常不錯,需要的朋友參考下吧
    2017-08-08
  • JavaScript Class的正確使用方法詳解

    JavaScript Class的正確使用方法詳解

    在JavaScript中,類是通過class關(guān)鍵字來定義的,它的本質(zhì)是一種語法糖,仍然是基于原型鏈的,class 內(nèi)部的屬性和方法最終都會添加到構(gòu)造函數(shù)的 prototype 屬性上,本文給大家介紹了JavaScript Class的正確打開方式,需要的朋友可以參考下
    2025-03-03
  • 基于cornerstone.js的dicom醫(yī)學(xué)影像查看瀏覽功能

    基于cornerstone.js的dicom醫(yī)學(xué)影像查看瀏覽功能

    這篇文章主要介紹了基于cornerstone.js的dicom醫(yī)學(xué)影像查看瀏覽功能,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-07-07
  • JavaScript動畫函數(shù)封裝詳解

    JavaScript動畫函數(shù)封裝詳解

    動畫的原理是通過定時器setInterval() 不斷移動盒子位置。但是如果同時有好幾個元素都需要添加動畫呢?我們就可以考慮將其封裝成一個簡單的動畫函數(shù)。本文將為大家介紹如何進行封裝,需要的可以參考一下
    2021-12-12
  • JS中利用FileReader實現(xiàn)上傳圖片前本地預(yù)覽功能

    JS中利用FileReader實現(xiàn)上傳圖片前本地預(yù)覽功能

    FileReader 對象允許Web應(yīng)用程序異步讀取存儲在用戶計算機上的文件(或原始數(shù)據(jù)緩沖區(qū))的內(nèi)容,使用 File 或 Blob 對象指定要讀取的文件或數(shù)據(jù)。下面通過本文給大家介紹JS中利用FileReader實現(xiàn)上傳圖片前本地預(yù)覽功能,需要的朋友參考下
    2018-03-03
  • 收藏,對比功能的JS部分實現(xiàn)代碼

    收藏,對比功能的JS部分實現(xiàn)代碼

    非常不錯的,收藏效果代碼,增加當(dāng)前頁的現(xiàn)實,實現(xiàn)對比
    2008-08-08
  • 防止xss和sql注入:JS特殊字符過濾正則

    防止xss和sql注入:JS特殊字符過濾正則

    防止xss和sql注入:JS特殊字符過濾正則,需要的朋友可以參考一下
    2013-04-04
  • JS實現(xiàn)五星好評案例

    JS實現(xiàn)五星好評案例

    這篇文章主要為大家詳細介紹了JS實現(xiàn)五星好評案例,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • 基于JavaScript如何制作遮罩層對話框

    基于JavaScript如何制作遮罩層對話框

    遮罩層聽起來貌似很復(fù)雜,其實說白了就是一個全界面的半透明的div,用戶不可以點擊下邊的元素,或者說是點擊沒有反應(yīng),接下來通過本文給大家介紹JavaScript如何制作遮罩層對話框,對js遮罩層相關(guān)知識感興趣的朋友一起學(xué)習(xí)吧
    2016-01-01
  • 微信小程序?qū)崿F(xiàn)鼠標(biāo)拖動效果示例

    微信小程序?qū)崿F(xiàn)鼠標(biāo)拖動效果示例

    這篇文章主要介紹了微信小程序?qū)崿F(xiàn)鼠標(biāo)拖動效果,涉及微信小程序事件綁定及元素屬性動態(tài)操作相關(guān)實現(xiàn)技巧,需要的朋友可以參考下
    2017-12-12

最新評論

扎兰屯市| 湖南省| 淄博市| 荆门市| 乌拉特后旗| 靖江市| 河北区| 安龙县| 樟树市| 六枝特区| 安乡县| 翁牛特旗| 开平市| 育儿| 广昌县| 波密县| 泗洪县| 宁明县| 墨玉县| 白城市| 莆田市| 革吉县| 通州区| 钟祥市| 广州市| 呈贡县| 林芝县| 伽师县| 曲阳县| 岢岚县| 邯郸县| 英超| 疏附县| 阜平县| 南皮县| 涞源县| 额敏县| 遂宁市| 治县。| 温州市| 襄汾县|