Skip to content
New issue

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

Not faster than JSONDecoder for specific case #52

Closed
michaeleisel opened this issue Aug 30, 2022 · 12 comments
Closed

Not faster than JSONDecoder for specific case #52

michaeleisel opened this issue Aug 30, 2022 · 12 comments

Comments

@michaeleisel
Copy link
Owner

This issue is to track a case that was reported where ZippyJSON is only 7% faster than JSONDecoder

@RandomHashTags
Copy link

ZippyJSON is actually slower, usually 2.5x or more, when I test it. Running Swift 5.7, Xcode 14 beta 3, macOS 12.5.1, on a 2019 iMac (Intel i9 8-core, 3.6 GHz). Usually takes ~23ms for JSONDecoder and ~67ms for ZippyJSON.

full code
private func decode() async throws {
    let url:String = "https://api.weather.gov/alerts/active?status=actual"
    let data:Data = try await X // get server response
    for _ in 0..<10 {
        async let zippy:Void = testZippy(data)
        async let apple:Void = testApple(data)
        let _:(Void, Void) = await (zippy, apple)
    }
}
private func testApple(_ data: Data) async {
    let started:Int64 = getCurrentTimeMilliseconds()
    let response1:WeatherJSONResponse = try! JSONDecoder().decode(WeatherJSONResponse.self, from: data)
    print("configure;testApple;took " + getElapsedTime(started: started))
}
private func testZippy(_ data: Data) async {
    let started:Int64 = getCurrentTimeMilliseconds()
    let response2:WeatherJSONResponse = try! ZippyJSONDecoder().decode(WeatherJSONResponse.self, from: data)
    print("configure;testZippy;took " + getElapsedTime(started: started))
}
private func getCurrentTimeMilliseconds() -> Int64 {
    return Int64( (Date().timeIntervalSince1970 * 1000.0).rounded() )
}
private func getElapsedTime(started: Int64) -> String {
    return getElapsedTimeFromMilliseconds(elapsedMilliseconds: getCurrentTimeMilliseconds()-started)
}
private func getElapsedTimeFromMilliseconds(elapsedMilliseconds: Int64) -> String {
    var elapsedMilliseconds:Int64 = elapsedMilliseconds
    var elapsedSeconds:Int64 = elapsedMilliseconds / 1000
    elapsedMilliseconds -= elapsedSeconds * 1000
    let elapsedMinutes:Int64 = elapsedSeconds / 60
    elapsedSeconds -= elapsedMinutes * 60
    return (elapsedMinutes > 0 ? elapsedMinutes.description + "m" : "") + (elapsedSeconds > 0 ? elapsedSeconds.description + "s" : "") + Int(elapsedMilliseconds).description + "ms"
}

struct WeatherJSONResponse : Codable {
    let features:[WeatherJSONResponseFeature]
}
struct WeatherJSONResponseFeature : Codable {
    let id:String, properties:WeatherJSONResponseFeatureProperties?
}
struct WeatherJSONResponseFeatureProperties : Codable {
    let id:String, event:String, description:String
    let severity:String
    let headline:String?, instruction:String?
    let sent:String?, ends:String?, effective:String?, expires:String?
    let affectedZones:[String]?
}

@michaeleisel
Copy link
Owner Author

Are you compiling in release mode?

@RandomHashTags
Copy link

RandomHashTags commented Sep 9, 2022

Production/release mode gives slightly better performance to both; ~20ms for JSONDecoder and ~57ms for ZippyJSON.

@addy239
Copy link

addy239 commented Sep 14, 2022

Similar case for me, though my JSON file is massive, ~2.6MB and it takes JSONDecoder 0.55s while it took ZippyJSON 3.3s, both debug mode.

@michaeleisel
Copy link
Owner Author

@addy239 please do all measurements with release mode

@RandomHashTags on my arm mac I am seeing ~4ms for ZippyJSON and ~19ms for Apple, are you sure that you're on release? If so, can you make sure that you're on the latest version, 1.2.5? And try it on an actual phone if it's an iOS app? Note that switching to release generally makes a big difference for ZippyJSON, and doesn't speed up JSONDecoder (any "speed up" you see for JSONDecoder in release is actually just due to noise, beca
active.json.zip
use debug/release doesn't affect JSONDecoder, since it is already compiled). Also, in the attached .zip is the exact copy from that endpoint that I am using.

@addy239
Copy link

addy239 commented Oct 1, 2022

Results with release mode (iPhone 14 Pro, previously I used an iPhone Xs in Debug):

~0.24s with JSONDecoder
~0.36s with ZippyJSONDecoder

Same file as before.

@michaeleisel
Copy link
Owner Author

Can you provide everything necessary for me to reproduce? I.e. the source code for the benchmarking, JSON models, and the JSON file itself.

@addy239
Copy link

addy239 commented Oct 1, 2022

I'm sorry I don't have the models in a form I can share as they are actively used in production and I'm not sure if only sharing the JSON file would be useful to you.

@RandomHashTags
Copy link

@addy239 please do all measurements with release mode

@RandomHashTags on my arm mac I am seeing ~4ms for ZippyJSON and ~19ms for Apple, are you sure that you're on release? If so, can you make sure that you're on the latest version, 1.2.5? And try it on an actual phone if it's an iOS app? Note that switching to release generally makes a big difference for ZippyJSON, and doesn't speed up JSONDecoder (any "speed up" you see for JSONDecoder in release is actually just due to noise, beca active.json.zip use debug/release doesn't affect JSONDecoder, since it is already compiled). Also, in the attached .zip is the exact copy from that endpoint that I am using.

Upon further investigation, I am getting 4-6ms using ZippyJSON and 19-20ms using JSONDecoder on my same machine, same code, release mode, running Xcode 14.1 beta 3 with toolchain Swift 5.7 Release 2022-09-12. The previously poor performance probably was my configuration some where, and not this library.

@michaeleisel
Copy link
Owner Author

@addy239 without the code, it's hard for me to reproduce, and as with @RandomHashTags there may be some configuration issue. Closing...

@robsontenorio
Copy link

@RandomHashTags do you mind to share what configuration affected performance ?

@RandomHashTags
Copy link

@RandomHashTags do you mind to share what configuration affected performance ?

Not sure exactly, but I'm pretty sure it was something with Xcode's build caching. After cleaning the build folder, closing Xcode and simulators completely, and reopening the project, the issue was resolved.

It is important to note that this was 9 months ago (and on an Xcode beta), so I am unconfidently guessing on how I fixed my issue at the time.
Another important note would be: the benchmark methodology is flawed, which can now be measured natively using the <Clock>.measure function.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants