Skip to content

Conversation

ChrisBenua
Copy link
Contributor

In short: T.self is _JSONStringDictionaryDecodableMarker.Type, value as? _JSONStringDictionaryEncodableMarker and value as? _JSONDirectArrayEncodable are really slow operations. And the bigger binary gets the slower this check works for the first time for each pair of class/struct/enum and protocol.

But checking whether current type conforms to _JSONStringDictionaryDecodableMarker and _JSONStringDictionaryEncodableMarker is needed only when we use custom keyDecoding/EncodingStrategy. Comments in code confirm this:

/// A marker protocol used to determine whether a value is a `String`-keyed `Dictionary`
/// containing `Decodable` values (in which case it should be exempt from key conversion strategies).
///
/// The marker protocol also provides access to the type of the `Decodable` values,
/// which is needed for the implementation of the key conversion strategy exemption.
private protocol _JSONStringDictionaryDecodableMarker {
    static var elementType: Decodable.Type { get }
}
/// A marker protocol used to determine whether a value is a `String`-keyed `Dictionary`
/// containing `Encodable` values (in which case it should be exempt from key conversion strategies).
private protocol _JSONStringDictionaryEncodableMarker { }

So we can easily skip this checks when default keyDecoding/EncodingStrategy is used.

For details: see this issue: #1480

@ChrisBenua
Copy link
Contributor Author

Benchmarking results

Collected using this command swift package --allow-writing-to-package-directory benchmark baseline compare new_coders --target JSONBenchmarks --format markdown

Comparing results between 'old_coders' and 'Current_run'

Host 'Christians-MacBook-Pro.local' with 8 'arm64' processors with 16 GB memory, running:
Darwin Kernel Version 24.6.0: Mon Jul 14 11:30:34 PDT 2025; root:xnu-11417.140.69~1/RELEASE_ARM64_T8103

JSONBenchmarks

Canada-decodeFromJSON metrics

Time (total CPU): results within specified thresholds, fold down for details.

Time (total CPU) (μs) * p0 p25 p50 p75 p90 p99 p100 Samples
old_coders 27 27 27 27 27 27 28 112
Current_run 27 27 28 28 28 28 28 109
Δ 0 0 1 1 1 1 0 -3
Improvement % 0 0 -4 -4 -4 -4 0 -3

Throughput (# / s): results within specified thresholds, fold down for details.

Throughput (# / s) (K) p0 p25 p50 p75 p90 p99 p100 Samples
old_coders 38 38 37 37 37 37 36 112
Current_run 37 36 36 36 36 36 36 109
Δ -1 -2 -1 -1 -1 -1 0 -3
Improvement % -3 -5 -3 -3 -3 -3 0 -3

Canada-encodeToJSON metrics

Time (total CPU): results within specified thresholds, fold down for details.

Time (total CPU) (μs) * p0 p25 p50 p75 p90 p99 p100 Samples
old_coders 54 54 54 54 55 55 55 56
Current_run 54 54 54 54 55 55 55 56
Δ 0 0 0 0 0 0 0 0
Improvement % 0 0 0 0 0 0 0 0

Throughput (# / s): results within specified thresholds, fold down for details.

Throughput (# / s) (K) p0 p25 p50 p75 p90 p99 p100 Samples
old_coders 19 18 18 18 18 18 18 56
Current_run 19 18 18 18 18 18 18 56
Δ 0 0 0 0 0 0 0 0
Improvement % 0 0 0 0 0 0 0 0

Twitter-decodeFromJSON metrics

Time (total CPU): results within specified thresholds, fold down for details.

Time (total CPU) (ns) * p0 p25 p50 p75 p90 p99 p100 Samples
old_coders 2150 2163 2169 2198 2224 2292 2448 1374
Current_run 2152 2165 2167 2175 2204 2247 2477 1379
Δ 2 2 -2 -23 -20 -45 29 5
Improvement % 0 0 0 1 1 2 -1 5

Throughput (# / s): results within specified thresholds, fold down for details.

Throughput (# / s) (K) p0 p25 p50 p75 p90 p99 p100 Samples
old_coders 465 463 461 456 450 435 389 1374
Current_run 465 463 462 460 454 446 404 1379
Δ 0 0 1 4 4 11 15 5
Improvement % 0 0 0 1 1 3 4 5

Twitter-encodeToJSON metrics

Time (total CPU): results within specified thresholds, fold down for details.

Time (total CPU) (ns) * p0 p25 p50 p75 p90 p99 p100 Samples
old_coders 1078 1083 1085 1089 1094 1155 1314 2752
Current_run 1085 1091 1093 1095 1100 1135 1280 2738
Δ 7 8 8 6 6 -20 -34 -14
Improvement % -1 -1 -1 -1 -1 2 3 -14

Throughput (# / s): results within specified thresholds, fold down for details.

Throughput (# / s) (K) p0 p25 p50 p75 p90 p99 p100 Samples
old_coders 928 924 922 920 915 864 629 2752
Current_run 922 918 917 914 910 882 782 2738
Δ -6 -6 -5 -6 -5 18 153 -14
Improvement % -1 -1 -1 -1 -1 2 24 -14

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

Successfully merging this pull request may close these issues.

1 participant