ssrjson-benchmark 0.0.4__cp310-cp310-win_amd64.whl → 0.0.5__cp310-cp310-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ssrjson-benchmark might be problematic. Click here for more details.
- ssrjson_benchmark/__main__.py +18 -4
- ssrjson_benchmark/_ssrjson_benchmark.pyd +0 -0
- ssrjson_benchmark/benchmark_impl.py +100 -33
- {ssrjson_benchmark-0.0.4.dist-info → ssrjson_benchmark-0.0.5.dist-info}/METADATA +3 -24
- {ssrjson_benchmark-0.0.4.dist-info → ssrjson_benchmark-0.0.5.dist-info}/RECORD +8 -8
- {ssrjson_benchmark-0.0.4.dist-info → ssrjson_benchmark-0.0.5.dist-info}/WHEEL +0 -0
- {ssrjson_benchmark-0.0.4.dist-info → ssrjson_benchmark-0.0.5.dist-info}/licenses/LICENSE +0 -0
- {ssrjson_benchmark-0.0.4.dist-info → ssrjson_benchmark-0.0.5.dist-info}/top_level.txt +0 -0
ssrjson_benchmark/__main__.py
CHANGED
|
@@ -37,10 +37,17 @@ def main():
|
|
|
37
37
|
action="store_true",
|
|
38
38
|
)
|
|
39
39
|
parser.add_argument(
|
|
40
|
-
"--process-
|
|
41
|
-
help="Total process
|
|
40
|
+
"--process-gigabytes",
|
|
41
|
+
help="Total process gigabytes per test, default 0.1 (float)",
|
|
42
42
|
required=False,
|
|
43
|
-
default=
|
|
43
|
+
default=0.1,
|
|
44
|
+
type=float,
|
|
45
|
+
)
|
|
46
|
+
parser.add_argument(
|
|
47
|
+
"--bin-process-megabytes",
|
|
48
|
+
help="Maximum bytes to process per read for binary formats, default 32 (int)",
|
|
49
|
+
required=False,
|
|
50
|
+
default=32,
|
|
44
51
|
type=int,
|
|
45
52
|
)
|
|
46
53
|
parser.add_argument(
|
|
@@ -70,7 +77,14 @@ def main():
|
|
|
70
77
|
result = parse_file_result(result_)
|
|
71
78
|
file = args.file.split("/")[-1]
|
|
72
79
|
else:
|
|
73
|
-
|
|
80
|
+
process_bytes = int(args.process_gigabytes * 1024 * 1024 * 1024)
|
|
81
|
+
bin_process_bytes = args.bin_process_megabytes * 1024 * 1024
|
|
82
|
+
if process_bytes <= 0 or bin_process_bytes <= 0:
|
|
83
|
+
print("process-gigabytes and bin-process-megabytes must be positive.")
|
|
84
|
+
sys.exit(1)
|
|
85
|
+
result, file = run_benchmark(
|
|
86
|
+
benchmark_files_dir, process_bytes, bin_process_bytes
|
|
87
|
+
)
|
|
74
88
|
file = file.split("/")[-1]
|
|
75
89
|
|
|
76
90
|
if args.markdown:
|
|
Binary file
|
|
@@ -2,6 +2,7 @@ import gc
|
|
|
2
2
|
import io
|
|
3
3
|
import json
|
|
4
4
|
import math
|
|
5
|
+
import multiprocessing
|
|
5
6
|
import os
|
|
6
7
|
import pathlib
|
|
7
8
|
import platform
|
|
@@ -43,6 +44,8 @@ LIBRARIES_COLORS = {
|
|
|
43
44
|
"ssrjson": "#fd8d3c",
|
|
44
45
|
}
|
|
45
46
|
|
|
47
|
+
MAX_BIN_BYTES_SIZE = 512 * 1024 * 1024 # 512MiB
|
|
48
|
+
|
|
46
49
|
|
|
47
50
|
class BenchmarkFunction:
|
|
48
51
|
def __init__(self, func: Callable, library_name: str) -> None:
|
|
@@ -65,11 +68,13 @@ class BenchmarkGroup:
|
|
|
65
68
|
|
|
66
69
|
|
|
67
70
|
# benchmarkers
|
|
68
|
-
def _benchmark(repeat_time: int, func, *args):
|
|
71
|
+
def _benchmark(repeat_time: int, times_per_bin: int, func, *args):
|
|
69
72
|
"""
|
|
70
73
|
Run repeat benchmark, with utf-8 cache.
|
|
71
74
|
returns time used (ns).
|
|
72
75
|
"""
|
|
76
|
+
# times_per_bin not used
|
|
77
|
+
# disable automatic GC
|
|
73
78
|
gc_was_enabled = _gc_prepare()
|
|
74
79
|
try:
|
|
75
80
|
# warm up
|
|
@@ -82,53 +87,62 @@ def _benchmark(repeat_time: int, func, *args):
|
|
|
82
87
|
gc.enable()
|
|
83
88
|
|
|
84
89
|
|
|
85
|
-
def _benchmark_unicode_arg(repeat_time: int, func, unicode: str):
|
|
90
|
+
def _benchmark_unicode_arg(repeat_time: int, times_per_bin: int, func, unicode: str):
|
|
86
91
|
"""
|
|
87
92
|
Run repeat benchmark, disabling utf-8 cache.
|
|
88
93
|
returns time used (ns).
|
|
89
94
|
"""
|
|
95
|
+
# disable automatic GC
|
|
90
96
|
gc_was_enabled = _gc_prepare()
|
|
91
97
|
try:
|
|
92
|
-
|
|
93
|
-
# prepare identical data, without sharing objects
|
|
94
|
-
warmup_data = _ssrjson_benchmark.copy_unicode_list_invalidate_cache(
|
|
95
|
-
unicode, warmup_size
|
|
96
|
-
)
|
|
97
|
-
benchmark_data = _ssrjson_benchmark.copy_unicode_list_invalidate_cache(
|
|
98
|
-
unicode, repeat_time
|
|
99
|
-
)
|
|
100
|
-
# warm up
|
|
101
|
-
for i in range(warmup_size):
|
|
102
|
-
_ssrjson_benchmark.run_object_benchmark(func, (warmup_data[i],))
|
|
98
|
+
times_left = repeat_time
|
|
103
99
|
total = 0
|
|
104
|
-
|
|
105
|
-
|
|
100
|
+
while times_left != 0:
|
|
101
|
+
cur_bin_size = min(times_left, times_per_bin)
|
|
102
|
+
times_left -= cur_bin_size
|
|
103
|
+
# prepare identical data, without sharing objects
|
|
104
|
+
benchmark_data = _ssrjson_benchmark.copy_unicode_list_invalidate_cache(
|
|
105
|
+
unicode, cur_bin_size + 1
|
|
106
|
+
)
|
|
107
|
+
# warm up
|
|
108
|
+
_ssrjson_benchmark.run_object_benchmark(func, (benchmark_data[0],))
|
|
109
|
+
#
|
|
110
|
+
for i in range(1, cur_bin_size + 1):
|
|
111
|
+
total += _ssrjson_benchmark.run_object_benchmark(
|
|
112
|
+
func, (benchmark_data[i],)
|
|
113
|
+
)
|
|
114
|
+
del benchmark_data
|
|
106
115
|
return total
|
|
107
116
|
finally:
|
|
108
117
|
if gc_was_enabled:
|
|
109
118
|
gc.enable()
|
|
110
119
|
|
|
111
120
|
|
|
112
|
-
def _benchmark_invalidate_dump_cache(
|
|
121
|
+
def _benchmark_invalidate_dump_cache(
|
|
122
|
+
repeat_time: int, times_per_bin: int, func, raw_bytes: bytes
|
|
123
|
+
):
|
|
113
124
|
"""
|
|
114
125
|
Invalidate utf-8 cache for the same input.
|
|
115
126
|
returns time used (ns).
|
|
116
127
|
"""
|
|
117
|
-
#
|
|
118
|
-
data_warmup = [json.loads(raw_bytes) for _ in range(10)]
|
|
119
|
-
data = [json.loads(raw_bytes) for _ in range(repeat_time)]
|
|
120
|
-
# disable GC
|
|
128
|
+
# disable automatic GC
|
|
121
129
|
gc_was_enabled = _gc_prepare()
|
|
122
130
|
try:
|
|
123
|
-
|
|
124
|
-
for i in range(10):
|
|
125
|
-
new_args = (data_warmup[i],)
|
|
126
|
-
_ssrjson_benchmark.run_object_benchmark(func, new_args)
|
|
127
|
-
#
|
|
131
|
+
times_left = repeat_time
|
|
128
132
|
total = 0
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
133
|
+
while times_left != 0:
|
|
134
|
+
cur_bin_size = min(times_left, times_per_bin)
|
|
135
|
+
times_left -= cur_bin_size
|
|
136
|
+
# prepare identical data, without sharing objects
|
|
137
|
+
benchmark_data = [json.loads(raw_bytes) for _ in range(cur_bin_size + 1)]
|
|
138
|
+
# warm up
|
|
139
|
+
_ssrjson_benchmark.run_object_benchmark(func, (benchmark_data[0],))
|
|
140
|
+
#
|
|
141
|
+
for i in range(1, cur_bin_size + 1):
|
|
142
|
+
total += _ssrjson_benchmark.run_object_benchmark(
|
|
143
|
+
func, (benchmark_data[i],)
|
|
144
|
+
)
|
|
145
|
+
del benchmark_data
|
|
132
146
|
return total
|
|
133
147
|
finally:
|
|
134
148
|
if gc_was_enabled:
|
|
@@ -266,9 +280,17 @@ def _get_processed_size(func: Callable, input_data, is_dumps):
|
|
|
266
280
|
return size
|
|
267
281
|
|
|
268
282
|
|
|
283
|
+
def benchmark_multiprocess_wrapper(
|
|
284
|
+
benchmarker, args, result_multiprocess_queue: multiprocessing.Queue
|
|
285
|
+
):
|
|
286
|
+
ret = benchmarker(*args)
|
|
287
|
+
result_multiprocess_queue.put(ret)
|
|
288
|
+
|
|
289
|
+
|
|
269
290
|
def _run_benchmark(
|
|
270
291
|
cur_result_file: BenchmarkResultPerFile,
|
|
271
292
|
repeat_times: int,
|
|
293
|
+
times_per_bin: int,
|
|
272
294
|
input_data: str | bytes,
|
|
273
295
|
benchmark_group: BenchmarkGroup,
|
|
274
296
|
):
|
|
@@ -277,10 +299,26 @@ def _run_benchmark(
|
|
|
277
299
|
|
|
278
300
|
input_data = benchmark_group.input_preprocessor(input_data)
|
|
279
301
|
|
|
302
|
+
result_multiprocess_queue = multiprocessing.Queue() # type: ignore
|
|
303
|
+
|
|
280
304
|
for benchmark_target in benchmark_group.functions:
|
|
281
|
-
|
|
282
|
-
|
|
305
|
+
prefix = f"[{benchmark_target.library_name}][{benchmark_group.group_name}]"
|
|
306
|
+
print(
|
|
307
|
+
prefix
|
|
308
|
+
+ (" " * max(0, 40 - len(prefix)))
|
|
309
|
+
+ f"repeat_times={repeat_times} times_per_bin={times_per_bin}"
|
|
283
310
|
)
|
|
311
|
+
p = multiprocessing.Process(
|
|
312
|
+
target=benchmark_multiprocess_wrapper,
|
|
313
|
+
args=(
|
|
314
|
+
benchmark_group.benchmarker,
|
|
315
|
+
(repeat_times, times_per_bin, benchmark_target.func, input_data),
|
|
316
|
+
result_multiprocess_queue,
|
|
317
|
+
),
|
|
318
|
+
)
|
|
319
|
+
p.start()
|
|
320
|
+
p.join()
|
|
321
|
+
speed = result_multiprocess_queue.get()
|
|
284
322
|
cur_lib = cur_target[benchmark_target.library_name]
|
|
285
323
|
cur_lib.speed = speed
|
|
286
324
|
|
|
@@ -308,6 +346,7 @@ def _run_file_benchmark(
|
|
|
308
346
|
benchmark_libraries: dict[str, BenchmarkGroup],
|
|
309
347
|
file: pathlib.Path,
|
|
310
348
|
process_bytes: int,
|
|
349
|
+
bin_process_bytes: int,
|
|
311
350
|
):
|
|
312
351
|
print(f"Running benchmark for {file.name}")
|
|
313
352
|
with open(file, "rb") as f:
|
|
@@ -316,14 +355,19 @@ def _run_file_benchmark(
|
|
|
316
355
|
base_file_name = os.path.basename(file)
|
|
317
356
|
cur_result_file = BenchmarkResultPerFile()
|
|
318
357
|
cur_result_file.byte_size = bytes_size = len(raw_bytes)
|
|
358
|
+
if bytes_size == 0:
|
|
359
|
+
raise RuntimeError(f"File {file} is empty.")
|
|
319
360
|
kind, str_size, is_ascii, _ = _ssrjson_benchmark.inspect_pyunicode(raw)
|
|
320
361
|
cur_result_file.pyunicode_size = str_size
|
|
321
362
|
cur_result_file.pyunicode_kind = kind
|
|
322
363
|
cur_result_file.pyunicode_is_ascii = is_ascii
|
|
323
364
|
repeat_times = int((process_bytes + bytes_size - 1) // bytes_size)
|
|
365
|
+
times_per_bin = max(1, bin_process_bytes // bytes_size)
|
|
324
366
|
|
|
325
367
|
for benchmark_group in benchmark_libraries.values():
|
|
326
|
-
_run_benchmark(
|
|
368
|
+
_run_benchmark(
|
|
369
|
+
cur_result_file, repeat_times, times_per_bin, raw_bytes, benchmark_group
|
|
370
|
+
)
|
|
327
371
|
return base_file_name, cur_result_file
|
|
328
372
|
|
|
329
373
|
|
|
@@ -732,11 +776,32 @@ def parse_file_result(j):
|
|
|
732
776
|
return BenchmarkFinalResult.parse(j)
|
|
733
777
|
|
|
734
778
|
|
|
735
|
-
def
|
|
779
|
+
def is_unix_except_macos():
|
|
780
|
+
system = platform.system()
|
|
781
|
+
return system in ("Linux", "AIX", "FreeBSD")
|
|
782
|
+
|
|
783
|
+
|
|
784
|
+
def _set_multiprocessing_start_method():
|
|
785
|
+
try:
|
|
786
|
+
multiprocessing.set_start_method("fork")
|
|
787
|
+
except RuntimeError as e:
|
|
788
|
+
if "context has already been set" not in str(e):
|
|
789
|
+
raise
|
|
790
|
+
|
|
791
|
+
|
|
792
|
+
def run_benchmark(
|
|
793
|
+
files: list[pathlib.Path],
|
|
794
|
+
process_bytes: int,
|
|
795
|
+
bin_process_bytes: int,
|
|
796
|
+
):
|
|
736
797
|
"""
|
|
737
798
|
Generate a JSON result of benchmark.
|
|
738
799
|
Also returns a result object.
|
|
739
800
|
"""
|
|
801
|
+
# Set multiprocessing start method to fork, if Python version is 3.14+ on Unix
|
|
802
|
+
if sys.version_info >= (3, 14) and is_unix_except_macos():
|
|
803
|
+
_set_multiprocessing_start_method()
|
|
804
|
+
|
|
740
805
|
file = _get_real_output_file_name()
|
|
741
806
|
|
|
742
807
|
result = BenchmarkFinalResult()
|
|
@@ -747,7 +812,9 @@ def run_benchmark(files: list[pathlib.Path], process_bytes: int = int(1e8)):
|
|
|
747
812
|
result.catagories = sorted(list(benchmark_libraries.keys()))
|
|
748
813
|
|
|
749
814
|
for bench_file in files:
|
|
750
|
-
k, v = _run_file_benchmark(
|
|
815
|
+
k, v = _run_file_benchmark(
|
|
816
|
+
benchmark_libraries, bench_file, process_bytes, bin_process_bytes
|
|
817
|
+
)
|
|
751
818
|
result.results[k] = v
|
|
752
819
|
output_result = result.dumps()
|
|
753
820
|
|
|
@@ -1,30 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ssrjson-benchmark
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.5
|
|
4
4
|
Summary: benchmark of ssrJSON
|
|
5
5
|
Author-email: Eritque Arcus <eritque-arcus@ikuyo.dev>, Antares <antares0982@gmail.com>
|
|
6
|
-
License: MIT
|
|
7
|
-
|
|
8
|
-
Copyright (c) 2025 Eritque arcus
|
|
9
|
-
|
|
10
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
-
in the Software without restriction, including without limitation the rights
|
|
13
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
-
furnished to do so, subject to the following conditions:
|
|
16
|
-
|
|
17
|
-
The above copyright notice and this permission notice shall be included in all
|
|
18
|
-
copies or substantial portions of the Software.
|
|
19
|
-
|
|
20
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
-
SOFTWARE.
|
|
27
|
-
|
|
6
|
+
License-Expression: MIT
|
|
28
7
|
Project-URL: Homepage, https://github.com/Nambers/ssrJSON-benchmark
|
|
29
8
|
Project-URL: Issues, https://github.com/Nambers/ssrJSON-benchmark/issues
|
|
30
9
|
Project-URL: Repository, https://github.com/Nambers/ssrJSON-benchmark.git
|
|
@@ -35,7 +14,7 @@ Classifier: Intended Audience :: Developers
|
|
|
35
14
|
Classifier: Topic :: System :: Benchmark
|
|
36
15
|
Classifier: Programming Language :: Python :: 3
|
|
37
16
|
Classifier: Operating System :: OS Independent
|
|
38
|
-
Requires-Python: >=3.
|
|
17
|
+
Requires-Python: >=3.10
|
|
39
18
|
Description-Content-Type: text/markdown
|
|
40
19
|
License-File: LICENSE
|
|
41
20
|
Requires-Dist: ssrjson
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
ssrjson_benchmark/__init__.py,sha256=i4lVJ3CRKTxfxGyXREUi5OUesvmwWm8fEkcME7usGpk,380
|
|
2
|
-
ssrjson_benchmark/__main__.py,sha256=
|
|
3
|
-
ssrjson_benchmark/_ssrjson_benchmark.pyd,sha256=
|
|
4
|
-
ssrjson_benchmark/benchmark_impl.py,sha256=
|
|
2
|
+
ssrjson_benchmark/__main__.py,sha256=kCW5S5avgZcb2W4I4Mlb0ytXCF9epg4P441JEJywxac,2901
|
|
3
|
+
ssrjson_benchmark/_ssrjson_benchmark.pyd,sha256=_C1QheoqYeX-m70WYK2NgZLWvaxiLxmrS-JiUgjdROk,13312
|
|
4
|
+
ssrjson_benchmark/benchmark_impl.py,sha256=rsrRX5FP6XFvcXybrL9rAjDLlgAkzSRpvOlivRJAs_4,25953
|
|
5
5
|
ssrjson_benchmark/result_types.py,sha256=_rrM4Lz4-8fJhtHQ9tOF2tr6dRc-FU4CmabodUO_hk8,2379
|
|
6
6
|
ssrjson_benchmark/template.md,sha256=ZRM36XR-EB2Up0BkRiE1IL7GmlaozwNQ-S1TFw_hnwM,272
|
|
7
7
|
ssrjson_benchmark/_files/MotionsQuestionsAnswersQuestions2016.json,sha256=EqcdpROZfEPUSuOq1PXmDY3WXQqPvNYmvqAYF_30ICQ,10323246
|
|
@@ -16,8 +16,8 @@ ssrjson_benchmark/_files/simple_object_zh.json,sha256=uPOPBRqqFwxxu1Sh0DMoe1q9o3
|
|
|
16
16
|
ssrjson_benchmark/_files/truenull.json,sha256=enl_cy6qWa8b7bdVpx3-e0k6X9BFe_aCPot1rEquGiU,12000
|
|
17
17
|
ssrjson_benchmark/_files/tweet.json,sha256=nd_aAjLwHMcvzh_4ntacdK6S1Dlz65bcsPEzS-9MEtc,5128
|
|
18
18
|
ssrjson_benchmark/_files/twitter.json,sha256=apbJI9QLVdnFuler9fbDV8AyK9Tz2AuygSujmeMKn2o,770627
|
|
19
|
-
ssrjson_benchmark-0.0.
|
|
20
|
-
ssrjson_benchmark-0.0.
|
|
21
|
-
ssrjson_benchmark-0.0.
|
|
22
|
-
ssrjson_benchmark-0.0.
|
|
23
|
-
ssrjson_benchmark-0.0.
|
|
19
|
+
ssrjson_benchmark-0.0.5.dist-info/licenses/LICENSE,sha256=grt4_GrNwicUFuNLSSbvvdGq2fFW6s81CFBO9_mtQbg,1091
|
|
20
|
+
ssrjson_benchmark-0.0.5.dist-info/METADATA,sha256=c5fakyL6f7a7QLTAl6R9KuPi5JVZac7Xcai-l8f2ET0,4641
|
|
21
|
+
ssrjson_benchmark-0.0.5.dist-info/WHEEL,sha256=KUuBC6lxAbHCKilKua8R9W_TM71_-9Sg5uEP3uDWcoU,101
|
|
22
|
+
ssrjson_benchmark-0.0.5.dist-info/top_level.txt,sha256=l1O9IjI1lR5DczhKv9O-GeItgq5HZySDOI5KjfFfvq8,37
|
|
23
|
+
ssrjson_benchmark-0.0.5.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|