v2 / vlib / v / tests / bench / bench_json_vs_json2.v
229 lines · 200 sloc · 8.29 KB · a86e8cf276475d86bcb4d1dc69d838ecd6df0c80
Raw
1import os
2import json
3import x.json2
4import time
5import benchmark
6
7// recommendations:
8// ./v wipe-cache && MAX_ITERATIONS=100_000 ./v run vlib/v/tests/bench/bench_json_vs_json2.v
9// ./v wipe-cache && MAX_ITERATIONS=100_000 ./v -prod crun vlib/v/tests/bench/bench_json_vs_json2.v
10// ./v wipe-cache && ./v -gc boehm_leak -o testcase_leak -prod vlib/v/tests/bench/bench_json_vs_json2.v && ./testcase_leak 2>leaks.txt
11// ./v wipe-cache && ./v -prod vlib/v/tests/bench/bench_json_vs_json2.v -o b_out && valgrind --track-origins=yes ./b_out
12
13const max_iterations = os.getenv_opt('MAX_ITERATIONS') or { '1000' }.int()
14
15fn main() {
16 benchmark_measure_json_vs_json2_on_complex_struct()!
17 println('')
18 benchmark_measure_decode_by_type()!
19 println('')
20 benchmark_measure_encode_by_type()!
21 println('')
22 benchmark_measure_encode_by_alias_type()!
23}
24
25type StringAlias = string
26type BoolAlias = bool
27type IntAlias = int
28type TimeAlias = time.Time
29type StructAlias = StructType[int]
30type EnumAlias = Enum
31
32type SumTypes = StructType[string] | bool | int | string | time.Time
33
34enum Enum {
35 a
36 b
37 c
38 d
39 e = 99
40 f
41}
42
43struct StructType[T] {
44mut:
45 val T
46}
47
48struct StructTypeOption[T] {
49mut:
50 val ?T
51}
52
53struct StructTypePointer[T] {
54mut:
55 val &T
56}
57
58struct Person {
59 name string
60 age int
61 created_at time.Time
62}
63
64fn benchmark_measure_json_vs_json2_on_complex_struct() ! {
65 println(@FN)
66 dump('👈')
67 s := '{"name":"Bilbo Baggins","age":99,"created_at":1670840340}'
68 mut b := benchmark.start()
69 for _ in 0 .. max_iterations {
70 p := json2.decode[Person](s)!
71 if p.age != 99 {
72 return error('json2.decode ${p}')
73 }
74 }
75 b.measure('json2.decode')
76 for _ in 0 .. max_iterations {
77 p := json.decode(Person, s)!
78 if p.age != 99 {
79 return error('json.decode ${p}')
80 }
81 }
82 b.measure('json.decode\n')
83
84 measure_json_encode_old_vs_new(json.decode(Person, s)!)!
85}
86
87fn benchmark_measure_encode_by_type() ! {
88 println(@FN)
89 dump('👈')
90
91 big_multiple_type_string := '✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t✔な🐈\t'
92 println('✔な🐈\t = ${big_multiple_type_string.len}')
93 measure_json_encode_old_vs_new(StructType[string]{big_multiple_type_string})!
94
95 big_emoji_string := '🐈🐟🐧🐀💀🐈🐟🐧🐀💀🐈🐟🐧🐀💀🐈🐟🐧🐀💀🐈🐟🐧🐀💀🐈🐟🐧🐀💀🐈🐟🐧🐀💀🐈🐟🐧🐀💀🐈🐟🐧🐀💀🐈🐟🐧🐀💀🐈🐟🐧🐀💀🐈🐟🐧🐀💀🐈🐟🐧🐀💀🐈🐟🐧🐀💀🐈🐟🐧🐀💀🐈🐟🐧🐀💀🐈🐟🐧🐀💀🐈🐟🐧🐀💀🐈🐟🐧🐀💀🐈🐟🐧🐀💀🐈🐟🐧🐀💀🐈🐟🐧🐀💀🐈🐟🐧🐀💀🐈🐟🐧🐀💀🐈🐟🐧🐀💀'
96 println('🐈🐟🐧🐀💀 = ${big_emoji_string.len}')
97 measure_json_encode_old_vs_new(StructType[string]{big_emoji_string})!
98
99 big_no_ancii_string := 'ひらがなひらがなひらがなひらがなひらがなひらがなひらがなひらがなひらがなひらがなひらがなひらがなひらがなひらがなひらがなひらがなひらがなひらがなひらがなひらがなひらがなひらがなひらがなひらがなひらがなひらがなひらがなひらがなひらがなひらがなひらがな'
100 println('ひらがな = ${big_no_ancii_string.len}')
101 measure_json_encode_old_vs_new(StructType[string]{big_no_ancii_string})!
102
103 big_string := 'jhsbhjhajbujhfbdjhgbxdljgbxdlkjgbxdlkgjbdlfjbszldjkfbdljgbzsljfzsbkfdjsbfljhsdhbfljzhsdbfljzshfblszdjfbjzhdsbfjzsdhbfljsdhbfljzsdfblzjsdfbzsjdfbhljzsdhfbljzsbfjsdbfjshdbfljzsdhbfljzsdhbfljszdbhfljzsbfljhzsbdfljhzbsdljfbsdljfbzlsjfhdbzdsljhfbszdljhfbzsldjfhbszdljhfbzsdljfhbzsdjhfbdsljhfbljsdhbflsjdhjhsbh jhajbujhfbdjhgbxdljgbxdlkjgbxdlkgjbdlfjbszldjkfbdljgbzsljfzsbkfdjsbfljhsdhbfljzhsdbfljzshfblszdjfbjzhdsbfjzsdhbfljsdhbfljzsdfblzjsdfbzsjdfbhljzsdhfbljzsbfjsdbfjshdbfljzsdhbfljzsdhbfljszdbhfljzsbfljhzsbdfljhzbsdljfbsdljfbzlsjfhdbzdsljhfbszdljhfbzsldjfhbszdljhfbzsdljfhbzsdjhfbdsljhfbljsdhbflsjdh'
104
105 println('big string length = ${big_string.len}')
106 measure_json_encode_old_vs_new(StructType[string]{big_string})!
107
108 println('empty string')
109 measure_json_encode_old_vs_new(StructType[string]{})!
110
111 println('empty time.Time')
112 measure_json_encode_old_vs_new(StructType[time.Time]{})!
113 println('time.utc()')
114 measure_json_encode_old_vs_new(StructType[time.Time]{time.utc()})!
115 println('time.now()')
116 measure_json_encode_old_vs_new(StructType[time.Time]{time.now()})!
117 measure_json_encode_old_vs_new(StructType[int]{})!
118 measure_json_encode_old_vs_new(StructType[u64]{u64(-1)})! // 18446744073709551615
119 measure_json_encode_old_vs_new(StructType[f64]{})!
120 measure_json_encode_old_vs_new(StructType[bool]{false})!
121
122 println('empty array')
123 measure_json_encode_old_vs_new(StructType[[]int]{})!
124
125 println('array with 10 elements [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]')
126 measure_json_encode_old_vs_new(StructType[[]int]{[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]})!
127 measure_json_encode_old_vs_new(StructType[StructType[int]]{ val: StructType[int]{} })!
128 measure_json_encode_old_vs_new(StructType[Enum]{})!
129 measure_json_encode_old_vs_new(StructType[SumTypes]{1})!
130}
131
132fn benchmark_measure_encode_by_alias_type() ! {
133 println(@FN)
134 dump('👈')
135 measure_json_encode_old_vs_new(StructType[StringAlias]{})!
136 measure_json_encode_old_vs_new(StructType[TimeAlias]{})!
137 measure_json_encode_old_vs_new(StructType[IntAlias]{})!
138 measure_json_encode_old_vs_new(StructType[BoolAlias]{})!
139 measure_json_encode_old_vs_new(StructType[StructAlias]{})!
140}
141
142fn benchmark_measure_decode_by_type() ! {
143 println(@FN)
144 dump('👈')
145 mut b := benchmark.start()
146
147 vs := '{"val": ""}'
148 for _ in 0 .. max_iterations {
149 d := json2.decode[StructType[string]](vs)!
150 if d.val != '' {
151 return error('json2.decode ${d}')
152 }
153 }
154 b.measure('json2.decode StructType[string]')
155 for _ in 0 .. max_iterations {
156 d := json.decode(StructType[string], vs)!
157 if d.val != '' {
158 return error('json.decode ${d}')
159 }
160 }
161 b.measure(' json.decode StructType[string]\n')
162
163 vb := '{"val": true}'
164 for _ in 0 .. max_iterations {
165 d := json2.decode[StructType[bool]](vb) or { panic('') }
166 if !d.val {
167 return error('json2.decode ${d}')
168 }
169 }
170 b.measure('json2.decode StructType[bool]')
171 for _ in 0 .. max_iterations {
172 d := json.decode(StructType[bool], vb) or { panic('') }
173 if !d.val {
174 return error('json.decode ${d}')
175 }
176 }
177 b.measure(' json.decode StructType[bool]\n')
178
179 v0 := '{"val": 0}'
180 for _ in 0 .. max_iterations {
181 d := json2.decode[StructType[int]](v0)!
182 if d.val != 0 {
183 return error('json2.decode ${d}')
184 }
185 }
186 b.measure('json2.decode StructType[int]')
187 for _ in 0 .. max_iterations {
188 d := json.decode(StructType[int], v0)!
189 if d.val != 0 {
190 return error('json.decode ${d}')
191 }
192 }
193 b.measure(' json.decode StructType[int]\n')
194
195 vt := '{"val": "2015-01-06 15:47:32"}'
196 for _ in 0 .. max_iterations {
197 d := json2.decode[StructType[time.Time]](vt)!
198 if d.val.year != 2015 {
199 return error('json2.decode ${d}')
200 }
201 }
202 b.measure('json2.decode StructType[time.Time]')
203 for _ in 0 .. max_iterations {
204 d := json.decode(StructType[time.Time], vt)!
205 if d.val.year != 2015 {
206 return error('json.decode ${d}')
207 }
208 }
209 b.measure(' json.decode StructType[time.Time]\n')
210}
211
212fn measure_json_encode_old_vs_new[T](val T) ! {
213 typename := typeof[T]().name
214 mut b := benchmark.start()
215 for _ in 0 .. max_iterations {
216 e := json2.encode(val)
217 if e[0] != `{` {
218 return error('json2.encode ${e}')
219 }
220 }
221 b.measure('json2.encode ${typename}')
222 for _ in 0 .. max_iterations {
223 e := json.encode(val)
224 if e[0] != `{` {
225 return error('json.encode ${e}')
226 }
227 }
228 b.measure(' json.encode ${typename}\n')
229}
230