成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

比JSON.stringify快兩倍的fast-json-stringify

開發 前端
相信大家對JSON.stringify并不陌生,通常在很多場景下都會用到這個API,最常見的就是HTTP請求中的數據傳輸, 因為HTTP 協議是一個文本協議,傳輸的格式都是字符串,但我們在代碼中常常操作的是 JSON 格式的數據,所以我們需要在返回響應數據前將 JSON 數據序列化為字符串。

前言?

相信大家對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 && 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 && '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 方法
責任編輯:華軒 來源: 前端南玖
相關推薦

2021-05-06 05:30:33

JSONstringify()parse()

2019-06-11 15:25:03

JSON性能前端

2021-12-11 18:59:35

JavascriptJSON應用

2020-03-29 20:16:09

JavaScript前端技術

2020-05-25 14:37:31

JSON.string前端秘密特性

2021-12-22 09:08:39

JSON.stringJavaScript字符串

2024-09-30 11:08:18

JSON局限性數據

2022-08-31 22:50:13

JavaScript函數JSON

2024-03-25 00:10:00

JSON后端開發

2025-04-21 10:43:21

2023-01-17 16:25:18

前端開發JSON

2022-03-10 09:11:33

JavaScrip開發JSON

2024-05-08 08:32:25

架構

2009-06-03 09:16:54

FirefoxMozilla瀏覽器

2023-05-12 08:11:58

JavaScriptJSON克隆

2023-05-08 09:00:46

JSON深拷貝對象

2024-11-06 08:32:02

JavaScriptTypeScript數據結構

2024-01-05 07:46:15

JS克隆對象JSON

2022-10-27 08:31:31

架構

2022-04-29 10:17:51

數據庫Group-IB數據庫安全
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 久久久久黄 | 日韩视频在线免费观看 | 老司机精品福利视频 | 国产美女精品 | 欧美精品在线播放 | 成人网av| 欧美性网站 | 国产视频中文字幕 | 做a视频 | 欧美日韩中文字幕在线 | 黄色一级在线播放 | 亚洲一级视频在线 | 亚洲二区在线 | 欧美日韩电影一区二区 | 日韩在线免费播放 | 国产精品区一区二 | 国产色婷婷 | 欧美精三区欧美精三区 | 羞羞视频在线观免费观看 | 日韩免费视频一区二区 | 亚洲视频免费观看 | 天天插天天操 | 美女天天操| 亚洲午夜精品久久久久久app | 性高湖久久久久久久久aaaaa | 久久久精品| 国产一区二区三区在线 | 精品欧美一区二区三区免费观看 | 国产一区不卡在线观看 | 天天色综 | 久久爱黑人激情av摘花 | 久久久久久国产精品 | 成人一区二区视频 | 高清黄色 | 99在线精品视频 | 天天操天天操 | 激情五月综合 | 国产伦一区二区三区四区 | 区一区二在线观看 | 在线一区| 黄色在线网站 |