We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
很长的JSON串的序列化和反序列化耗时比较大,能否换一种方式,缩短耗时。
JSON序列化的时候,多记录一些信息,并将这些信息作为反序列化的依据,而不是直接反序列源数据。
比如有一个串 '{"name":{"key":"hello"}}'
记录第一个为{,第一个键的初始位置2,结束位置5,值的初始位置为7,结束位置11,值的类型是字符串。键值对以及数组的两个值之间都是,分隔。
也就是说记录下值的类型,位置,避免循环整个串去判断取值,直接根据位置取值,然后再根据值类型进一步分析。
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>Page Title</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <script> (function () { var sum0 = '' var locations = [] function stringify(value) { sum0 = '' locations = [] string("", {"": value}) return { str: sum0, locations: locations.join(" ") } } function string(key, holder) { // 引用值的位置 if (!holder.___location) { locations.push("") Object.defineProperty(holder, '___location', { enumerable: false, configurable: false, writable: false, value: locations.length - 1 }) } var value = holder[key] var str0 = "" var index = sum0.length switch (typeof value) { case "string": str0 = value locations.push("s|" + index + "|" + str0.length) Object.defineProperty(holder, [key + 'Location'], { enumerable: false, configurable: false, writable: false, value: locations.length - 1 }) break case "number": str0 = String(value) locations.push("n|" + index + "|" + str0.length) Object.defineProperty(holder, [key + 'Location'], { enumerable: false, configurable: false, writable: false, value: locations.length - 1 }) break case "boolean": str0 = String(value) locations.push("b|" + index + "|" + str0.length) Object.defineProperty(holder, [key + 'Location'], { enumerable: false, configurable: false, writable: false, value: locations.length - 1 }) break case "null": str0 = String(value) locations.push("u|" + index + "|" + str0.length) Object.defineProperty(holder, [key + 'Location'], { enumerable: false, configurable: false, writable: false, value: locations.length - 1 }) break case "object": if (value === null) { str0 = "null" locations.push("u|" + index + "|" + str0.length) Object.defineProperty(holder, [key + 'Location'], { enumerable: false, configurable: false, writable: false, value: locations.length - 1 }) } else if (Object.prototype.toString.apply(value) === "[object Array]") { var length = value.length var partial = [] for (var i = 0; i < length; i += 1) { string(i, value) || "null" partial.push(value[i + 'Location']) if (value[i] && typeof value[i] === 'object') { Object.defineProperty(value, [key + 'Location'], { enumerable: false, configurable: false, writable: false, value: value[i].___location }) } } locations[value.___location] = "a|" + partial.join("|") } else { var partial = [] for (var key1 in value) { if (Object.prototype.hasOwnProperty.call(value, key1)) { string(key1, value) var index1 = sum0.length sum0 += key1 locations.push(index1 + "|" + key1.length) if (value[key1] && typeof value[key1] === 'object') { Object.defineProperty(value, [key1 + 'Location'], { enumerable: false, configurable: false, writable: false, value: value[key1].___location }) } partial.push((locations.length - 1) + "=" + value[key1 + 'Location']) } } locations[value.___location] = "o|" + partial.join("|") } break } sum0 += str0 return str0 } // o|1=2|3=4 // 对象类型|键1的位置=值1的位置|键2的位置=值2的位置 // a|10|20 // 数组类型|索引1值的位置|索引2值的位置 // console.log(JSON.stringify(obj) === str) // 类型 起始位置 长度 /* 值的类型 s -> string n -> number o -> object a -> array t -> true f -> false u -> null */ var obj = { name: 123 } function creat() { var i = 0 var obj = { } var cur = obj while (i < 1000) { i++ var nested = { name: 'hello', world: [1, 2, 3] } cur.nested = nested cur = nested } return obj } function parse(str, location) { var value = {} var locations = location.split(' ') walk(value, '', str, locations, "o|0=1") return value[''][''] } function walk(holder, key, str, locations, info) { var array = info.split('|') var type = array.shift() if (type === 'o') { var value = holder[key] = {} array.forEach(function (ele) { var positions = ele.split('=') var keyPositions = locations[positions[0] * 1].split("|") var keyStart = keyPositions[0] * 1 var key = str.substring(keyStart, keyStart + keyPositions[1] * 1) walk(value, key, str, locations, locations[positions[1] * 1]) }) } else if (type === 'a') { var value = holder[key] = [] array.forEach(function (position, index) { walk(value, index, str, locations, locations[position]) }) } else if (type === 's') { var start = array[0] * 1 holder[key] = str.substring(start, start + array[1] * 1) } else if (type === 'b') { var start = array[0] * 1 holder[key] = new Boolean(str.substring(start, start + array[1] * 1)) } else if (type === 'n') { var start = array[0] * 1 holder[key] = str.substring(start, start + array[1] * 1) * 1 } else if (type === 'u') { holder[key] = null } } var start = Date.now() var str_locations = stringify(obj) console.log(str_locations.str + str_locations.locations) console.log(parse(str_locations.str, str_locations.locations)) console.log('优化序列化及反序列化耗时: ', Date.now() - start, 'ms') var start = Date.now() var str = JSON.stringify(obj) console.log(str) console.log(JSON.parse(str)) console.log('JSON序列化及反序列化耗时: ', Date.now() - start, 'ms') })() </script> </head> <body> </body> </html>
实现思路描述: 对象:{ name: 123 } 数据字符串:123name 描述字符串:o|3=2 n|0|3 3|4
o代表的是对象,有一个键,键的在描述字符串内位于索引3 ,即3|4,存储的是数据字符串的位置,3代表起始位置,4代表长度,取出来就是name,name对应的值位于索引2,是一个数字类型,从字符串内取出得到值123
这种方式目前实现出来数据量比原生的JSON序列化和反序列化大很多,数据字符串短了,但是描述字符串很长,解析耗时方面也长很多。比JSON的序列化执行耗时会快一些。猜测原生代码是c语言实现,二进制代码执行效率高,打算用c++再实现一次,缩短描述字符串,看看能否应用在c++、java这种语言内。目前来看在javascript中这种方式应该行不通。
描述字符串长的原因是,越往后拼接的值,其起始索引越大,考虑将起始索引缩小,因为这个值在前面有可能出现过,取前面出现过的小的起始索引。
The text was updated successfully, but these errors were encountered:
No branches or pull requests
很长的JSON串的序列化和反序列化耗时比较大,能否换一种方式,缩短耗时。
JSON序列化的时候,多记录一些信息,并将这些信息作为反序列化的依据,而不是直接反序列源数据。
比如有一个串
'{"name":{"key":"hello"}}'
记录第一个为{,第一个键的初始位置2,结束位置5,值的初始位置为7,结束位置11,值的类型是字符串。键值对以及数组的两个值之间都是,分隔。
也就是说记录下值的类型,位置,避免循环整个串去判断取值,直接根据位置取值,然后再根据值类型进一步分析。
实现思路描述:
对象:{ name: 123 }
数据字符串:123name
描述字符串:o|3=2 n|0|3 3|4
o代表的是对象,有一个键,键的在描述字符串内位于索引3 ,即3|4,存储的是数据字符串的位置,3代表起始位置,4代表长度,取出来就是name,name对应的值位于索引2,是一个数字类型,从字符串内取出得到值123
这种方式目前实现出来数据量比原生的JSON序列化和反序列化大很多,数据字符串短了,但是描述字符串很长,解析耗时方面也长很多。比JSON的序列化执行耗时会快一些。猜测原生代码是c语言实现,二进制代码执行效率高,打算用c++再实现一次,缩短描述字符串,看看能否应用在c++、java这种语言内。目前来看在javascript中这种方式应该行不通。
描述字符串长的原因是,越往后拼接的值,其起始索引越大,考虑将起始索引缩小,因为这个值在前面有可能出现过,取前面出现过的小的起始索引。
The text was updated successfully, but these errors were encountered: