ssrjson-benchmark 0.0.4__cp311-cp311-win_amd64.whl → 0.0.6__cp311-cp311-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:
@@ -269,6 +283,7 @@ def _get_processed_size(func: Callable, input_data, is_dumps):
269
283
  def _run_benchmark(
270
284
  cur_result_file: BenchmarkResultPerFile,
271
285
  repeat_times: int,
286
+ times_per_bin: int,
272
287
  input_data: str | bytes,
273
288
  benchmark_group: BenchmarkGroup,
274
289
  ):
@@ -278,8 +293,14 @@ def _run_benchmark(
278
293
  input_data = benchmark_group.input_preprocessor(input_data)
279
294
 
280
295
  for benchmark_target in benchmark_group.functions:
296
+ prefix = f"[{benchmark_target.library_name}][{benchmark_group.group_name}]"
297
+ print(
298
+ prefix
299
+ + (" " * max(0, 40 - len(prefix)))
300
+ + f"repeat_times={repeat_times} times_per_bin={times_per_bin}"
301
+ )
281
302
  speed = benchmark_group.benchmarker(
282
- repeat_times, benchmark_target.func, input_data
303
+ repeat_times, times_per_bin, benchmark_target.func, input_data
283
304
  )
284
305
  cur_lib = cur_target[benchmark_target.library_name]
285
306
  cur_lib.speed = speed
@@ -308,6 +329,7 @@ def _run_file_benchmark(
308
329
  benchmark_libraries: dict[str, BenchmarkGroup],
309
330
  file: pathlib.Path,
310
331
  process_bytes: int,
332
+ bin_process_bytes: int,
311
333
  ):
312
334
  print(f"Running benchmark for {file.name}")
313
335
  with open(file, "rb") as f:
@@ -316,14 +338,19 @@ def _run_file_benchmark(
316
338
  base_file_name = os.path.basename(file)
317
339
  cur_result_file = BenchmarkResultPerFile()
318
340
  cur_result_file.byte_size = bytes_size = len(raw_bytes)
341
+ if bytes_size == 0:
342
+ raise RuntimeError(f"File {file} is empty.")
319
343
  kind, str_size, is_ascii, _ = _ssrjson_benchmark.inspect_pyunicode(raw)
320
344
  cur_result_file.pyunicode_size = str_size
321
345
  cur_result_file.pyunicode_kind = kind
322
346
  cur_result_file.pyunicode_is_ascii = is_ascii
323
347
  repeat_times = int((process_bytes + bytes_size - 1) // bytes_size)
348
+ times_per_bin = max(1, bin_process_bytes // bytes_size)
324
349
 
325
350
  for benchmark_group in benchmark_libraries.values():
326
- _run_benchmark(cur_result_file, repeat_times, raw_bytes, benchmark_group)
351
+ _run_benchmark(
352
+ cur_result_file, repeat_times, times_per_bin, raw_bytes, benchmark_group
353
+ )
327
354
  return base_file_name, cur_result_file
328
355
 
329
356
 
@@ -732,11 +759,32 @@ def parse_file_result(j):
732
759
  return BenchmarkFinalResult.parse(j)
733
760
 
734
761
 
735
- def run_benchmark(files: list[pathlib.Path], process_bytes: int = int(1e8)):
762
+ def is_unix_except_macos():
763
+ system = platform.system()
764
+ return system in ("Linux", "AIX", "FreeBSD")
765
+
766
+
767
+ def _set_multiprocessing_start_method():
768
+ try:
769
+ multiprocessing.set_start_method("fork")
770
+ except RuntimeError as e:
771
+ if "context has already been set" not in str(e):
772
+ raise
773
+
774
+
775
+ def run_benchmark(
776
+ files: list[pathlib.Path],
777
+ process_bytes: int,
778
+ bin_process_bytes: int,
779
+ ):
736
780
  """
737
781
  Generate a JSON result of benchmark.
738
782
  Also returns a result object.
739
783
  """
784
+ # Set multiprocessing start method to fork, if Python version is 3.14+ on Unix
785
+ if sys.version_info >= (3, 14) and is_unix_except_macos():
786
+ _set_multiprocessing_start_method()
787
+
740
788
  file = _get_real_output_file_name()
741
789
 
742
790
  result = BenchmarkFinalResult()
@@ -747,7 +795,9 @@ def run_benchmark(files: list[pathlib.Path], process_bytes: int = int(1e8)):
747
795
  result.catagories = sorted(list(benchmark_libraries.keys()))
748
796
 
749
797
  for bench_file in files:
750
- k, v = _run_file_benchmark(benchmark_libraries, bench_file, process_bytes)
798
+ k, v = _run_file_benchmark(
799
+ benchmark_libraries, bench_file, process_bytes, bin_process_bytes
800
+ )
751
801
  result.results[k] = v
752
802
  output_result = result.dumps()
753
803
 
@@ -1,30 +1,9 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ssrjson-benchmark
3
- Version: 0.0.4
3
+ Version: 0.0.6
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=kkVc77rzmZdRqzuPkhX1lB0AwUMCpTsStMsQfpcIYL0,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=pkJKLRBWIn6WpKP46_EcmyZLssCjE2Fot_oyYXygAr8,13312
4
+ ssrjson_benchmark/benchmark_impl.py,sha256=YgXaMpYkpApPvthuDQ8TGJoKDruSH46Lf6L_1QLWovU,25427
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=JLOMsP7F5qtkAkINx5UnzbFguf8CqZeraV8o04b0I8I,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.6.dist-info/licenses/LICENSE,sha256=grt4_GrNwicUFuNLSSbvvdGq2fFW6s81CFBO9_mtQbg,1091
20
+ ssrjson_benchmark-0.0.6.dist-info/METADATA,sha256=U20IW7AekyqgYTHaNIgFN9jgq6m7nm6KxLZCiIdwKHI,4641
21
+ ssrjson_benchmark-0.0.6.dist-info/WHEEL,sha256=JLOMsP7F5qtkAkINx5UnzbFguf8CqZeraV8o04b0I8I,101
22
+ ssrjson_benchmark-0.0.6.dist-info/top_level.txt,sha256=l1O9IjI1lR5DczhKv9O-GeItgq5HZySDOI5KjfFfvq8,37
23
+ ssrjson_benchmark-0.0.6.dist-info/RECORD,,