In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-04-01 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article introduces the knowledge of "how to improve the performance of JSON.stringify ()". In the operation of actual cases, many people will encounter such a dilemma, so let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!
1. Familiar JSON.stringify ()
JSON.stringify () is a common method on both the browser side and the server side:
Store JSON object in localStorage
JSON body in POST request
Processing data in JSON form in the response body
Even under some conditions, we will use it to make a simple deep copy.
……
In some performance-sensitive situations (for example, the server handles a large number of concurrency), or when faced with a large number of stringify operations, we want its performance to be better and faster. This has also led to some optimized stringify schemes / libraries, which are shown below in comparison with native methods:
The green part is native JSON.stringify (), so you can see that the performance is much lower than these libraries. So what is the technical rationale behind the significant performance improvements?
two。 Stringify faster than stringify
Because JavaScript is a very dynamic language, for a variable of Object type, the key name, key value, and key value type can only be determined at run time. Therefore, there will be a lot of work to do when executing JSON.stringify (). Without knowing anything, it is obvious that there is nothing we can do to greatly optimize.
So will it help if we know the key name and key value information in this Object-- that is, its structure information?
Look at an example:
Here's the Object.
Const obj = {name: 'alienzhou', status: 6, working: true}
We apply JSON.stringify () to it and get the result as follows
JSON.stringify (obj); / / {"name": "alienzhou", "status": 6, "working": true}
Now if we know that the structure of this obj is fixed:
The key name remains the same
The type of key value must be
So, in fact, I can create a "custom" stringify method
Function myStringify (o) {return ('{"name": "'+ o.name +'", "status":'+ o.status +', "isWorking":'+ o.working +'}');}
Look at the output of our myStringify method:
MyStringify ({name: 'alienzhou', status: 6, working: true}); / / {"name": "alienzhou", "status": 6, "isWorking": true} myStringify ({name:' mengshou', status: 3, working: false}); / / {"name": "mengshou", "status": 3, "isWorking": false}
You can get the correct results, but only type conversion and string concatenation are used, so the "customization" approach can make "stringify" faster.
To sum up, how do you get a faster stringify method than stringify?
You need to determine the structure information of the object first.
According to its structure information, a "customized" stringify method is created for the object of this structure, and the internal result is actually generated by string concatenation.
* use this "customized" method to stringify the object.
This is also the pattern of most stringify acceleration libraries, which translates into code like this:
Import faster from 'some_library_faster_stringify'; / / 1. Through the corresponding rules, define your object structure const theObjectScheme = {/ /... }; / / 2. According to the structure, we get a customized method const stringify = faster (theObjectScheme); / / 3. Call the method, and quickly stringify const target = {/ /... }; stringify (target)
3. How to generate the method of customization
According to the above analysis, the core function is to create "customized" stringify methods for such objects based on their structural information, which is actually a simple property access and string concatenation.
In order to understand the specific implementation, let me take two open source libraries with slightly different implementations as examples.
3.1. Fast-json-stringify
The following figure shows the performance comparison based on the benchmark results provided by fast-json-stringify.
As you can see, there is a 2-5-fold performance improvement in most scenarios.
3.1.1. How scheme is defined
Fast-json-stringify uses JSON Schema Validation to define (JSON) the data format of the object. The structure defined by its scheme is itself in JSON format, such as objects
{name: 'alienzhou', status: 6, working: true}
The corresponding scheme is:
{title: 'Example Schema', type:' object', properties: {name: {type: 'string'}, status: {type:' integer'}, working: {type: 'boolean'}
Its scheme definition rules are rich, specific use can refer to Ajv this JSON check library.
3.1.2. Generation of stringify method
Fast-json-stringify splices the actual function code string based on the scheme just defined, and then uses the Function constructor to dynamically generate the corresponding stringify function at run time.
In code generation, it first injects various predefined tool methods, which are all the same for different scheme:
Var code = `'use strict'' code + =` ${$asString.toString ()} ${$asStringNullable.toString ()} ${$asStringSmall.toString ()} ${$asNumber.toString ()} ${$asNumberNullable.toString ()} ${$asIntegerNullable.toString ()} ${$asNull.toString ()} ${$asBoolean.toString ()} ${$asBooleanNullable.toString ()} `
Second, the specific code of the stringify function is generated according to the specific content of the scheme definition. The way to generate it is relatively simple: by traversing the scheme.
When traversing the scheme, according to the defined type, insert the corresponding tool function at the corresponding code for key-value conversion. For example, the attribute name in the above example:
Var accessor = key.indexOf ('[') = = 0? SanitizeKey (key): `['${sanitizeKey (key)}'] `switch (type) {case 'null': code + = `json + = $asNull () `break case' string': code + = nullable? `json + = obj$ {accessor} = null? Null: $asString (obj$ {accessor}) `: `json + = $asString (obj$ {accessor}) `break case 'integer': code + = nullable? `json + = obj$ {accessor} = null? Null: $asInteger (obj$ {accessor}) `: `json + = $asInteger (obj$ {accessor}) `break.
The code variable in the above code holds the code string of the function body generated by * *. Because name is of type string and is not empty in the scheme definition, the following code string is added to the code:
"json + = $asString (obj ['name'])"
Because you also need to deal with complex situations such as arrays and concatenated objects, the actual code is omitted a lot.
Then, the complete code string is generated roughly as follows:
Function $asString (str) {/ /. } function $asStringNullable (str) {/ /. } function $asStringSmall (str) {/ /. } function $asNumber (I) {/ /. } function $asNumberNullable (I) {/ /. } / * the above are a series of general key-value conversion methods * / / * $main is the main function of stringify * / function $main (input) {var obj = typeof input.toJSON = = 'function'? Input.toJSON (): input var json ='{'var addComma = false if (obj [' name']! = undefined) {if (addComma) {json + =','} addComma = true json + ='"name": 'json + = $asString (obj [' name'])} / /. Splicing json + ='} 'return json} return $main for other attributes (status, working)
*, pass the code string into the Function constructor to create the corresponding stringify function.
/ / dependencies is mainly used to handle situations that include anyOf and if syntax dependenciesName.push (code) return (Function.apply (null, dependenciesName). Apply (null, dependencies))
3.2. Slow-json-stringify
Although slow-json-stringify is called "slow", it is actually a stringify library of "fast" (mischievously named).
The slowest stringifier in the known universe. Just kidding, it's the fastest (:
Its implementation is more lightweight and ingenious than the fast-json-stringify mentioned earlier. At the same time, it is more efficient than fast-json-stringify in many scenarios.
3.2.1. How scheme is defined
The scheme definition of slow-json-stringify is more natural and simple, mainly replacing the key value with the type description. Again, in the example of the object above, scheme becomes
{name: 'string', status:' number', working: 'boolean'}
It's really intuitive.
3.2.2. Generation of stringify method
I don't know if you've noticed.
/ / scheme {name: 'string', status:' number', working: 'boolean'} / / Target object {name:' alienzhou', status: 6, working: true}
Is the structure of scheme similar to that of the original object?
The ingenuity of this scheme is that after this definition, we can first scheme JSON.stringify, and then "deduct" all the type values, and what is waiting for us is to populate the actual values directly into the type declaration corresponding to scheme.
How to operate it exactly?
First, you can directly call JSON.stringify () on scheme to generate the underlying template, while borrowing the second parameter of JSON.stringify () as the access path to the traversal method collection properties:
Let map = {}; const str = JSON.stringify (schema, (prop, value) = > {const isArray = Array.isArray (value); if (typeof value! = = 'object' | | isArray) {if (isArray) {const current = value [0]; arrais.set (prop, current);} _ validator (value); map [prop] = _ deepPath (schema, prop) Props + = `"${prop}" |`;} return value;})
At this point, the access paths of all attributes are collected in the map. At the same time, the generated props can be spliced into regular expressions that match the corresponding type of characters. For example, the regular expression in our example is / name | status | working "(string | number | boolean | undef)" |\ [(. *?)\] /.
Then, match these attributes sequentially according to the regular expression, replace the string of attribute type with the uniform placeholder string "_ _ par__", and split the string based on "_ _ par__":
Const queue = []; const chunks = str. Replace (regex, (type) = > {switch (type) {case'"string"': case'"undefined"': return'"_ _ par__"' Case'"number"': case'"boolean"': case'["array-simple"]': case'[null]': return'_ par__'; default: const prop = type.match (/ (?
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.