quinnj / JSON3.jl

Other
214 stars 47 forks source link

Very long compilation times in JSON3.read with nested structures #205

Closed doctordreas closed 2 years ago

doctordreas commented 2 years ago

Firstly - thanks for this amazing package (which is allowing me to deprecate a ton of code).

I am using JSON3.read to parse a deeply nested structure but have found the compilation time increases with depth of nesting to the point of becoming a show stopper for my particular application.

Sample to reproduce included below with an output run.

Using Julia 1.7.1 on Windows 10.

[0f8b85d8] JSON3 v1.9.2 [856f2bd8] StructTypes v1.8.1

Thanks very much for any assistance or suggestions.

module TestJSON3CompilationSpeed

using JSON3
using StructTypes

struct A
a::Int
end

struct B
b::A
end

struct C
c::B
end

struct D
d::C
end

struct E
e::D
end

struct F
f::E
end

struct G
g::F
end

struct H
h::G
end

struct I
i::H
end

StructTypes.StructType(::Type{A}) = StructTypes.Struct()
StructTypes.StructType(::Type{B}) = StructTypes.Struct()
StructTypes.StructType(::Type{C}) = StructTypes.Struct()
StructTypes.StructType(::Type{D}) = StructTypes.Struct()
StructTypes.StructType(::Type{E}) = StructTypes.Struct()
StructTypes.StructType(::Type{F}) = StructTypes.Struct()
StructTypes.StructType(::Type{G}) = StructTypes.Struct()
StructTypes.StructType(::Type{H}) = StructTypes.Struct()
StructTypes.StructType(::Type{I}) = StructTypes.Struct()

A_str = """ {"a":1} """
B_str = """ {"b":$(A_str)} """
C_str = """ {"c":$(B_str)} """
D_str = """ {"d":$(C_str)} """
E_str = """ {"e":$(D_str)} """
F_str = """ {"f":$(E_str)} """
G_str = """ {"g":$(F_str)} """
H_str = """ {"h":$(G_str)} """
I_str = """ {"i":$(H_str)} """

println("Timing A to I first pass")
@time JSON3.read(A_str, A)
@time JSON3.read(B_str, B)
@time JSON3.read(C_str, C)
@time JSON3.read(D_str, D)
@time JSON3.read(E_str, E)
@time JSON3.read(F_str, F)
@time JSON3.read(G_str, G)
@time JSON3.read(H_str, H)
@time JSON3.read(I_str, I)

println("Timing A to I second pass")
@time JSON3.read(A_str, A)
@time JSON3.read(B_str, B)
@time JSON3.read(C_str, C)
@time JSON3.read(D_str, D)
@time JSON3.read(E_str, E)
@time JSON3.read(F_str, F)
@time JSON3.read(G_str, G)
@time JSON3.read(H_str, H)
@time JSON3.read(I_str, I)

end # module
               _
   _       _ _(_)_     |  Documentation: https://docs.julialang.org
  (_)     | (_) (_)    |
   _ _   _| |_  __ _   |  Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 1.7.1 (2021-12-22)
 _/ |\__'_|_|_|\__'_|  |  Official https://julialang.org/ release
|__/                   |

julia> include("TestJSON3CompilationSpeed.jl")
Timing A to I first pass
  2.728005 seconds (12.78 M allocations: 537.905 MiB, 5.69% gc time, 100.00% compilation time)
  1.674844 seconds (6.69 M allocations: 243.955 MiB, 4.07% gc time, 100.00% compilation time)
  2.905516 seconds (11.00 M allocations: 396.640 MiB, 5.31% gc time, 100.00% compilation time)
  4.322817 seconds (15.30 M allocations: 550.317 MiB, 3.89% gc time, 100.00% compilation time)
  6.090615 seconds (19.60 M allocations: 704.165 MiB, 4.08% gc time, 100.00% compilation time)
  8.664862 seconds (23.91 M allocations: 852.310 MiB, 3.41% gc time, 100.00% compilation time)
 10.052238 seconds (28.21 M allocations: 1000.251 MiB, 3.13% gc time, 100.00% compilation time)
 13.860841 seconds (32.51 M allocations: 1.122 GiB, 2.93% gc time, 100.00% compilation time)
 16.696443 seconds (36.81 M allocations: 1.268 GiB, 2.59% gc time, 100.00% compilation time)
Timing A to I second pass
  0.000010 seconds (2 allocations: 320 bytes)
  0.000010 seconds (4 allocations: 640 bytes)
  0.000014 seconds (6 allocations: 960 bytes)
  0.000016 seconds (8 allocations: 1.250 KiB)
  0.000021 seconds (10 allocations: 1.562 KiB)
  0.000024 seconds (12 allocations: 1.875 KiB)
  0.000022 seconds (14 allocations: 2.188 KiB)
  0.000024 seconds (16 allocations: 2.500 KiB)
  0.000028 seconds (18 allocations: 2.812 KiB)
Main.TestJSON3CompilationSpeed

julia> 

quinnj commented 2 years ago

Thanks for the detailed report! Fix is up: https://github.com/quinnj/JSON3.jl/pull/206