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.

@@ -37,10 +37,17 @@ def main():
37
37
  action="store_true",
38
38
  )
39
39
  parser.add_argument(
40
- "--process-bytes",
41
- help="Total process bytes per test, default 1e8",
40
+ "--process-gigabytes",
41
+ help="Total process gigabytes per test, default 0.1 (float)",
42
42
  required=False,
43
- default=1e8,
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
- result, file = run_benchmark(benchmark_files_dir, args.process_bytes)
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
- warmup_size = 100
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
- for i in range(repeat_time):
105
- total += _ssrjson_benchmark.run_object_benchmark(func, (benchmark_data[i],))
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(repeat_time: int, func, raw_bytes: bytes):
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
- # prepare identical data, without sharing objects
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
- # warm up
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
- for i in range(repeat_time):
130
- new_args = (data[i],)
131
- total += _ssrjson_benchmark.run_object_benchmark(func, new_args)
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
- speed = benchmark_group.benchmarker(
282
- repeat_times, benchmark_target.func, input_data
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(cur_result_file, repeat_times, raw_bytes, benchmark_group)
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 run_benchmark(files: list[pathlib.Path], process_bytes: int = int(1e8)):
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(benchmark_libraries, bench_file, process_bytes)
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.4
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 License
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.9
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=PQgkJRKuQT9NPQ3JZD7qyAbHhRKbh9UvkxOlXsJnITA,2312
3
- ssrjson_benchmark/_ssrjson_benchmark.pyd,sha256=Z15oFGhdAWs8RKyYngxiAFRcvUQvtbUZ-1FYsTHcQw0,13312
4
- ssrjson_benchmark/benchmark_impl.py,sha256=5yRsbhcB5jz1VC4wuNgI4BZndZVxogW3_obz9jC2OBA,23828
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.4.dist-info/licenses/LICENSE,sha256=grt4_GrNwicUFuNLSSbvvdGq2fFW6s81CFBO9_mtQbg,1091
20
- ssrjson_benchmark-0.0.4.dist-info/METADATA,sha256=9LlYrNP1-cBf3hP8WakHkcFLNVBNzwVNCT8JqFAji08,5885
21
- ssrjson_benchmark-0.0.4.dist-info/WHEEL,sha256=KUuBC6lxAbHCKilKua8R9W_TM71_-9Sg5uEP3uDWcoU,101
22
- ssrjson_benchmark-0.0.4.dist-info/top_level.txt,sha256=l1O9IjI1lR5DczhKv9O-GeItgq5HZySDOI5KjfFfvq8,37
23
- ssrjson_benchmark-0.0.4.dist-info/RECORD,,
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,,