Skip to content

Commit 7f0e31a

Browse files
committed
[perf] JSON encoding can be faster by skipping string building.
I realized that one of the test related to CharacterSet was very slow in constrained devices, but also relatively slow in beefy Linux machines (taking a couple of seconds to perform back and forth JSON encoding/decoding trips in memory). The test in question have to embed relatively large Data in the JSON string (around 128KB, if I remember correctly), which are serialized as Base64. When serializing the data, the serializer ask for the String representation of each object, and then appends all of them into a String, to later transform into an UTF-8 C string copied into a Data. One can improve performance by appending the UTF-8 representation of each piece of the JSON serialization instead of the String building code, since appending [UInt8] without doing all the checking that String will do is faster for this case.
1 parent 7dba88d commit 7f0e31a

File tree

1 file changed

+4
-6
lines changed

1 file changed

+4
-6
lines changed

Foundation/JSONSerialization.swift

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -123,14 +123,14 @@ open class JSONSerialization : NSObject {
123123
/* Generate JSON data from a Foundation object. If the object will not produce valid JSON then an exception will be thrown. Setting the NSJSONWritingPrettyPrinted option will generate JSON with whitespace designed to make the output more readable. If that option is not set, the most compact possible JSON will be generated. If an error occurs, the error parameter will be set and the return value will be nil. The resulting data is a encoded in UTF-8.
124124
*/
125125
internal class func _data(withJSONObject value: Any, options opt: WritingOptions, stream: Bool) throws -> Data {
126-
var jsonStr = String()
126+
var jsonStr = [UInt8]()
127127

128128
var writer = JSONWriter(
129129
pretty: opt.contains(.prettyPrinted),
130130
sortedKeys: opt.contains(.sortedKeys),
131131
writer: { (str: String?) in
132132
if let str = str {
133-
jsonStr.append(str)
133+
jsonStr.append(contentsOf: Array(str.utf8))
134134
}
135135
}
136136
)
@@ -147,10 +147,8 @@ open class JSONSerialization : NSObject {
147147
fatalError("Top-level object was not NSArray or NSDictionary") // This is a fatal error in objective-c too (it is an NSInvalidArgumentException)
148148
}
149149

150-
let count = jsonStr.utf8.count
151-
return jsonStr.withCString {
152-
Data(bytes: $0, count: count)
153-
}
150+
let count = jsonStr.count
151+
return Data(bytes: &jsonStr, count: count)
154152
}
155153

156154
open class func data(withJSONObject value: Any, options opt: WritingOptions = []) throws -> Data {

0 commit comments

Comments
 (0)