From 98cbc4e77090580982a11eceef1740aafbb58ccc Mon Sep 17 00:00:00 2001 From: Andrija Kolic Date: Mon, 5 Jan 2026 14:40:36 +0100 Subject: [PATCH] Port 'pyperformance' and 'numpy' benchmarks to PolyBench. --- .../python/micro/numpy/LICENSE.txt | 30 + .../python/micro/numpy/README.md | 155 ++ .../numpy/bench_core.Core.time_arange_100.py | 83 + .../numpy/bench_core.Core.time_array_1.py | 83 + .../numpy/bench_core.Core.time_array_empty.py | 83 + ...ench_core.Core.time_array_float64_l1000.py | 83 + .../bench_core.Core.time_array_float_l1000.py | 83 + ..._core.Core.time_array_float_l1000_dtype.py | 83 + .../bench_core.Core.time_array_int_l1000.py | 83 + .../numpy/bench_core.Core.time_array_l.py | 83 + .../numpy/bench_core.Core.time_array_l1.py | 83 + .../numpy/bench_core.Core.time_array_l100.py | 83 + .../bench_core.Core.time_array_l_view.py | 83 + .../numpy/bench_core.Core.time_can_cast.py | 83 + ...bench_core.Core.time_can_cast_same_kind.py | 83 + .../numpy/bench_core.Core.time_diag_l100.py | 83 + .../bench_core.Core.time_diagflat_l100.py | 83 + .../bench_core.Core.time_diagflat_l50_l50.py | 83 + .../numpy/bench_core.Core.time_dstack_l.py | 83 + .../numpy/bench_core.Core.time_empty_100.py | 83 + .../numpy/bench_core.Core.time_empty_like.py | 83 + .../numpy/bench_core.Core.time_eye_100.py | 83 + .../numpy/bench_core.Core.time_eye_3000.py | 83 + .../numpy/bench_core.Core.time_hstack_l.py | 83 + .../bench_core.Core.time_identity_100.py | 83 + .../bench_core.Core.time_identity_3000.py | 83 + .../numpy/bench_core.Core.time_ones_100.py | 83 + .../bench_core.Core.time_tril_indices_500.py | 83 + .../numpy/bench_core.Core.time_tril_l10x10.py | 83 + .../bench_core.Core.time_triu_indices_500.py | 83 + .../numpy/bench_core.Core.time_triu_l10x10.py | 83 + .../numpy/bench_core.Core.time_vstack_l.py | 83 + .../numpy/bench_core.Core.time_zeros_100.py | 83 + .../bench_core.CorrConv.time_convolve.py | 87 + .../bench_core.CorrConv.time_correlate.py | 87 + ...ch_core.CountNonzero.time_count_nonzero.py | 87 + ...re.CountNonzero.time_count_nonzero_axis.py | 87 + ...ntNonzero.time_count_nonzero_multi_axis.py | 87 + .../numpy/bench_core.Indices.time_indices.py | 82 + .../bench_core.PackBits.time_packbits.py | 85 + ...bench_core.PackBits.time_packbits_axis0.py | 85 + ...bench_core.PackBits.time_packbits_axis1.py | 85 + ...ench_core.PackBits.time_packbits_little.py | 85 + .../numpy/bench_core.StatsMethods.time_max.py | 86 + .../bench_core.StatsMethods.time_mean.py | 86 + .../numpy/bench_core.StatsMethods.time_min.py | 86 + .../bench_core.StatsMethods.time_prod.py | 86 + .../numpy/bench_core.StatsMethods.time_std.py | 86 + .../numpy/bench_core.StatsMethods.time_sum.py | 86 + .../numpy/bench_core.StatsMethods.time_var.py | 86 + .../bench_core.Temporaries.time_large.py | 83 + .../bench_core.Temporaries.time_large2.py | 83 + .../numpy/bench_core.Temporaries.time_mid.py | 83 + .../numpy/bench_core.Temporaries.time_mid2.py | 83 + .../bench_core.UnpackBits.time_unpackbits.py | 83 + ...h_core.UnpackBits.time_unpackbits_axis0.py | 83 + ...h_core.UnpackBits.time_unpackbits_axis1.py | 83 + ...UnpackBits.time_unpackbits_axis1_little.py | 83 + ..._core.UnpackBits.time_unpackbits_little.py | 83 + .../python/micro/numpy/bench_core.py | 259 +++ .../python/micro/numpy/common.py | 224 ++ .../python/micro/pyperformance/LICENSE.txt | 20 + .../python/micro/pyperformance/README.md | 1234 +++++++++++ .../python/micro/pyperformance/bm_pathlib.py | 76 + .../python/micro/pyperformance/bm_pickle.py | 287 +++ .../python/micro/pyperformance/bm_richards.py | 434 ++++ .../python/micro/pyperformance/chaos.py | 314 +++ .../pyperformance/data/interpreter.tar.bz2 | Bin 0 -> 67562 bytes .../micro/pyperformance/data/telco-bench.b | Bin 0 -> 160000 bytes .../python/micro/pyperformance/fannkuch.py | 66 + .../python/micro/pyperformance/float.py | 70 + .../python/micro/pyperformance/go.py | 469 +++++ .../python/micro/pyperformance/hexiom.py | 673 ++++++ .../python/micro/pyperformance/json_dumps.py | 69 + .../python/micro/pyperformance/json_loads.py | 115 ++ .../micro/pyperformance/meteor_contest.py | 231 +++ .../python/micro/pyperformance/nbody.py | 167 ++ .../python/micro/pyperformance/nqueens.py | 72 + .../python/micro/pyperformance/pickle_dict.py | 28 + .../python/micro/pyperformance/pickle_list.py | 28 + .../python/micro/pyperformance/pidigits.py | 81 + .../python/micro/pyperformance/pyflate.py | 676 +++++++ .../micro/pyperformance/regex_compile.py | 83 + .../python/micro/pyperformance/regex_dna.py | 239 +++ .../micro/pyperformance/regex_effbot.py | 183 ++ .../python/micro/pyperformance/regex_v8.py | 1798 +++++++++++++++++ .../python/micro/pyperformance/scimark.py | 414 ++++ .../micro/pyperformance/spectral_norm.py | 81 + .../python/micro/pyperformance/telco.py | 101 + .../micro/pyperformance/unpack_sequence.py | 466 +++++ .../python/micro/pyperformance/unpickle.py | 28 + .../micro/pyperformance/unpickle_list.py | 28 + mx.graalpython/mx_graalpython.py | 3 + mx.graalpython/mx_graalpython_benchmark.py | 14 +- .../polybench-stable-run-config.json | 425 ++++ mx.graalpython/suite.py | 98 + 96 files changed, 14511 insertions(+), 7 deletions(-) create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/LICENSE.txt create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/README.md create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_arange_100.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_array_1.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_array_empty.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_array_float64_l1000.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_array_float_l1000.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_array_float_l1000_dtype.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_array_int_l1000.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_array_l.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_array_l1.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_array_l100.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_array_l_view.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_can_cast.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_can_cast_same_kind.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_diag_l100.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_diagflat_l100.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_diagflat_l50_l50.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_dstack_l.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_empty_100.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_empty_like.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_eye_100.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_eye_3000.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_hstack_l.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_identity_100.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_identity_3000.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_ones_100.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_tril_indices_500.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_tril_l10x10.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_triu_indices_500.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_triu_l10x10.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_vstack_l.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_zeros_100.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.CorrConv.time_convolve.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.CorrConv.time_correlate.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.CountNonzero.time_count_nonzero.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.CountNonzero.time_count_nonzero_axis.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.CountNonzero.time_count_nonzero_multi_axis.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Indices.time_indices.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.PackBits.time_packbits.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.PackBits.time_packbits_axis0.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.PackBits.time_packbits_axis1.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.PackBits.time_packbits_little.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.StatsMethods.time_max.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.StatsMethods.time_mean.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.StatsMethods.time_min.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.StatsMethods.time_prod.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.StatsMethods.time_std.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.StatsMethods.time_sum.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.StatsMethods.time_var.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Temporaries.time_large.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Temporaries.time_large2.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Temporaries.time_mid.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Temporaries.time_mid2.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.UnpackBits.time_unpackbits.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.UnpackBits.time_unpackbits_axis0.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.UnpackBits.time_unpackbits_axis1.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.UnpackBits.time_unpackbits_axis1_little.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.UnpackBits.time_unpackbits_little.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/common.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/LICENSE.txt create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/README.md create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/bm_pathlib.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/bm_pickle.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/bm_richards.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/chaos.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/data/interpreter.tar.bz2 create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/data/telco-bench.b create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/fannkuch.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/float.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/go.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/hexiom.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/json_dumps.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/json_loads.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/meteor_contest.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/nbody.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/nqueens.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/pickle_dict.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/pickle_list.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/pidigits.py create mode 100755 graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/pyflate.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/regex_compile.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/regex_dna.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/regex_effbot.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/regex_v8.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/scimark.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/spectral_norm.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/telco.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/unpack_sequence.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/unpickle.py create mode 100644 graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/unpickle_list.py diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/LICENSE.txt b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/LICENSE.txt new file mode 100644 index 0000000000..74b2da5e3f --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/LICENSE.txt @@ -0,0 +1,30 @@ +Copyright (c) 2005-2025, NumPy Developers. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * Neither the name of the NumPy Developers nor the names of any + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/README.md b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/README.md new file mode 100644 index 0000000000..0093444ebd --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/README.md @@ -0,0 +1,155 @@ +# Numpy benchmark port process for benchmarking with the PolyBench harness + +## Brief explanation + +These PolyBench benchmarks have been manually generated for the file `bench_core.py` +that was copied from the `numpy` repository. +Each benchmark file maps 1:1 to a `test_*` method of a `Benchmark` extending class +inside `bench_core.py` and the files are named following the pattern of `--.py` +- e.g. the PolyBench benchmark file `bench_core.Core.time_array_1.py` corresponds to +the `time_array_1` method of the `Core` class which is defined in the `bench_core.py` file. + +If required, the imported set of benchmarks could be expanded to other numpy benchmarks analogously. + +## Version information + +Version: 1.26.4 +Source repository: https://github.com/numpy/numpy + +The version was chosen to align with the one used in `graalpython/mx.graalpython/mx_graalpython_python_benchmarks.py::NumPySuite`. + +## Files sourced from the numpy project + +### bench_core.py +Original file path: numpy/benchmarks/benchmarks/bench_core.py +Changes made to the original file, as reported by the `diff` tool: +``` +1,2c1,2 +< from .common import Benchmark +< +--- +> import sys +> import os +3a4,5 +> sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +> from common import Benchmark +4a7,8 +> # Ensure we have numpy version info in the logs +> print(f"Using numpy version '{np.__version__}'") +``` + +### common.py +Original file path: numpy/benchmarks/benchmarks/common.py +No modifications made. + +### License.txt +The BSD 3-clause license copied from the numpy repository. + +## Original files necessary for benchmarking with the PolyBench harness + +### `--.py` files +These are new files that do not have a corresponding match in the numpy repository. +They are thus licensed under the Oracle UPL license used elsewhere in this repository. +These files are generated to conform to the expectations of the PolyBench harness. +These files were generated with the help of a generative AI model using the following pattern: +``` +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +LOOP_COUNT = + = None + + +def setup(): + from import + global + = () + .setup() + + +def __benchmark__(): + # Original workload + .() + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return [".py", "common.py"] + +``` +Where: +* `` is a global variable that stores the instance of the benchmark class. +* `` is the name of the benchmark file (without the extension, e.g. `bench_core`). +* `` is the benchmark class (e.g. `Core`). +* `` is the benchmark method (e.g. `time_array_1`). +* `` is a number tweaked to ensure a workload long enough to minimize noise. +The value was initially set by the AI model and subsequently tweaked by hand. +The value was tweaked so that the benchmark executes somewhere in the range between 10ms and 1s. + +This template is not exhaustive and is provided for the purpose of facilitating maintenance. +There are multiple edge-cases one has to consider when generating a benchmark file: +* The benchmark class might not implement the `setup` method. +* The benchmark method might require arguments to be passed. +In such cases, the values were chosen from the `params` field of the benchmark class and stored +as global constants next to the `LOOP_COUNT` constant. diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_arange_100.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_arange_100.py new file mode 100644 index 0000000000..4e35d7a9df --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_arange_100.py @@ -0,0 +1,83 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +LOOP_COUNT = 100000 +_core = None + + +def setup(): + from bench_core import Core + global _core + _core = Core() + _core.setup() + + +def __benchmark__(): + # Original workload + _core.time_arange_100() + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_array_1.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_array_1.py new file mode 100644 index 0000000000..c194635129 --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_array_1.py @@ -0,0 +1,83 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +LOOP_COUNT = 1_000_000 +_core = None + + +def setup(): + from bench_core import Core + global _core + _core = Core() + _core.setup() + + +def __benchmark__(): + # Original workload + _core.time_array_1() + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_array_empty.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_array_empty.py new file mode 100644 index 0000000000..d45537b0e7 --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_array_empty.py @@ -0,0 +1,83 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +LOOP_COUNT = 1_000_000 +_core = None + + +def setup(): + from bench_core import Core + global _core + _core = Core() + _core.setup() + + +def __benchmark__(): + # Original workload + _core.time_array_empty() + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_array_float64_l1000.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_array_float64_l1000.py new file mode 100644 index 0000000000..921ac4d649 --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_array_float64_l1000.py @@ -0,0 +1,83 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +LOOP_COUNT = 1000 +_core = None + + +def setup(): + from bench_core import Core + global _core + _core = Core() + _core.setup() + + +def __benchmark__(): + # Original workload + _core.time_array_float64_l1000() + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_array_float_l1000.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_array_float_l1000.py new file mode 100644 index 0000000000..7156a80e3f --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_array_float_l1000.py @@ -0,0 +1,83 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +LOOP_COUNT = 1000 +_core = None + + +def setup(): + from bench_core import Core + global _core + _core = Core() + _core.setup() + + +def __benchmark__(): + # Original workload + _core.time_array_float_l1000() + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_array_float_l1000_dtype.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_array_float_l1000_dtype.py new file mode 100644 index 0000000000..2d6b8b510b --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_array_float_l1000_dtype.py @@ -0,0 +1,83 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +LOOP_COUNT = 1000 +_core = None + + +def setup(): + from bench_core import Core + global _core + _core = Core() + _core.setup() + + +def __benchmark__(): + # Original workload + _core.time_array_float_l1000_dtype() + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_array_int_l1000.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_array_int_l1000.py new file mode 100644 index 0000000000..7d1335ea9b --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_array_int_l1000.py @@ -0,0 +1,83 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +LOOP_COUNT = 1000 +_core = None + + +def setup(): + from bench_core import Core + global _core + _core = Core() + _core.setup() + + +def __benchmark__(): + # Original workload + _core.time_array_int_l1000() + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_array_l.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_array_l.py new file mode 100644 index 0000000000..038ce95126 --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_array_l.py @@ -0,0 +1,83 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +LOOP_COUNT = 100000 +_core = None + + +def setup(): + from bench_core import Core + global _core + _core = Core() + _core.setup() + + +def __benchmark__(): + # Original workload + _core.time_array_l() + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_array_l1.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_array_l1.py new file mode 100644 index 0000000000..7292875851 --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_array_l1.py @@ -0,0 +1,83 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +LOOP_COUNT = 1000000 +_core = None + + +def setup(): + from bench_core import Core + global _core + _core = Core() + _core.setup() + + +def __benchmark__(): + # Original workload + _core.time_array_l1() + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_array_l100.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_array_l100.py new file mode 100644 index 0000000000..43c4585ddb --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_array_l100.py @@ -0,0 +1,83 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +LOOP_COUNT = 10000 +_core = None + + +def setup(): + from bench_core import Core + global _core + _core = Core() + _core.setup() + + +def __benchmark__(): + # Original workload + _core.time_array_l100() + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_array_l_view.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_array_l_view.py new file mode 100644 index 0000000000..1a75b55ac8 --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_array_l_view.py @@ -0,0 +1,83 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +LOOP_COUNT = 100000 +_core = None + + +def setup(): + from bench_core import Core + global _core + _core = Core() + _core.setup() + + +def __benchmark__(): + # Original workload + _core.time_array_l_view() + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_can_cast.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_can_cast.py new file mode 100644 index 0000000000..b50cee1ca1 --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_can_cast.py @@ -0,0 +1,83 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +LOOP_COUNT = 1000000 +_core = None + + +def setup(): + from bench_core import Core + global _core + _core = Core() + _core.setup() + + +def __benchmark__(): + # Original workload + _core.time_can_cast() + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_can_cast_same_kind.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_can_cast_same_kind.py new file mode 100644 index 0000000000..ae28277ca6 --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_can_cast_same_kind.py @@ -0,0 +1,83 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +LOOP_COUNT = 1000000 +_core = None + + +def setup(): + from bench_core import Core + global _core + _core = Core() + _core.setup() + + +def __benchmark__(): + # Original workload + _core.time_can_cast_same_kind() + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_diag_l100.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_diag_l100.py new file mode 100644 index 0000000000..dde6f3c72c --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_diag_l100.py @@ -0,0 +1,83 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +LOOP_COUNT = 10000 +_core = None + + +def setup(): + from bench_core import Core + global _core + _core = Core() + _core.setup() + + +def __benchmark__(): + # Original workload + _core.time_diag_l100() + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_diagflat_l100.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_diagflat_l100.py new file mode 100644 index 0000000000..f7652a760f --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_diagflat_l100.py @@ -0,0 +1,83 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +LOOP_COUNT = 1000 +_core = None + + +def setup(): + from bench_core import Core + global _core + _core = Core() + _core.setup() + + +def __benchmark__(): + # Original workload + _core.time_diagflat_l100() + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_diagflat_l50_l50.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_diagflat_l50_l50.py new file mode 100644 index 0000000000..ae08e0539e --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_diagflat_l50_l50.py @@ -0,0 +1,83 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +LOOP_COUNT = 1000 +_core = None + + +def setup(): + from bench_core import Core + global _core + _core = Core() + _core.setup() + + +def __benchmark__(): + # Original workload + _core.time_diagflat_l50_l50() + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_dstack_l.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_dstack_l.py new file mode 100644 index 0000000000..3675b67682 --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_dstack_l.py @@ -0,0 +1,83 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +LOOP_COUNT = 10000 +_core = None + + +def setup(): + from bench_core import Core + global _core + _core = Core() + _core.setup() + + +def __benchmark__(): + # Original workload + _core.time_dstack_l() + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_empty_100.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_empty_100.py new file mode 100644 index 0000000000..4ebda680df --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_empty_100.py @@ -0,0 +1,83 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +LOOP_COUNT = 100000 +_core = None + + +def setup(): + from bench_core import Core + global _core + _core = Core() + _core.setup() + + +def __benchmark__(): + # Original workload + _core.time_empty_100() + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_empty_like.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_empty_like.py new file mode 100644 index 0000000000..48de92709a --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_empty_like.py @@ -0,0 +1,83 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +LOOP_COUNT = 100000 +_core = None + + +def setup(): + from bench_core import Core + global _core + _core = Core() + _core.setup() + + +def __benchmark__(): + # Original workload + _core.time_empty_like() + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_eye_100.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_eye_100.py new file mode 100644 index 0000000000..5487c7a40a --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_eye_100.py @@ -0,0 +1,83 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +LOOP_COUNT = 10000 +_core = None + + +def setup(): + from bench_core import Core + global _core + _core = Core() + _core.setup() + + +def __benchmark__(): + # Original workload + _core.time_eye_100() + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_eye_3000.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_eye_3000.py new file mode 100644 index 0000000000..2b5448c797 --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_eye_3000.py @@ -0,0 +1,83 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +LOOP_COUNT = 10 +_core = None + + +def setup(): + from bench_core import Core + global _core + _core = Core() + _core.setup() + + +def __benchmark__(): + # Original workload + _core.time_eye_3000() + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_hstack_l.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_hstack_l.py new file mode 100644 index 0000000000..45023a6837 --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_hstack_l.py @@ -0,0 +1,83 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +LOOP_COUNT = 10000 +_core = None + + +def setup(): + from bench_core import Core + global _core + _core = Core() + _core.setup() + + +def __benchmark__(): + # Original workload + _core.time_hstack_l() + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_identity_100.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_identity_100.py new file mode 100644 index 0000000000..ba1b5d0b99 --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_identity_100.py @@ -0,0 +1,83 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +LOOP_COUNT = 10000 +_core = None + + +def setup(): + from bench_core import Core + global _core + _core = Core() + _core.setup() + + +def __benchmark__(): + # Original workload + _core.time_identity_100() + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_identity_3000.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_identity_3000.py new file mode 100644 index 0000000000..55ae152590 --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_identity_3000.py @@ -0,0 +1,83 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +LOOP_COUNT = 10 +_core = None + + +def setup(): + from bench_core import Core + global _core + _core = Core() + _core.setup() + + +def __benchmark__(): + # Original workload + _core.time_identity_3000() + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_ones_100.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_ones_100.py new file mode 100644 index 0000000000..b367291978 --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_ones_100.py @@ -0,0 +1,83 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +LOOP_COUNT = 100000 +_core = None + + +def setup(): + from bench_core import Core + global _core + _core = Core() + _core.setup() + + +def __benchmark__(): + # Original workload + _core.time_ones_100() + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_tril_indices_500.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_tril_indices_500.py new file mode 100644 index 0000000000..5548196c32 --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_tril_indices_500.py @@ -0,0 +1,83 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +LOOP_COUNT = 100 +_core = None + + +def setup(): + from bench_core import Core + global _core + _core = Core() + _core.setup() + + +def __benchmark__(): + # Original workload + _core.time_tril_indices_500() + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_tril_l10x10.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_tril_l10x10.py new file mode 100644 index 0000000000..35efb90e1f --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_tril_l10x10.py @@ -0,0 +1,83 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +LOOP_COUNT = 10000 +_core = None + + +def setup(): + from bench_core import Core + global _core + _core = Core() + _core.setup() + + +def __benchmark__(): + # Original workload + _core.time_tril_l10x10() + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_triu_indices_500.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_triu_indices_500.py new file mode 100644 index 0000000000..4cf56bbe5c --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_triu_indices_500.py @@ -0,0 +1,83 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +LOOP_COUNT = 100 +_core = None + + +def setup(): + from bench_core import Core + global _core + _core = Core() + _core.setup() + + +def __benchmark__(): + # Original workload + _core.time_triu_indices_500() + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_triu_l10x10.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_triu_l10x10.py new file mode 100644 index 0000000000..9cbc8aa209 --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_triu_l10x10.py @@ -0,0 +1,83 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +LOOP_COUNT = 10000 +_core = None + + +def setup(): + from bench_core import Core + global _core + _core = Core() + _core.setup() + + +def __benchmark__(): + # Original workload + _core.time_triu_l10x10() + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_vstack_l.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_vstack_l.py new file mode 100644 index 0000000000..727d612ad1 --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_vstack_l.py @@ -0,0 +1,83 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +LOOP_COUNT = 10000 +_core = None + + +def setup(): + from bench_core import Core + global _core + _core = Core() + _core.setup() + + +def __benchmark__(): + # Original workload + _core.time_vstack_l() + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_zeros_100.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_zeros_100.py new file mode 100644 index 0000000000..dc8bdfbcc4 --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_zeros_100.py @@ -0,0 +1,83 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +LOOP_COUNT = 100000 +_core = None + + +def setup(): + from bench_core import Core + global _core + _core = Core() + _core.setup() + + +def __benchmark__(): + # Original workload + _core.time_zeros_100() + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.CorrConv.time_convolve.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.CorrConv.time_convolve.py new file mode 100644 index 0000000000..a56bbf974e --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.CorrConv.time_convolve.py @@ -0,0 +1,87 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +SIZE1 = int(1e5) +SIZE2 = int(1e4) +MODE = 'valid' + +LOOP_COUNT = 1 +_corrconv = None + + +def setup(): + from bench_core import CorrConv + global _corrconv + _corrconv = CorrConv() + _corrconv.setup(SIZE1, SIZE2, MODE) + + +def __benchmark__(): + # Original workload + _corrconv.time_convolve(SIZE1, SIZE2, MODE) + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.CorrConv.time_correlate.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.CorrConv.time_correlate.py new file mode 100644 index 0000000000..60b76b7d3c --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.CorrConv.time_correlate.py @@ -0,0 +1,87 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +SIZE1 = int(1e5) +SIZE2 = int(1e4) +MODE = 'valid' + +LOOP_COUNT = 1 +_corrconv = None + + +def setup(): + from bench_core import CorrConv + global _corrconv + _corrconv = CorrConv() + _corrconv.setup(SIZE1, SIZE2, MODE) + + +def __benchmark__(): + # Original workload + _corrconv.time_correlate(SIZE1, SIZE2, MODE) + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.CountNonzero.time_count_nonzero.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.CountNonzero.time_count_nonzero.py new file mode 100644 index 0000000000..a111364397 --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.CountNonzero.time_count_nonzero.py @@ -0,0 +1,87 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +NUMAXES = 3 +SIZE = 1_000_000 +DTYPE = bool + +LOOP_COUNT = 1000 +_countnonzero = None + + +def setup(): + from bench_core import CountNonzero + global _countnonzero + _countnonzero = CountNonzero() + _countnonzero.setup(NUMAXES, SIZE, DTYPE) + + +def __benchmark__(): + # Original workload + _countnonzero.time_count_nonzero(NUMAXES, SIZE, DTYPE) + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.CountNonzero.time_count_nonzero_axis.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.CountNonzero.time_count_nonzero_axis.py new file mode 100644 index 0000000000..a840160d81 --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.CountNonzero.time_count_nonzero_axis.py @@ -0,0 +1,87 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +NUMAXES = 3 +SIZE = 1_000_000 +DTYPE = bool + +LOOP_COUNT = 10 +_countnonzero = None + + +def setup(): + from bench_core import CountNonzero + global _countnonzero + _countnonzero = CountNonzero() + _countnonzero.setup(NUMAXES, SIZE, DTYPE) + + +def __benchmark__(): + # Original workload + _countnonzero.time_count_nonzero_axis(NUMAXES, SIZE, DTYPE) + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.CountNonzero.time_count_nonzero_multi_axis.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.CountNonzero.time_count_nonzero_multi_axis.py new file mode 100644 index 0000000000..8b59ef4f42 --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.CountNonzero.time_count_nonzero_multi_axis.py @@ -0,0 +1,87 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +NUMAXES = 3 +SIZE = 1_000_000 +DTYPE = bool + +LOOP_COUNT = 10 +_countnonzero = None + + +def setup(): + from bench_core import CountNonzero + global _countnonzero + _countnonzero = CountNonzero() + _countnonzero.setup(NUMAXES, SIZE, DTYPE) + + +def __benchmark__(): + # Original workload + _countnonzero.time_count_nonzero_multi_axis(NUMAXES, SIZE, DTYPE) + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Indices.time_indices.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Indices.time_indices.py new file mode 100644 index 0000000000..d5370a4a4c --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Indices.time_indices.py @@ -0,0 +1,82 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +LOOP_COUNT = 100 +_indices = None + + +def setup(): + from bench_core import Indices + global _indices + _indices = Indices() + + +def __benchmark__(): + # Original workload + _indices.time_indices() + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.PackBits.time_packbits.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.PackBits.time_packbits.py new file mode 100644 index 0000000000..197bf75fb3 --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.PackBits.time_packbits.py @@ -0,0 +1,85 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +DTYPE = bool + +LOOP_COUNT = 100000 +_packbits = None + + +def setup(): + from bench_core import PackBits + global _packbits + _packbits = PackBits() + _packbits.setup(DTYPE) + + +def __benchmark__(): + # Original workload + _packbits.time_packbits(DTYPE) + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.PackBits.time_packbits_axis0.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.PackBits.time_packbits_axis0.py new file mode 100644 index 0000000000..bf305b0513 --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.PackBits.time_packbits_axis0.py @@ -0,0 +1,85 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +DTYPE = bool + +LOOP_COUNT = 100 +_packbits = None + + +def setup(): + from bench_core import PackBits + global _packbits + _packbits = PackBits() + _packbits.setup(DTYPE) + + +def __benchmark__(): + # Original workload + _packbits.time_packbits_axis0(DTYPE) + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.PackBits.time_packbits_axis1.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.PackBits.time_packbits_axis1.py new file mode 100644 index 0000000000..453dc0881b --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.PackBits.time_packbits_axis1.py @@ -0,0 +1,85 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +DTYPE = bool + +LOOP_COUNT = 10000 +_packbits = None + + +def setup(): + from bench_core import PackBits + global _packbits + _packbits = PackBits() + _packbits.setup(DTYPE) + + +def __benchmark__(): + # Original workload + _packbits.time_packbits_axis1(DTYPE) + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.PackBits.time_packbits_little.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.PackBits.time_packbits_little.py new file mode 100644 index 0000000000..c160ce0732 --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.PackBits.time_packbits_little.py @@ -0,0 +1,85 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +DTYPE = bool + +LOOP_COUNT = 100000 +_packbits = None + + +def setup(): + from bench_core import PackBits + global _packbits + _packbits = PackBits() + _packbits.setup(DTYPE) + + +def __benchmark__(): + # Original workload + _packbits.time_packbits_little(DTYPE) + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.StatsMethods.time_max.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.StatsMethods.time_max.py new file mode 100644 index 0000000000..947977beae --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.StatsMethods.time_max.py @@ -0,0 +1,86 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +DTYPE = 'float64' +SIZE = 10_000 + +LOOP_COUNT = 10000 +_statsmethods = None + + +def setup(): + from bench_core import StatsMethods + global _statsmethods + _statsmethods = StatsMethods() + _statsmethods.setup(DTYPE, SIZE) + + +def __benchmark__(): + # Original workload + _statsmethods.time_max(DTYPE, SIZE) + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.StatsMethods.time_mean.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.StatsMethods.time_mean.py new file mode 100644 index 0000000000..b30c1a833c --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.StatsMethods.time_mean.py @@ -0,0 +1,86 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +DTYPE = 'float64' +SIZE = 10_000 + +LOOP_COUNT = 10000 +_statsmethods = None + + +def setup(): + from bench_core import StatsMethods + global _statsmethods + _statsmethods = StatsMethods() + _statsmethods.setup(DTYPE, SIZE) + + +def __benchmark__(): + # Original workload + _statsmethods.time_mean(DTYPE, SIZE) + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.StatsMethods.time_min.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.StatsMethods.time_min.py new file mode 100644 index 0000000000..42daeed0ae --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.StatsMethods.time_min.py @@ -0,0 +1,86 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +DTYPE = 'float64' +SIZE = 10_000 + +LOOP_COUNT = 10000 +_statsmethods = None + + +def setup(): + from bench_core import StatsMethods + global _statsmethods + _statsmethods = StatsMethods() + _statsmethods.setup(DTYPE, SIZE) + + +def __benchmark__(): + # Original workload + _statsmethods.time_min(DTYPE, SIZE) + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.StatsMethods.time_prod.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.StatsMethods.time_prod.py new file mode 100644 index 0000000000..011bc5df46 --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.StatsMethods.time_prod.py @@ -0,0 +1,86 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +DTYPE = 'float64' +SIZE = 10_000 + +LOOP_COUNT = 10000 +_statsmethods = None + + +def setup(): + from bench_core import StatsMethods + global _statsmethods + _statsmethods = StatsMethods() + _statsmethods.setup(DTYPE, SIZE) + + +def __benchmark__(): + # Original workload + _statsmethods.time_prod(DTYPE, SIZE) + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.StatsMethods.time_std.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.StatsMethods.time_std.py new file mode 100644 index 0000000000..12450de327 --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.StatsMethods.time_std.py @@ -0,0 +1,86 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +DTYPE = 'float64' +SIZE = 10_000 + +LOOP_COUNT = 1000 +_statsmethods = None + + +def setup(): + from bench_core import StatsMethods + global _statsmethods + _statsmethods = StatsMethods() + _statsmethods.setup(DTYPE, SIZE) + + +def __benchmark__(): + # Original workload + _statsmethods.time_std(DTYPE, SIZE) + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.StatsMethods.time_sum.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.StatsMethods.time_sum.py new file mode 100644 index 0000000000..fc6545ee66 --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.StatsMethods.time_sum.py @@ -0,0 +1,86 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +DTYPE = 'float64' +SIZE = 10_000 + +LOOP_COUNT = 10000 +_statsmethods = None + + +def setup(): + from bench_core import StatsMethods + global _statsmethods + _statsmethods = StatsMethods() + _statsmethods.setup(DTYPE, SIZE) + + +def __benchmark__(): + # Original workload + _statsmethods.time_sum(DTYPE, SIZE) + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.StatsMethods.time_var.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.StatsMethods.time_var.py new file mode 100644 index 0000000000..bfc58877c1 --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.StatsMethods.time_var.py @@ -0,0 +1,86 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +DTYPE = 'float64' +SIZE = 10_000 + +LOOP_COUNT = 1000 +_statsmethods = None + + +def setup(): + from bench_core import StatsMethods + global _statsmethods + _statsmethods = StatsMethods() + _statsmethods.setup(DTYPE, SIZE) + + +def __benchmark__(): + # Original workload + _statsmethods.time_var(DTYPE, SIZE) + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Temporaries.time_large.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Temporaries.time_large.py new file mode 100644 index 0000000000..c2e3d74a52 --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Temporaries.time_large.py @@ -0,0 +1,83 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +LOOP_COUNT = 100 +_temporaries = None + + +def setup(): + from bench_core import Temporaries + global _temporaries + _temporaries = Temporaries() + _temporaries.setup() + + +def __benchmark__(): + # Original workload + _temporaries.time_large() + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Temporaries.time_large2.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Temporaries.time_large2.py new file mode 100644 index 0000000000..9d99e33dd2 --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Temporaries.time_large2.py @@ -0,0 +1,83 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +LOOP_COUNT = 100 +_temporaries = None + + +def setup(): + from bench_core import Temporaries + global _temporaries + _temporaries = Temporaries() + _temporaries.setup() + + +def __benchmark__(): + # Original workload + _temporaries.time_large2() + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Temporaries.time_mid.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Temporaries.time_mid.py new file mode 100644 index 0000000000..85db0ac146 --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Temporaries.time_mid.py @@ -0,0 +1,83 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +LOOP_COUNT = 1000 +_temporaries = None + + +def setup(): + from bench_core import Temporaries + global _temporaries + _temporaries = Temporaries() + _temporaries.setup() + + +def __benchmark__(): + # Original workload + _temporaries.time_mid() + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Temporaries.time_mid2.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Temporaries.time_mid2.py new file mode 100644 index 0000000000..856841e42b --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Temporaries.time_mid2.py @@ -0,0 +1,83 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +LOOP_COUNT = 1000 +_temporaries = None + + +def setup(): + from bench_core import Temporaries + global _temporaries + _temporaries = Temporaries() + _temporaries.setup() + + +def __benchmark__(): + # Original workload + _temporaries.time_mid2() + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.UnpackBits.time_unpackbits.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.UnpackBits.time_unpackbits.py new file mode 100644 index 0000000000..e11c15e7fe --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.UnpackBits.time_unpackbits.py @@ -0,0 +1,83 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +LOOP_COUNT = 10000 +_unpackbits = None + + +def setup(): + from bench_core import UnpackBits + global _unpackbits + _unpackbits = UnpackBits() + _unpackbits.setup() + + +def __benchmark__(): + # Original workload + _unpackbits.time_unpackbits() + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.UnpackBits.time_unpackbits_axis0.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.UnpackBits.time_unpackbits_axis0.py new file mode 100644 index 0000000000..0c21e6356b --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.UnpackBits.time_unpackbits_axis0.py @@ -0,0 +1,83 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +LOOP_COUNT = 100 +_unpackbits = None + + +def setup(): + from bench_core import UnpackBits + global _unpackbits + _unpackbits = UnpackBits() + _unpackbits.setup() + + +def __benchmark__(): + # Original workload + _unpackbits.time_unpackbits_axis0() + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.UnpackBits.time_unpackbits_axis1.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.UnpackBits.time_unpackbits_axis1.py new file mode 100644 index 0000000000..a244c4738e --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.UnpackBits.time_unpackbits_axis1.py @@ -0,0 +1,83 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +LOOP_COUNT = 1000 +_unpackbits = None + + +def setup(): + from bench_core import UnpackBits + global _unpackbits + _unpackbits = UnpackBits() + _unpackbits.setup() + + +def __benchmark__(): + # Original workload + _unpackbits.time_unpackbits_axis1() + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.UnpackBits.time_unpackbits_axis1_little.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.UnpackBits.time_unpackbits_axis1_little.py new file mode 100644 index 0000000000..953a8c1862 --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.UnpackBits.time_unpackbits_axis1_little.py @@ -0,0 +1,83 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +LOOP_COUNT = 1000 +_unpackbits = None + + +def setup(): + from bench_core import UnpackBits + global _unpackbits + _unpackbits = UnpackBits() + _unpackbits.setup() + + +def __benchmark__(): + # Original workload + _unpackbits.time_unpackbits_axis1_little() + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.UnpackBits.time_unpackbits_little.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.UnpackBits.time_unpackbits_little.py new file mode 100644 index 0000000000..022ff52aa0 --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.UnpackBits.time_unpackbits_little.py @@ -0,0 +1,83 @@ +# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# The Universal Permissive License (UPL), Version 1.0 +# +# Subject to the condition set forth below, permission is hereby granted to any +# person obtaining a copy of this software, associated documentation and/or +# data (collectively the "Software"), free of charge and under any and all +# copyright rights in the Software, and any and all patent rights owned or +# freely licensable by each licensor hereunder covering either (i) the +# unmodified Software as contributed to or provided by such licensor, or (ii) +# the Larger Works (as defined below), to deal in both +# +# (a) the Software, and +# +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +# one is included with the Software each a "Larger Work" to which the Software +# is contributed by such licensors), +# +# without restriction, including without limitation the rights to copy, create +# derivative works of, display, perform, and distribute the Software and make, +# use, sell, offer for sale, import, export, have made, and have sold the +# Software and the Larger Work(s), and to sublicense the foregoing rights on +# either these or other terms. +# +# This license is subject to the following condition: +# +# The above copyright notice and either this complete permission notice or at a +# minimum a reference to the UPL must be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +LOOP_COUNT = 10000 +_unpackbits = None + + +def setup(): + from bench_core import UnpackBits + global _unpackbits + _unpackbits = UnpackBits() + _unpackbits.setup() + + +def __benchmark__(): + # Original workload + _unpackbits.time_unpackbits_little() + + +def run(): + for _ in range(LOOP_COUNT): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + # Required alongside this file if copied elsewhere + return ["bench_core.py", "common.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.py new file mode 100644 index 0000000000..326f1e3ce9 --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.py @@ -0,0 +1,259 @@ +import sys +import os +import numpy as np +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +from common import Benchmark + +# Ensure we have numpy version info in the logs +print(f"Using numpy version '{np.__version__}'") + +class Core(Benchmark): + def setup(self): + self.l100 = range(100) + self.l50 = range(50) + self.float_l1000 = [float(i) for i in range(1000)] + self.float64_l1000 = [np.float64(i) for i in range(1000)] + self.int_l1000 = list(range(1000)) + self.l = [np.arange(1000), np.arange(1000)] + self.l_view = [memoryview(a) for a in self.l] + self.l10x10 = np.ones((10, 10)) + self.float64_dtype = np.dtype(np.float64) + + def time_array_1(self): + np.array(1) + + def time_array_empty(self): + np.array([]) + + def time_array_l1(self): + np.array([1]) + + def time_array_l100(self): + np.array(self.l100) + + def time_array_float_l1000(self): + np.array(self.float_l1000) + + def time_array_float_l1000_dtype(self): + np.array(self.float_l1000, dtype=self.float64_dtype) + + def time_array_float64_l1000(self): + np.array(self.float64_l1000) + + def time_array_int_l1000(self): + np.array(self.int_l1000) + + def time_array_l(self): + np.array(self.l) + + def time_array_l_view(self): + np.array(self.l_view) + + def time_can_cast(self): + np.can_cast(self.l10x10, self.float64_dtype) + + def time_can_cast_same_kind(self): + np.can_cast(self.l10x10, self.float64_dtype, casting="same_kind") + + def time_vstack_l(self): + np.vstack(self.l) + + def time_hstack_l(self): + np.hstack(self.l) + + def time_dstack_l(self): + np.dstack(self.l) + + def time_arange_100(self): + np.arange(100) + + def time_zeros_100(self): + np.zeros(100) + + def time_ones_100(self): + np.ones(100) + + def time_empty_100(self): + np.empty(100) + + def time_empty_like(self): + np.empty_like(self.l10x10) + + def time_eye_100(self): + np.eye(100) + + def time_identity_100(self): + np.identity(100) + + def time_eye_3000(self): + np.eye(3000) + + def time_identity_3000(self): + np.identity(3000) + + def time_diag_l100(self): + np.diag(self.l100) + + def time_diagflat_l100(self): + np.diagflat(self.l100) + + def time_diagflat_l50_l50(self): + np.diagflat([self.l50, self.l50]) + + def time_triu_l10x10(self): + np.triu(self.l10x10) + + def time_tril_l10x10(self): + np.tril(self.l10x10) + + def time_triu_indices_500(self): + np.triu_indices(500) + + def time_tril_indices_500(self): + np.tril_indices(500) + + +class Temporaries(Benchmark): + def setup(self): + self.amid = np.ones(50000) + self.bmid = np.ones(50000) + self.alarge = np.ones(1000000) + self.blarge = np.ones(1000000) + + def time_mid(self): + (self.amid * 2) + self.bmid + + def time_mid2(self): + (self.amid + self.bmid) - 2 + + def time_large(self): + (self.alarge * 2) + self.blarge + + def time_large2(self): + (self.alarge + self.blarge) - 2 + + +class CorrConv(Benchmark): + params = [[50, 1000, int(1e5)], + [10, 100, 1000, int(1e4)], + ['valid', 'same', 'full']] + param_names = ['size1', 'size2', 'mode'] + + def setup(self, size1, size2, mode): + self.x1 = np.linspace(0, 1, num=size1) + self.x2 = np.cos(np.linspace(0, 2*np.pi, num=size2)) + + def time_correlate(self, size1, size2, mode): + np.correlate(self.x1, self.x2, mode=mode) + + def time_convolve(self, size1, size2, mode): + np.convolve(self.x1, self.x2, mode=mode) + + +class CountNonzero(Benchmark): + param_names = ['numaxes', 'size', 'dtype'] + params = [ + [1, 2, 3], + [100, 10000, 1000000], + [bool, np.int8, np.int16, np.int32, np.int64, str, object] + ] + + def setup(self, numaxes, size, dtype): + self.x = np.arange(numaxes * size).reshape(numaxes, size) + self.x = (self.x % 3).astype(dtype) + + def time_count_nonzero(self, numaxes, size, dtype): + np.count_nonzero(self.x) + + def time_count_nonzero_axis(self, numaxes, size, dtype): + np.count_nonzero(self.x, axis=self.x.ndim - 1) + + def time_count_nonzero_multi_axis(self, numaxes, size, dtype): + if self.x.ndim >= 2: + np.count_nonzero(self.x, axis=( + self.x.ndim - 1, self.x.ndim - 2)) + + +class PackBits(Benchmark): + param_names = ['dtype'] + params = [[bool, np.uintp]] + def setup(self, dtype): + self.d = np.ones(10000, dtype=dtype) + self.d2 = np.ones((200, 1000), dtype=dtype) + + def time_packbits(self, dtype): + np.packbits(self.d) + + def time_packbits_little(self, dtype): + np.packbits(self.d, bitorder="little") + + def time_packbits_axis0(self, dtype): + np.packbits(self.d2, axis=0) + + def time_packbits_axis1(self, dtype): + np.packbits(self.d2, axis=1) + + +class UnpackBits(Benchmark): + def setup(self): + self.d = np.ones(10000, dtype=np.uint8) + self.d2 = np.ones((200, 1000), dtype=np.uint8) + + def time_unpackbits(self): + np.unpackbits(self.d) + + def time_unpackbits_little(self): + np.unpackbits(self.d, bitorder="little") + + def time_unpackbits_axis0(self): + np.unpackbits(self.d2, axis=0) + + def time_unpackbits_axis1(self): + np.unpackbits(self.d2, axis=1) + + def time_unpackbits_axis1_little(self): + np.unpackbits(self.d2, bitorder="little", axis=1) + + +class Indices(Benchmark): + def time_indices(self): + np.indices((1000, 500)) + + +class StatsMethods(Benchmark): + # Not testing, but in array_api (redundant) + # 8, 16, 32 bit variants, and 128 complexes + params = [['int64', 'uint64', 'float64', 'intp', + 'complex64', 'bool', 'float', 'int', + 'complex', 'complex256'], + [100**n for n in range(0, 2)]] + param_names = ['dtype', 'size'] + + def setup(self, dtype, size): + try: + self.data = np.ones(size, dtype=getattr(np, dtype)) + except AttributeError: # builtins throw AttributeError after 1.20 + self.data = np.ones(size, dtype=dtype) + if dtype.startswith('complex'): + self.data = np.random.randn(size) + 1j * np.random.randn(size) + + def time_min(self, dtype, size): + self.data.min() + + def time_max(self, dtype, size): + self.data.max() + + def time_mean(self, dtype, size): + self.data.mean() + + def time_std(self, dtype, size): + self.data.std() + + def time_prod(self, dtype, size): + self.data.prod() + + def time_var(self, dtype, size): + self.data.var() + + def time_sum(self, dtype, size): + self.data.sum() diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/common.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/common.py new file mode 100644 index 0000000000..4f291dad11 --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/common.py @@ -0,0 +1,224 @@ +import numpy as np +import random +import os +from functools import lru_cache +from pathlib import Path + +# Various pre-crafted datasets/variables for testing +# !!! Must not be changed -- only appended !!! +# while testing numpy we better not rely on numpy to produce random +# sequences +random.seed(1) +# but will seed it nevertheless +np.random.seed(1) + +nx, ny = 1000, 1000 +# reduced squares based on indexes_rand, primarily for testing more +# time-consuming functions (ufunc, linalg, etc) +nxs, nys = 100, 100 + +# a list of interesting types to test +TYPES1 = [ + 'int16', 'float16', + 'int32', 'float32', + 'int64', 'float64', 'complex64', + 'longdouble', 'complex128', +] +if 'complex256' in np.sctypeDict: + TYPES1.append('clongdouble') + +DLPACK_TYPES = [ + 'int16', 'float16', + 'int32', 'float32', + 'int64', 'float64', 'complex64', + 'complex128', 'bool', +] + +# Path for caching +CACHE_ROOT = Path(__file__).resolve().parent.parent / 'env' / 'numpy_benchdata' + +# values which will be used to construct our sample data matrices +# replicate 10 times to speed up initial imports of this helper +# and generate some redundancy + +@lru_cache(typed=True) +def get_values(): + rnd = np.random.RandomState(1) + values = np.tile(rnd.uniform(0, 100, size=nx*ny//10), 10) + return values + + +@lru_cache(typed=True) +def get_square(dtype): + values = get_values() + arr = values.astype(dtype=dtype).reshape((nx, ny)) + + # adjust complex ones to have non-degenerated imagery part -- use + # original data transposed for that + if arr.dtype.kind == 'c': + arr += arr.T*1j + + return arr + +@lru_cache(typed=True) +def get_squares(): + return {t: get_square(t) for t in TYPES1} + + +@lru_cache(typed=True) +def get_square_(dtype): + arr = get_square(dtype) + return arr[:nxs, :nys] + + +@lru_cache(typed=True) +def get_squares_(): + # smaller squares + return {t: get_square_(t) for t in TYPES1} + + +@lru_cache(typed=True) +def get_vectors(): + # vectors + vectors = {t: s[0] for t, s in get_squares().items()} + return vectors + + +@lru_cache(typed=True) +def get_indexes(): + indexes = list(range(nx)) + # so we do not have all items + indexes.pop(5) + indexes.pop(95) + + indexes = np.array(indexes) + return indexes + + +@lru_cache(typed=True) +def get_indexes_rand(): + rnd = random.Random(1) + + indexes_rand = get_indexes().tolist() # copy + rnd.shuffle(indexes_rand) # in-place shuffle + indexes_rand = np.array(indexes_rand) + return indexes_rand + + +@lru_cache(typed=True) +def get_indexes_(): + # smaller versions + indexes = get_indexes() + indexes_ = indexes[indexes < nxs] + return indexes_ + + +@lru_cache(typed=True) +def get_indexes_rand_(): + indexes_rand = get_indexes_rand() + indexes_rand_ = indexes_rand[indexes_rand < nxs] + return indexes_rand_ + + +@lru_cache(typed=True) +def get_data(size, dtype, ip_num=0, zeros=False, finite=True, denormal=False): + """ + Generates a cached random array that covers several scenarios that + may affect the benchmark for fairness and to stabilize the benchmark. + + Parameters + ---------- + size: int + Array length. + + dtype: dtype or dtype specifier + + ip_num: int + Input number, to avoid memory overload + and to provide unique data for each operand. + + zeros: bool + Spreading zeros along with generated data. + + finite: bool + Avoid spreading fp special cases nan/inf. + + denormal: + Spreading subnormal numbers along with generated data. + """ + dtype = np.dtype(dtype) + dname = dtype.name + cache_name = f'{dname}_{size}_{ip_num}_{int(zeros)}' + if dtype.kind in 'fc': + cache_name += f'{int(finite)}{int(denormal)}' + cache_name += '.bin' + cache_path = CACHE_ROOT / cache_name + if cache_path.exists(): + return np.fromfile(cache_path, dtype) + + array = np.ones(size, dtype) + rands = [] + if dtype.kind == 'i': + dinfo = np.iinfo(dtype) + scale = 8 + if zeros: + scale += 1 + lsize = size // scale + for low, high in ( + (-0x80, -1), + (1, 0x7f), + (-0x8000, -1), + (1, 0x7fff), + (-0x80000000, -1), + (1, 0x7fffffff), + (-0x8000000000000000, -1), + (1, 0x7fffffffffffffff), + ): + rands += [np.random.randint( + max(low, dinfo.min), + min(high, dinfo.max), + lsize, dtype + )] + elif dtype.kind == 'u': + dinfo = np.iinfo(dtype) + scale = 4 + if zeros: + scale += 1 + lsize = size // scale + for high in (0xff, 0xffff, 0xffffffff, 0xffffffffffffffff): + rands += [np.random.randint(1, min(high, dinfo.max), lsize, dtype)] + elif dtype.kind in 'fc': + scale = 1 + if zeros: + scale += 1 + if not finite: + scale += 2 + if denormal: + scale += 1 + dinfo = np.finfo(dtype) + lsize = size // scale + rands = [np.random.rand(lsize).astype(dtype)] + if not finite: + rands += [ + np.empty(lsize, dtype=dtype), np.empty(lsize, dtype=dtype) + ] + rands[1].fill(float('nan')) + rands[2].fill(float('inf')) + if denormal: + rands += [np.empty(lsize, dtype=dtype)] + rands[-1].fill(dinfo.smallest_subnormal) + + if rands: + if zeros: + rands += [np.zeros(lsize, dtype)] + stride = len(rands) + for start, r in enumerate(rands): + array[start:len(r)*stride:stride] = r + + if not CACHE_ROOT.exists(): + CACHE_ROOT.mkdir(parents=True) + array.tofile(cache_path) + return array + +class Benchmark: + pass diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/LICENSE.txt b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/LICENSE.txt new file mode 100644 index 0000000000..fee212f6a3 --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/LICENSE.txt @@ -0,0 +1,20 @@ +The MIT License + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/README.md b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/README.md new file mode 100644 index 0000000000..44501438e4 --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/README.md @@ -0,0 +1,1234 @@ +# Pyperformance benchmark port process for benchmarking with the PolyBench harness + +## Brief explanation + +These benchmarks have been copied from the pyperformance repository and manually updated +so that they conform to the PolyBench contract and they don't use any pyperformance/pyperf interface. +* Remove the usage of `pyperf.Runner` and other `pyperf` functions/classes. +* Move the benchmark workload into the `run` function. +* Define the PolyBench benchmark configuration functions, such as: +`setup`, `warmupIterations`, `iterations`, `summary`, and `dependencies`. + +## Version information + +Version: 1.0.6 +Source repository: Acquired with `pip install` (GitHub repo: https://github.com/python/pyperformance/tree/main) + +The version was chosen to align with the one used in `graalpython/mx.graalpython/mx_graalpython_python_benchmarks.py::PyPerformanceSuite`. + +## Files sourced from the pyperformance project + +The benchmarks from the pyperformance repository have the following characteristics +which do not align with the requirements of the PolyBench harness: +* The benchmark workload is in a `if __name__ == "__main__":` branch. + * The PolyBench harness expects the benchmark workload to be in the `run` function. +* The workload is passed to a `pyperf.Runner` instance for execution. + * The PolyBench harness should execute the workload directly. +* The benchmark has a dependency on `pyperf` for performance measurement purposes. This dependency +is not required for the workload itself. + * As these dependencies are not essential for the workload but used for auxiliary purposes of the + pyperformance harness, they should be eliminated in facilitating benchmarking with the PolyBench harness. + +Additionally, there are special functions that the benchmark may implement to configure the PolyBench execution, +such as: `setup`, `run`, `warmupIterations`, `iterations`, `summary`, and `dependencies`. + +To handle these differences, appropriate changes to the source code of the benchmarks must be made. +These changes are not easy to automate and have therefore been made manually. +The differences have been catalogued in this section, on a file-by-file basis. + +### bm_pathlib.py +Original file path: pyperformance/pyperformance/data-files/benchmarks/bm_pathlib/run_benchmark.py +The file has not been named `pathlib.py` as this name would've hidden the `pathlib` package from the standard library. +Changes made to the original file, as reported by the `diff` tool: +``` +11d10 +< import shutil +14,15d12 +< import pyperf +< +29c26,28 +< def setup(num_files): +--- +> tmp_path = None +> def setup(): +> global tmp_path +31c30 +< for fn in generate_filenames(tmp_path, num_files): +--- +> for fn in generate_filenames(tmp_path, NUM_FILES): +35,36d33 +< return tmp_path +< +49d45 +< t0 = pyperf.perf_counter() +62c58,68 +< return pyperf.perf_counter() - t0 +--- +> +> def run(): +> bench_pathlib(8, tmp_path) +> +> +> def warmupIterations(): +> return 0 +> +> +> def iterations(): +> return 10 +65,77c71,76 +< if __name__ == "__main__": +< runner = pyperf.Runner() +< runner.metadata['description'] = ("Test the performance of " +< "pathlib operations.") +< +< modname = pathlib.__name__ +< runner.metadata['pathlib_module'] = modname +< +< tmp_path = setup(NUM_FILES) +< try: +< runner.bench_time_func('pathlib', bench_pathlib, tmp_path) +< finally: +< shutil.rmtree(tmp_path) +--- +> def summary(): +> return { +> "name": "OutlierRemovalAverageSummary", +> "lower-threshold": 0.0, +> "upper-threshold": 1.0, +> } +``` + +### bm_pickle.py +Original file path: pyperformance/pyperformance/data-files/benchmarks/bm_pickle/run_benchmark.py +The file has not been named `pickle.py` as this name would've hidden the `pickle` package from the standard library. +Changes made to the original file, as reported by the `diff` tool: +``` +18,20c18,19 +< +< import pyperf +< IS_PYPY = (pyperf.python_implementation() == 'pypy') +--- +> import argparse +> import pickle +87d85 +< t0 = pyperf.perf_counter() +113,114d110 +< return pyperf.perf_counter() - t0 +< +126d121 +< t0 = pyperf.perf_counter() +151,152d145 +< return pyperf.perf_counter() - t0 +< +163d155 +< t0 = pyperf.perf_counter() +178,179d169 +< return pyperf.perf_counter() - t0 +< +187d176 +< t0 = pyperf.perf_counter() +202,203d190 +< return pyperf.perf_counter() - t0 +< +213d199 +< t0 = pyperf.perf_counter() +223,224d208 +< return pyperf.perf_counter() - t0 +< +250,252c234,236 +< if __name__ == "__main__": +< runner = pyperf.Runner(add_cmdline_args=add_cmdline_args) +< runner.metadata['description'] = "Test the performance of pickling." +--- +> def run(): +> __benchmark__(["pickle"]) +> +254c238,239 +< parser = runner.argparser +--- +> def __benchmark__(args): +> parser = argparse.ArgumentParser(prog="python") +262,263c247,248 +< options = runner.parse_args() +< benchmark, inner_loops = BENCHMARKS[options.benchmark] +--- +> options = parser.parse_args(args) +> benchmark, _ = BENCHMARKS[options.benchmark] +269c254 +< if not (options.pure_python or IS_PYPY): +--- +> if not options.pure_python: +282,283d266 +< runner.metadata['pickle_protocol'] = str(options.protocol) +< runner.metadata['pickle_module'] = pickle.__name__ +285,286c268,287 +< runner.bench_time_func(name, benchmark, +< pickle, options, inner_loops=inner_loops) +--- +> benchmark(512, pickle, options) +> +> +> def warmupIterations(): +> return 0 +> +> +> def iterations(): +> return 10 +> +> +> def summary(): +> return { +> "name": "OutlierRemovalAverageSummary", +> "lower-threshold": 0.0, +> "upper-threshold": 1.0, +> } +> +> if __name__ == "__main__": +> run() +``` + +### bm_richards.py +Original file path: pyperformance/pyperformance/data-files/benchmarks/bm_richards/run_benchmark.py +The file has not been named `richards.py` as there is already a `richards.py` in micro benchmarks. +Changes made to the original file, as reported by the `diff` tool: +``` +12,13d11 +< import pyperf +< +418,421c416 +< if __name__ == "__main__": +< runner = pyperf.Runner() +< runner.metadata['description'] = "The Richards benchmark" +< +--- +> def run(): +423c418,434 +< runner.bench_func('richards', richard.run, 1) +--- +> richard.run(1) +> +> +> def warmupIterations(): +> return 0 +> +> +> def iterations(): +> return 10 +> +> +> def summary(): +> return { +> "name": "OutlierRemovalAverageSummary", +> "lower-threshold": 0.0, +> "upper-threshold": 1.0, +> } +``` + +### chaos.py +Original file path: pyperformance/pyperformance/data-files/benchmarks/bm_chaos/run_benchmark.py +Changes made to the original file, as reported by the `diff` tool: +``` +8,9c8 +< +< import pyperf +--- +> import argparse +238c237 +< def main(runner, args): +--- +> def __benchmark__(args): +263,268d261 +< runner.metadata['chaos_thickness'] = args.thickness +< runner.metadata['chaos_width'] = args.width +< runner.metadata['chaos_height'] = args.height +< runner.metadata['chaos_iterations'] = args.iterations +< runner.metadata['chaos_rng_seed'] = args.rng_seed +< +270,272c263 +< runner.bench_func('chaos', chaos.create_image_chaos, +< args.width, args.height, args.iterations, +< args.filename, args.rng_seed) +--- +> chaos.create_image_chaos(args.width, args.height, args.iterations, args.filename, args.rng_seed) +284,287c275,276 +< if __name__ == "__main__": +< runner = pyperf.Runner(add_cmdline_args=add_cmdline_args) +< runner.metadata['description'] = "Create chaosgame-like fractals" +< cmd = runner.argparser +--- +> def run(): +> cmd = argparse.ArgumentParser(prog="python") +308,309c297,314 +< args = runner.parse_args() +< main(runner, args) +--- +> args = cmd.parse_args() +> __benchmark__(args) +> +> +> def warmupIterations(): +> return 0 +> +> +> def iterations(): +> return 10 +> +> +> def summary(): +> return { +> "name": "OutlierRemovalAverageSummary", +> "lower-threshold": 0.0, +> "upper-threshold": 1.0, +> } +``` + +### fannkuch.py +Original file path: pyperformance/pyperformance/data-files/benchmarks/bm_fannkuch/run_benchmark.py +Changes made to the original file, as reported by the `diff` tool: +``` +8,9d7 +< import pyperf +< +51,54c49,66 +< if __name__ == "__main__": +< runner = pyperf.Runner() +< arg = DEFAULT_ARG +< runner.bench_func('fannkuch', fannkuch, arg) +--- +> def run(): +> fannkuch(DEFAULT_ARG) +> +> +> def warmupIterations(): +> return 0 +> +> +> def iterations(): +> return 10 +> +> +> def summary(): +> return { +> "name": "OutlierRemovalAverageSummary", +> "lower-threshold": 0.0, +> "upper-threshold": 1.0, +> } +``` + +### float.py +Original file path: pyperformance/pyperformance/data-files/benchmarks/bm_float/run_benchmark.py +Changes made to the original file, as reported by the `diff` tool: +``` +4,5d3 +< import pyperf +< +55,57c53,63 +< if __name__ == "__main__": +< runner = pyperf.Runner() +< runner.metadata['description'] = "Float benchmark" +--- +> def run(): +> benchmark(POINTS) +> +> +> def warmupIterations(): +> return 0 +> +> +> def iterations(): +> return 10 +> +59,60c65,70 +< points = POINTS +< runner.bench_func('float', benchmark, points) +--- +> def summary(): +> return { +> "name": "OutlierRemovalAverageSummary", +> "lower-threshold": 0.0, +> "upper-threshold": 1.0, +> } +``` + +### go.py +Original file path: pyperformance/pyperformance/data-files/benchmarks/bm_go/run_benchmark.py +Changes made to the original file, as reported by the `diff` tool: +``` +7,8d6 +< import pyperf +< +454,461c452,469 +< if __name__ == "__main__": +< kw = {} +< if pyperf.python_has_jit(): +< # PyPy needs to compute more warmup values to warmup its JIT +< kw['warmups'] = 50 +< runner = pyperf.Runner(**kw) +< runner.metadata['description'] = "Test the performance of the Go benchmark" +< runner.bench_func('go', versus_cpu) +--- +> def run(): +> versus_cpu() +> +> +> def warmupIterations(): +> return 0 +> +> +> def iterations(): +> return 10 +> +> +> def summary(): +> return { +> "name": "OutlierRemovalAverageSummary", +> "lower-threshold": 0.0, +> "upper-threshold": 1.0, +> } +``` + +### hexiom.py +Original file path: pyperformance/pyperformance/data-files/benchmarks/bm_hexiom/run_benchmark.py +Changes made to the original file, as reported by the `diff` tool: +``` +12,13c12 +< +< import pyperf +--- +> import argparse +621c620 +< def main(loops, level): +--- +> def __benchmark__(loops, level): +631d629 +< t0 = pyperf.perf_counter() +639,640d636 +< dt = pyperf.perf_counter() - t0 +< +646,647d641 +< return dt +< +653,658c647 +< if __name__ == "__main__": +< kw = {'add_cmdline_args': add_cmdline_args} +< if pyperf.python_has_jit(): +< # PyPy needs to compute more warmup values to warmup its JIT +< kw['warmups'] = 15 +< runner = pyperf.Runner(**kw) +--- +> def run(): +660c649,650 +< runner.argparser.add_argument("--level", type=int, +--- +> parser = argparse.ArgumentParser(prog="python") +> parser.add_argument("--level", type=int, +666,668c656,666 +< args = runner.parse_args() +< runner.metadata['description'] = "Solver of Hexiom board game" +< runner.metadata['hexiom_level'] = args.level +--- +> args = parser.parse_args() +> __benchmark__(16, args.level) +> +> +> def warmupIterations(): +> return 0 +> +> +> def iterations(): +> return 10 +> +670c668,673 +< runner.bench_time_func('hexiom', main, args.level) +--- +> def summary(): +> return { +> "name": "OutlierRemovalAverageSummary", +> "lower-threshold": 0.0, +> "upper-threshold": 1.0, +> } +``` + +### json_dumps.py +Original file path: pyperformance/pyperformance/data-files/benchmarks/bm_json_dumps/run_benchmark.py +Changes made to the original file, as reported by the `diff` tool: +``` +3,4c3 +< +< import pyperf +--- +> import argparse +30,32c29,31 +< def main(): +< runner = pyperf.Runner(add_cmdline_args=add_cmdline_args) +< runner.argparser.add_argument("--cases", +--- +> def run(): +> parser = argparse.ArgumentParser(prog="python") +> parser.add_argument("--cases", +35d33 +< runner.metadata['description'] = "Benchmark json.dumps()" +37c35 +< args = runner.parse_args() +--- +> args = parser.parse_args() +55c53,61 +< runner.bench_func('json_dumps', bench_json_dumps, data) +--- +> bench_json_dumps(data) +> +> +> def warmupIterations(): +> return 0 +> +> +> def iterations(): +> return 10 +58,59c64,69 +< if __name__ == '__main__': +< main() +--- +> def summary(): +> return { +> "name": "OutlierRemovalAverageSummary", +> "lower-threshold": 0.0, +> "upper-threshold": 1.0, +> } +``` + +### json_loads.py +Original file path: pyperformance/pyperformance/data-files/benchmarks/bm_json_loads/run_benchmark.py +Changes made to the original file, as reported by the `diff` tool: +``` +14,16d13 +< # Local imports +< import pyperf +< +97,100c94 +< if __name__ == "__main__": +< runner = pyperf.Runner() +< runner.metadata['description'] = "Benchmark json.loads()" +< +--- +> def run(): +104a99,108 +> bench_json_loads(objs) +> +> +> def warmupIterations(): +> return 0 +> +> +> def iterations(): +> return 10 +> +106c110,115 +< runner.bench_func('json_loads', bench_json_loads, objs, inner_loops=20) +--- +> def summary(): +> return { +> "name": "OutlierRemovalAverageSummary", +> "lower-threshold": 0.0, +> "upper-threshold": 1.0, +> } +``` + +### meteor_contest.py +Original file path: pyperformance/pyperformance/data-files/benchmarks/bm_meteor_contest/run_benchmark.py +Changes made to the original file, as reported by the `diff` tool: +``` +13,14d12 +< import pyperf +< +194d191 +< t0 = pyperf.perf_counter() +204,205d200 +< dt = pyperf.perf_counter() - t0 +< +209,214d203 +< return dt +< +< +< def main(): +< runner = pyperf.Runner() +< runner.metadata['description'] = "Solver for Meteor Puzzle board" +215a205 +> def __benchmark__(): +221,222c211,223 +< runner.bench_time_func('meteor_contest', bench_meteor_contest, +< board, pieces, solve_arg, fps, se_nh) +--- +> bench_meteor_contest(1, board, pieces, solve_arg, fps, se_nh) +> +> +> def run(): +> __benchmark__() +> +> +> def warmupIterations(): +> return 0 +> +> +> def iterations(): +> return 10 +225,226c226,231 +< if __name__ == "__main__": +< main() +--- +> def summary(): +> return { +> "name": "OutlierRemovalAverageSummary", +> "lower-threshold": 0.0, +> "upper-threshold": 1.0, +> } +``` + +### nbody.py +Original file path: pyperformance/pyperformance/data-files/benchmarks/bm_nbody/run_benchmark.py +Changes made to the original file, as reported by the `diff` tool: +``` +17c17 +< import pyperf +--- +> import argparse +128d127 +< t0 = pyperf.perf_counter() +135,136d133 +< return pyperf.perf_counter() - t0 +< +142,145c139,141 +< if __name__ == '__main__': +< runner = pyperf.Runner(add_cmdline_args=add_cmdline_args) +< runner.metadata['description'] = "n-body benchmark" +< runner.argparser.add_argument("--iterations", +--- +> def run(): +> parser = argparse.ArgumentParser(prog="python") +> parser.add_argument("--iterations", +149c145 +< runner.argparser.add_argument("--reference", +--- +> parser.add_argument("--reference", +154,156c150,167 +< args = runner.parse_args() +< runner.bench_time_func('nbody', bench_nbody, +< args.reference, args.iterations) +--- +> args = parser.parse_args() +> bench_nbody(1, args.reference, args.iterations) +> +> +> def warmupIterations(): +> return 0 +> +> +> def iterations(): +> return 10 +> +> +> def summary(): +> return { +> "name": "OutlierRemovalAverageSummary", +> "lower-threshold": 0.0, +> "upper-threshold": 1.0, +> } +``` + +### nqueens.py +Original file path: pyperformance/pyperformance/data-files/benchmarks/bm_nqueens/run_benchmark.py +Changes made to the original file, as reported by the `diff` tool: +``` +3,4d2 +< import pyperf +< +57,59c55,65 +< if __name__ == "__main__": +< runner = pyperf.Runner() +< runner.metadata['description'] = "Simple, brute-force N-Queens solver" +--- +> def run(): +> bench_n_queens(8) +> +> +> def warmupIterations(): +> return 0 +> +> +> def iterations(): +> return 10 +> +61,62c67,72 +< queen_count = 8 +< runner.bench_func('nqueens', bench_n_queens, queen_count) +--- +> def summary(): +> return { +> "name": "OutlierRemovalAverageSummary", +> "lower-threshold": 0.0, +> "upper-threshold": 1.0, +> } +``` + +### pidigits.py +Original file path: pyperformance/pyperformance/data-files/benchmarks/bm_pidigits/run_benchmark.py +Changes made to the original file, as reported by the `diff` tool: +``` +12,13c12 +< +< import pyperf +--- +> import argparse +59,62c58,59 +< if __name__ == "__main__": +< runner = pyperf.Runner(add_cmdline_args=add_cmdline_args) +< +< cmd = runner.argparser +--- +> def run(): +> cmd = argparse.ArgumentParser(prog="python") +67,70c64,81 +< args = runner.parse_args() +< runner.metadata['description'] = "Compute digits of pi." +< runner.metadata['pidigits_ndigit'] = args.digits +< runner.bench_func('pidigits', calc_ndigits, args.digits) +--- +> args = cmd.parse_args() +> calc_ndigits(args.digits) +> +> +> def warmupIterations(): +> return 0 +> +> +> def iterations(): +> return 10 +> +> +> def summary(): +> return { +> "name": "OutlierRemovalAverageSummary", +> "lower-threshold": 0.0, +> "upper-threshold": 1.0, +> } +``` + +### pyflate.py +Original file path: pyperformance/pyperformance/data-files/benchmarks/bm_pyflate/run_benchmark.py +Changes made to the original file, as reported by the `diff` tool: +``` +23,24d22 +< import pyperf +< +635d632 +< t0 = pyperf.perf_counter() +650d646 +< dt = pyperf.perf_counter() - t0 +656,661d651 +< return dt +< +< +< if __name__ == '__main__': +< runner = pyperf.Runner() +< runner.metadata['description'] = "Pyflate benchmark" +662a653 +> def run(): +665c656,676 +< runner.bench_time_func('pyflate', bench_pyflake, filename) +--- +> bench_pyflake(1, filename) +> +> +> def warmupIterations(): +> return 0 +> +> +> def iterations(): +> return 10 +> +> +> def summary(): +> return { +> "name": "OutlierRemovalAverageSummary", +> "lower-threshold": 0.0, +> "upper-threshold": 1.0, +> } +> +> +> def dependencies(): +> return ["data/interpreter.tar.bz2"] +``` + +### regex_compile.py +Original file path: pyperformance/pyperformance/data-files/benchmarks/bm_regex_compile/run_benchmark.py +Changes made to the original file, as reported by the `diff` tool: +``` +11,13c11,12 +< +< # Local imports +< import pyperf +--- +> import sys +> import os +39,40c38,40 +< import bm_regex_effbot +< bm_regex_effbot.bench_regex_effbot(1) +--- +> sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +> import regex_effbot +> regex_effbot.bench_regex_effbot(1) +42,43c42,43 +< import bm_regex_v8 +< bm_regex_v8.bench_regex_v8(1) +--- +> import regex_v8 +> regex_v8.bench_regex_v8(1) +53d52 +< t0 = pyperf.perf_counter() +61d59 +< return pyperf.perf_counter() - t0 +62a61,63 +> def run(): +> regexes = capture_regexes() +> bench_regex_compile(1, regexes) +64,66d64 +< if __name__ == "__main__": +< runner = pyperf.Runner() +< runner.metadata['description'] = "Test regex compilation performance" +68,69c66,83 +< regexes = capture_regexes() +< runner.bench_time_func('regex_compile', bench_regex_compile, regexes) +--- +> def warmupIterations(): +> return 0 +> +> +> def iterations(): +> return 10 +> +> +> def summary(): +> return { +> "name": "OutlierRemovalAverageSummary", +> "lower-threshold": 0.0, +> "upper-threshold": 1.0, +> } +> +> +> def dependencies(): +> return ["regex_effbot.py", "regex_v8.py"] +``` + +### regex_dna.py +Original file path: pyperformance/pyperformance/data-files/benchmarks/bm_regex_dna/run_benchmark.py +Changes made to the original file, as reported by the `diff` tool: +``` +20,21c20 +< +< import pyperf +--- +> import argparse +189d187 +< t0 = pyperf.perf_counter() +194d191 +< dt = pyperf.perf_counter() - t0 +198,199d194 +< return dt +< +206,212c201,202 +< if __name__ == '__main__': +< runner = pyperf.Runner(add_cmdline_args=add_cmdline_args) +< runner.metadata['description'] = ("Test the performance of regexps " +< "using benchmarks from " +< "The Computer Language Benchmarks Game.") +< +< cmd = runner.argparser +--- +> def run(): +> cmd = argparse.ArgumentParser(prog="python") +220c210 +< args = runner.parse_args() +--- +> args = cmd.parse_args() +229,231d218 +< runner.metadata['regex_dna_fasta_len'] = args.fasta_length +< runner.metadata['regex_dna_rng_seed'] = args.rng_seed +< +236c223,239 +< runner.bench_time_func('regex_dna', bench_regex_dna, seq, expected_res) +--- +> bench_regex_dna(1, seq, expected_res) +> +> +> def warmupIterations(): +> return 0 +> +> +> def iterations(): +> return 10 +> +> +> def summary(): +> return { +> "name": "OutlierRemovalAverageSummary", +> "lower-threshold": 0.0, +> "upper-threshold": 1.0, +> } +``` + +### regex_effbot.py +Original file path: pyperformance/pyperformance/data-files/benchmarks/bm_regex_effbot/run_benchmark.py +Changes made to the original file, as reported by the `diff` tool: +``` +16,18c16 +< +< # Local imports +< import pyperf +--- +> import argparse +135d132 +< t0 = pyperf.perf_counter() +152,153d148 +< return pyperf.perf_counter() - t0 +< +164,168c159,161 +< if __name__ == '__main__': +< runner = pyperf.Runner(add_cmdline_args=add_cmdline_args) +< runner.metadata['description'] = ("Test the performance of regexps " +< "using Fredik Lundh's benchmarks.") +< runner.argparser.add_argument("-B", "--force_bytes", action="store_true", +--- +> def run(): +> parser = argparse.ArgumentParser(prog="python") +> parser.add_argument("-B", "--force_bytes", action="store_true", +170c163 +< options = runner.parse_args() +--- +> options = parser.parse_args() +174,175c167,183 +< runner.bench_time_func('regex_effbot', bench_regex_effbot, +< inner_loops=10) +--- +> bench_regex_effbot(4) +> +> +> def warmupIterations(): +> return 0 +> +> +> def iterations(): +> return 10 +> +> +> def summary(): +> return { +> "name": "OutlierRemovalAverageSummary", +> "lower-threshold": 0.0, +> "upper-threshold": 1.0, +> } +``` + +### regex_v8.py +Original file path: pyperformance/pyperformance/data-files/benchmarks/bm_regex_v8/run_benchmark.py +Changes made to the original file, as reported by the `diff` tool: +``` +45,47d44 +< # Third party imports +< import pyperf +< +1769d1765 +< t0 = pyperf.perf_counter() +1783d1778 +< return pyperf.perf_counter() - t0 +1786,1790c1781,1798 +< if __name__ == '__main__': +< runner = pyperf.Runner() +< runner.metadata['description'] = ("Test the performance of regexps " +< "using V8's benchmarks") +< runner.bench_time_func('regex_v8', bench_regex_v8) +--- +> def run(): +> bench_regex_v8(8) +> +> +> def warmupIterations(): +> return 0 +> +> +> def iterations(): +> return 10 +> +> +> def summary(): +> return { +> "name": "OutlierRemovalAverageSummary", +> "lower-threshold": 0.0, +> "upper-threshold": 1.0, +> } +``` + +### scimark.py +Original file path: pyperformance/pyperformance/data-files/benchmarks/bm_scimark/run_benchmark.py +Changes made to the original file, as reported by the `diff` tool: +``` +3,4c3 +< +< import pyperf +--- +> import argparse +155d153 +< t0 = pyperf.perf_counter() +161,162d158 +< return pyperf.perf_counter() - t0 +< +166d161 +< t0 = pyperf.perf_counter() +175,176d169 +< return pyperf.perf_counter() - t0 +< +214d206 +< t0 = pyperf.perf_counter() +219,220d210 +< return pyperf.perf_counter() - t0 +< +263d252 +< t0 = pyperf.perf_counter() +268,269d256 +< return pyperf.perf_counter() - t0 +< +375d361 +< t0 = pyperf.perf_counter() +383,384d368 +< return pyperf.perf_counter() - t0 +< +393,397c377,381 +< 'sor': (bench_SOR, 100, 10, Array2D), +< 'sparse_mat_mult': (bench_SparseMatMult, 1000, 50 * 1000), +< 'monte_carlo': (bench_MonteCarlo, 100 * 1000,), +< 'lu': (bench_LU, 100,), +< 'fft': (bench_FFT, 1024, 50), +--- +> 'sor': (bench_SOR, 1, 100, 1, Array2D), +> 'sparse_mat_mult': (bench_SparseMatMult, 4, 1000, 50 * 1000), +> 'monte_carlo': (bench_MonteCarlo, 2, 10 * 1000,), +> 'lu': (bench_LU, 1, 50,), +> 'fft': (bench_FFT, 1, 1024, 5), +401,403c385,387 +< if __name__ == "__main__": +< runner = pyperf.Runner(add_cmdline_args=add_cmdline_args) +< runner.argparser.add_argument("benchmark", nargs='?', +--- +> def run(): +> parser = argparse.ArgumentParser(prog="python") +> parser.add_argument("benchmark", nargs='?', +406c390 +< args = runner.parse_args() +--- +> args = parser.parse_args() +413,415c397,414 +< name = 'scimark_%s' % bench +< args = BENCHMARKS[bench] +< runner.bench_time_func(name, *args) +--- +> func, *func_args = BENCHMARKS[bench] +> func(*func_args) +> +> +> def warmupIterations(): +> return 0 +> +> +> def iterations(): +> return 10 +> +> +> def summary(): +> return { +> "name": "OutlierRemovalAverageSummary", +> "lower-threshold": 0.0, +> "upper-threshold": 1.0, +> } +``` + +### spectral_norm.py +Original file path: pyperformance/pyperformance/data-files/benchmarks/bm_spectral_norm/run_benchmark.py +Changes made to the original file, as reported by the `diff` tool: +``` +15,16d14 +< import pyperf +< +51d48 +< t0 = pyperf.perf_counter() +66c63,73 +< return pyperf.perf_counter() - t0 +--- +> +> def run(): +> bench_spectral_norm(1) +> +> +> def warmupIterations(): +> return 0 +> +> +> def iterations(): +> return 10 +69,74c76,81 +< if __name__ == "__main__": +< runner = pyperf.Runner() +< runner.metadata['description'] = ( +< 'MathWorld: "Hundred-Dollar, Hundred-Digit Challenge Problems", ' +< 'Challenge #3.') +< runner.bench_time_func('spectral_norm', bench_spectral_norm) +--- +> def summary(): +> return { +> "name": "OutlierRemovalAverageSummary", +> "lower-threshold": 0.0, +> "upper-threshold": 1.0, +> } +``` + +### telco.py +Original file path: pyperformance/pyperformance/data-files/benchmarks/bm_telco/run_benchmark.py +Changes made to the original file, as reported by the `diff` tool: +``` +23,24d22 +< import pyperf +< +44d41 +< start = pyperf.perf_counter() +81d77 +< return pyperf.perf_counter() - start +82a79,81 +> def run(): +> filename = rel_path("data", "telco-bench.b") +> bench_telco(1, filename) +84,86d82 +< if __name__ == "__main__": +< runner = pyperf.Runner() +< runner.metadata['description'] = "Telco decimal benchmark" +88,89c84,101 +< filename = rel_path("data", "telco-bench.b") +< runner.bench_time_func('telco', bench_telco, filename) +--- +> def warmupIterations(): +> return 0 +> +> +> def iterations(): +> return 10 +> +> +> def summary(): +> return { +> "name": "OutlierRemovalAverageSummary", +> "lower-threshold": 0.0, +> "upper-threshold": 1.0, +> } +> +> +> def dependencies(): +> return ["data/telco-bench.b"] +``` + +### unpack_sequence.py +Original file path: pyperformance/pyperformance/data-files/benchmarks/bm_unpack_sequence/run_benchmark.py +Changes made to the original file, as reported by the `diff` tool: +``` +3c3 +< import pyperf +--- +> import argparse +8d7 +< t0 = pyperf.perf_counter() +413,414d411 +< return pyperf.perf_counter() - t0 +< +418c415 +< return do_unpacking(loops, x) +--- +> do_unpacking(loops, x) +424c421 +< return do_unpacking(loops, x) +--- +> do_unpacking(loops, x) +428,430c425,426 +< dt1 = bench_tuple_unpacking(loops) +< dt2 = bench_list_unpacking(loops) +< return dt1 + dt2 +--- +> bench_tuple_unpacking(loops) +> bench_list_unpacking(loops) +438c434 +< if __name__ == "__main__": +--- +> def run(): +442,446c438,439 +< runner = pyperf.Runner(add_cmdline_args=add_cmdline_args) +< runner.metadata['description'] = ("Microbenchmark for " +< "Python's sequence unpacking.") +< +< runner.argparser.add_argument("benchmark", nargs="?", +--- +> parser = argparse.ArgumentParser(prog="python") +> parser.add_argument("benchmark", nargs="?", +449c442 +< options = runner.parse_args() +--- +> options = parser.parse_args() +457c450,466 +< runner.bench_time_func(name, func, inner_loops=400) +--- +> func(8192) +> +> +> def warmupIterations(): +> return 0 +> +> +> def iterations(): +> return 10 +> +> +> def summary(): +> return { +> "name": "OutlierRemovalAverageSummary", +> "lower-threshold": 0.0, +> "upper-threshold": 1.0, +> } +``` + +### data/interpreter.tar.bz2 +Original file path: pyperformance/pyperformance/data-files/benchmarks/bm_pyflate/data/interpreter.tar.bz2 +Data file used for the `pyflate.py` benchmark. +No modifications made. + +### data/telco-bench.b +Original file path: pyperformance/pyperformance/data-files/benchmarks/bm_telco/data/telco-bench.b +Data file used for the `telco.py` benchmark. +No modifications made. + +## Original files necessary for benchmarking with the PolyBench harness + +These are new files that do not have a corresponding match in the numpy repository. +These files are generated to conform to the expectations of the PolyBench harness. + +### pickle_dict.py +Invokes the benchmark implemented in `bm_pickle.py` with the `["pickle_dict"]` argument value. +This file is the PolyBench equivalent of the pyperformance benchmark variant defined in the +`pyperformance/pyperformance/data-files/benchmarks/bm_pickle/bm_pickle_dict.toml` file. + +### pickle_list.py +Invokes the benchmark implemented in `bm_pickle.py` with the `["pickle_list"]` argument value. +This file is the PolyBench equivalent of the pyperformance benchmark variant defined in the +`pyperformance/pyperformance/data-files/benchmarks/bm_pickle/bm_pickle_list.toml` file. + +### unpickle_list.py +Invokes the benchmark implemented in `bm_pickle.py` with the `["unpickle_list"]` argument value. +This file is the PolyBench equivalent of the pyperformance benchmark variant defined in the +`pyperformance/pyperformance/data-files/benchmarks/bm_pickle/bm_unpickle_list.toml` file. + +### unpickle.py +Invokes the benchmark implemented in `bm_pickle.py` with the `["unpickle"]` argument value. +This file is the PolyBench equivalent of the pyperformance benchmark variant defined in the +`pyperformance/pyperformance/data-files/benchmarks/bm_pickle/bm_unpickle.toml` file. diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/bm_pathlib.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/bm_pathlib.py new file mode 100644 index 0000000000..ec7f2e01cd --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/bm_pathlib.py @@ -0,0 +1,76 @@ +""" +Test the performance of pathlib operations. + +This benchmark stresses the creation of small objects, globbing, and system +calls. +""" + +# Python imports +import os +import pathlib +import tempfile + + +NUM_FILES = 2000 + + +def generate_filenames(tmp_path, num_files): + i = 0 + while num_files: + for ext in [".py", ".txt", ".tar.gz", ""]: + i += 1 + yield os.path.join(tmp_path, str(i) + ext) + num_files -= 1 + + +tmp_path = None +def setup(): + global tmp_path + tmp_path = tempfile.mkdtemp() + for fn in generate_filenames(tmp_path, NUM_FILES): + with open(fn, "wb") as f: + f.write(b'benchmark') + + +def bench_pathlib(loops, tmp_path): + base_path = pathlib.Path(tmp_path) + + # Warm up the filesystem cache and keep some objects in memory. + path_objects = list(base_path.iterdir()) + # FIXME: does this code really cache anything? + for p in path_objects: + p.stat() + assert len(path_objects) == NUM_FILES, len(path_objects) + + range_it = range(loops) + + for _ in range_it: + # Do something simple with each path. + for p in base_path.iterdir(): + p.stat() + for p in base_path.glob("*.py"): + p.stat() + for p in base_path.iterdir(): + p.stat() + for p in base_path.glob("*.py"): + p.stat() + + +def run(): + bench_pathlib(8, tmp_path) + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/bm_pickle.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/bm_pickle.py new file mode 100644 index 0000000000..d4ec077eb6 --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/bm_pickle.py @@ -0,0 +1,287 @@ + +"""Script for testing the performance of pickling/unpickling. + +This will pickle/unpickle several real world-representative objects a few +thousand times. The methodology below was chosen for was chosen to be similar +to real-world scenarios which operate on single objects at a time. Note that if +we did something like + + pickle.dumps([dict(some_dict) for _ in range(10000)]) + +this isn't equivalent to dumping the dict 10000 times: pickle uses a +highly-efficient encoding for the n-1 following copies. +""" + +import datetime +import random +import sys +import argparse +import pickle + +__author__ = "collinwinter@google.com (Collin Winter)" + + +DICT = { + 'ads_flags': 0, + 'age': 18, + 'birthday': datetime.date(1980, 5, 7), + 'bulletin_count': 0, + 'comment_count': 0, + 'country': 'BR', + 'encrypted_id': 'G9urXXAJwjE', + 'favorite_count': 9, + 'first_name': '', + 'flags': 412317970704, + 'friend_count': 0, + 'gender': 'm', + 'gender_for_display': 'Male', + 'id': 302935349, + 'is_custom_profile_icon': 0, + 'last_name': '', + 'locale_preference': 'pt_BR', + 'member': 0, + 'tags': ['a', 'b', 'c', 'd', 'e', 'f', 'g'], + 'profile_foo_id': 827119638, + 'secure_encrypted_id': 'Z_xxx2dYx3t4YAdnmfgyKw', + 'session_number': 2, + 'signup_id': '201-19225-223', + 'status': 'A', + 'theme': 1, + 'time_created': 1225237014, + 'time_updated': 1233134493, + 'unread_message_count': 0, + 'user_group': '0', + 'username': 'collinwinter', + 'play_count': 9, + 'view_count': 7, + 'zip': ''} + +TUPLE = ( + [265867233, 265868503, 265252341, 265243910, 265879514, + 266219766, 266021701, 265843726, 265592821, 265246784, + 265853180, 45526486, 265463699, 265848143, 265863062, + 265392591, 265877490, 265823665, 265828884, 265753032], 60) + + +def mutate_dict(orig_dict, random_source): + new_dict = dict(orig_dict) + for key, value in new_dict.items(): + rand_val = random_source.random() * sys.maxsize + if isinstance(key, (int, bytes, str)): + new_dict[key] = type(key)(rand_val) + return new_dict + + +random_source = random.Random(5) # Fixed seed. +DICT_GROUP = [mutate_dict(DICT, random_source) for _ in range(3)] + + +def bench_pickle(loops, pickle, options): + range_it = range(loops) + + # micro-optimization: use fast local variables + dumps = pickle.dumps + objs = (DICT, TUPLE, DICT_GROUP) + protocol = options.protocol + + for _ in range_it: + for obj in objs: + # 20 dumps + dumps(obj, protocol) + dumps(obj, protocol) + dumps(obj, protocol) + dumps(obj, protocol) + dumps(obj, protocol) + dumps(obj, protocol) + dumps(obj, protocol) + dumps(obj, protocol) + dumps(obj, protocol) + dumps(obj, protocol) + dumps(obj, protocol) + dumps(obj, protocol) + dumps(obj, protocol) + dumps(obj, protocol) + dumps(obj, protocol) + dumps(obj, protocol) + dumps(obj, protocol) + dumps(obj, protocol) + dumps(obj, protocol) + dumps(obj, protocol) + + +def bench_unpickle(loops, pickle, options): + pickled_dict = pickle.dumps(DICT, options.protocol) + pickled_tuple = pickle.dumps(TUPLE, options.protocol) + pickled_dict_group = pickle.dumps(DICT_GROUP, options.protocol) + range_it = range(loops) + + # micro-optimization: use fast local variables + loads = pickle.loads + objs = (pickled_dict, pickled_tuple, pickled_dict_group) + + for _ in range_it: + for obj in objs: + # 20 loads dict + loads(obj) + loads(obj) + loads(obj) + loads(obj) + loads(obj) + loads(obj) + loads(obj) + loads(obj) + loads(obj) + loads(obj) + loads(obj) + loads(obj) + loads(obj) + loads(obj) + loads(obj) + loads(obj) + loads(obj) + loads(obj) + loads(obj) + loads(obj) + + +LIST = [[list(range(10)), list(range(10))] for _ in range(10)] + + +def bench_pickle_list(loops, pickle, options): + range_it = range(loops) + # micro-optimization: use fast local variables + dumps = pickle.dumps + obj = LIST + protocol = options.protocol + + for _ in range_it: + # 10 dumps list + dumps(obj, protocol) + dumps(obj, protocol) + dumps(obj, protocol) + dumps(obj, protocol) + dumps(obj, protocol) + dumps(obj, protocol) + dumps(obj, protocol) + dumps(obj, protocol) + dumps(obj, protocol) + dumps(obj, protocol) + + +def bench_unpickle_list(loops, pickle, options): + pickled_list = pickle.dumps(LIST, options.protocol) + range_it = range(loops) + + # micro-optimization: use fast local variables + loads = pickle.loads + + for _ in range_it: + # 10 loads list + loads(pickled_list) + loads(pickled_list) + loads(pickled_list) + loads(pickled_list) + loads(pickled_list) + loads(pickled_list) + loads(pickled_list) + loads(pickled_list) + loads(pickled_list) + loads(pickled_list) + + +MICRO_DICT = dict((key, dict.fromkeys(range(10))) for key in range(100)) + + +def bench_pickle_dict(loops, pickle, options): + range_it = range(loops) + # micro-optimization: use fast local variables + protocol = options.protocol + obj = MICRO_DICT + + for _ in range_it: + # 5 dumps dict + pickle.dumps(obj, protocol) + pickle.dumps(obj, protocol) + pickle.dumps(obj, protocol) + pickle.dumps(obj, protocol) + pickle.dumps(obj, protocol) + + +BENCHMARKS = { + # 20 inner-loops: don't count the 3 pickled objects + 'pickle': (bench_pickle, 20), + + # 20 inner-loops: don't count the 3 unpickled objects + 'unpickle': (bench_unpickle, 20), + + 'pickle_list': (bench_pickle_list, 10), + 'unpickle_list': (bench_unpickle_list, 10), + 'pickle_dict': (bench_pickle_dict, 5), +} + + +def is_accelerated_module(module): + return getattr(pickle.Pickler, '__module__', '') != 'pickle' + + +def add_cmdline_args(cmd, args): + if args.pure_python: + cmd.append("--pure-python") + cmd.extend(("--protocol", str(args.protocol))) + cmd.append(args.benchmark) + + +def run(): + __benchmark__(["pickle"]) + + +def __benchmark__(args): + parser = argparse.ArgumentParser(prog="python") + parser.add_argument("--pure-python", action="store_true", + help="Use the C version of pickle.") + parser.add_argument("--protocol", action="store", default=None, type=int, + help="Which protocol to use (default: highest protocol).") + benchmarks = sorted(BENCHMARKS) + parser.add_argument("benchmark", choices=benchmarks) + + options = parser.parse_args(args) + benchmark, _ = BENCHMARKS[options.benchmark] + + name = options.benchmark + if options.pure_python: + name += "_pure_python" + + if not options.pure_python: + # C accelerators are enabled by default on 3.x + import pickle + if not is_accelerated_module(pickle): + raise RuntimeError("Missing C accelerators for pickle") + else: + sys.modules['_pickle'] = None + import pickle + if is_accelerated_module(pickle): + raise RuntimeError("Unexpected C accelerators for pickle") + + if options.protocol is None: + options.protocol = pickle.HIGHEST_PROTOCOL + + benchmark(512, pickle, options) + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + +if __name__ == "__main__": + run() diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/bm_richards.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/bm_richards.py new file mode 100644 index 0000000000..90b72a3aec --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/bm_richards.py @@ -0,0 +1,434 @@ +""" +based on a Java version: + Based on original version written in BCPL by Dr Martin Richards + in 1981 at Cambridge University Computer Laboratory, England + and a C++ version derived from a Smalltalk version written by + L Peter Deutsch. + Java version: Copyright (C) 1995 Sun Microsystems, Inc. + Translation from C++, Mario Wolczko + Outer loop added by Alex Jacoby +""" + + +# Task IDs +I_IDLE = 1 +I_WORK = 2 +I_HANDLERA = 3 +I_HANDLERB = 4 +I_DEVA = 5 +I_DEVB = 6 + +# Packet types +K_DEV = 1000 +K_WORK = 1001 + +# Packet + +BUFSIZE = 4 + +BUFSIZE_RANGE = range(BUFSIZE) + + +class Packet(object): + + def __init__(self, l, i, k): + self.link = l + self.ident = i + self.kind = k + self.datum = 0 + self.data = [0] * BUFSIZE + + def append_to(self, lst): + self.link = None + if lst is None: + return self + else: + p = lst + next = p.link + while next is not None: + p = next + next = p.link + p.link = self + return lst + +# Task Records + + +class TaskRec(object): + pass + + +class DeviceTaskRec(TaskRec): + + def __init__(self): + self.pending = None + + +class IdleTaskRec(TaskRec): + + def __init__(self): + self.control = 1 + self.count = 10000 + + +class HandlerTaskRec(TaskRec): + + def __init__(self): + self.work_in = None + self.device_in = None + + def workInAdd(self, p): + self.work_in = p.append_to(self.work_in) + return self.work_in + + def deviceInAdd(self, p): + self.device_in = p.append_to(self.device_in) + return self.device_in + + +class WorkerTaskRec(TaskRec): + + def __init__(self): + self.destination = I_HANDLERA + self.count = 0 +# Task + + +class TaskState(object): + + def __init__(self): + self.packet_pending = True + self.task_waiting = False + self.task_holding = False + + def packetPending(self): + self.packet_pending = True + self.task_waiting = False + self.task_holding = False + return self + + def waiting(self): + self.packet_pending = False + self.task_waiting = True + self.task_holding = False + return self + + def running(self): + self.packet_pending = False + self.task_waiting = False + self.task_holding = False + return self + + def waitingWithPacket(self): + self.packet_pending = True + self.task_waiting = True + self.task_holding = False + return self + + def isPacketPending(self): + return self.packet_pending + + def isTaskWaiting(self): + return self.task_waiting + + def isTaskHolding(self): + return self.task_holding + + def isTaskHoldingOrWaiting(self): + return self.task_holding or (not self.packet_pending and self.task_waiting) + + def isWaitingWithPacket(self): + return self.packet_pending and self.task_waiting and not self.task_holding + + +tracing = False +layout = 0 + + +def trace(a): + global layout + layout -= 1 + if layout <= 0: + print() + layout = 50 + print(a, end='') + + +TASKTABSIZE = 10 + + +class TaskWorkArea(object): + + def __init__(self): + self.taskTab = [None] * TASKTABSIZE + + self.taskList = None + + self.holdCount = 0 + self.qpktCount = 0 + + +taskWorkArea = TaskWorkArea() + + +class Task(TaskState): + + def __init__(self, i, p, w, initialState, r): + self.link = taskWorkArea.taskList + self.ident = i + self.priority = p + self.input = w + + self.packet_pending = initialState.isPacketPending() + self.task_waiting = initialState.isTaskWaiting() + self.task_holding = initialState.isTaskHolding() + + self.handle = r + + taskWorkArea.taskList = self + taskWorkArea.taskTab[i] = self + + def fn(self, pkt, r): + raise NotImplementedError + + def addPacket(self, p, old): + if self.input is None: + self.input = p + self.packet_pending = True + if self.priority > old.priority: + return self + else: + p.append_to(self.input) + return old + + def runTask(self): + if self.isWaitingWithPacket(): + msg = self.input + self.input = msg.link + if self.input is None: + self.running() + else: + self.packetPending() + else: + msg = None + + return self.fn(msg, self.handle) + + def waitTask(self): + self.task_waiting = True + return self + + def hold(self): + taskWorkArea.holdCount += 1 + self.task_holding = True + return self.link + + def release(self, i): + t = self.findtcb(i) + t.task_holding = False + if t.priority > self.priority: + return t + else: + return self + + def qpkt(self, pkt): + t = self.findtcb(pkt.ident) + taskWorkArea.qpktCount += 1 + pkt.link = None + pkt.ident = self.ident + return t.addPacket(pkt, self) + + def findtcb(self, id): + t = taskWorkArea.taskTab[id] + if t is None: + raise Exception("Bad task id %d" % id) + return t + + +# DeviceTask + + +class DeviceTask(Task): + + def __init__(self, i, p, w, s, r): + Task.__init__(self, i, p, w, s, r) + + def fn(self, pkt, r): + d = r + assert isinstance(d, DeviceTaskRec) + if pkt is None: + pkt = d.pending + if pkt is None: + return self.waitTask() + else: + d.pending = None + return self.qpkt(pkt) + else: + d.pending = pkt + if tracing: + trace(pkt.datum) + return self.hold() + + +class HandlerTask(Task): + + def __init__(self, i, p, w, s, r): + Task.__init__(self, i, p, w, s, r) + + def fn(self, pkt, r): + h = r + assert isinstance(h, HandlerTaskRec) + if pkt is not None: + if pkt.kind == K_WORK: + h.workInAdd(pkt) + else: + h.deviceInAdd(pkt) + work = h.work_in + if work is None: + return self.waitTask() + count = work.datum + if count >= BUFSIZE: + h.work_in = work.link + return self.qpkt(work) + + dev = h.device_in + if dev is None: + return self.waitTask() + + h.device_in = dev.link + dev.datum = work.data[count] + work.datum = count + 1 + return self.qpkt(dev) + +# IdleTask + + +class IdleTask(Task): + + def __init__(self, i, p, w, s, r): + Task.__init__(self, i, 0, None, s, r) + + def fn(self, pkt, r): + i = r + assert isinstance(i, IdleTaskRec) + i.count -= 1 + if i.count == 0: + return self.hold() + elif i.control & 1 == 0: + i.control //= 2 + return self.release(I_DEVA) + else: + i.control = i.control // 2 ^ 0xd008 + return self.release(I_DEVB) + + +# WorkTask + + +A = ord('A') + + +class WorkTask(Task): + + def __init__(self, i, p, w, s, r): + Task.__init__(self, i, p, w, s, r) + + def fn(self, pkt, r): + w = r + assert isinstance(w, WorkerTaskRec) + if pkt is None: + return self.waitTask() + + if w.destination == I_HANDLERA: + dest = I_HANDLERB + else: + dest = I_HANDLERA + + w.destination = dest + pkt.ident = dest + pkt.datum = 0 + + for i in BUFSIZE_RANGE: # range(BUFSIZE) + w.count += 1 + if w.count > 26: + w.count = 1 + pkt.data[i] = A + w.count - 1 + + return self.qpkt(pkt) + + +def schedule(): + t = taskWorkArea.taskList + while t is not None: + if tracing: + print("tcb =", t.ident) + + if t.isTaskHoldingOrWaiting(): + t = t.link + else: + if tracing: + trace(chr(ord("0") + t.ident)) + t = t.runTask() + + +class Richards(object): + + def run(self, iterations): + for i in range(iterations): + taskWorkArea.holdCount = 0 + taskWorkArea.qpktCount = 0 + + IdleTask(I_IDLE, 1, 10000, TaskState().running(), IdleTaskRec()) + + wkq = Packet(None, 0, K_WORK) + wkq = Packet(wkq, 0, K_WORK) + WorkTask(I_WORK, 1000, wkq, TaskState( + ).waitingWithPacket(), WorkerTaskRec()) + + wkq = Packet(None, I_DEVA, K_DEV) + wkq = Packet(wkq, I_DEVA, K_DEV) + wkq = Packet(wkq, I_DEVA, K_DEV) + HandlerTask(I_HANDLERA, 2000, wkq, TaskState( + ).waitingWithPacket(), HandlerTaskRec()) + + wkq = Packet(None, I_DEVB, K_DEV) + wkq = Packet(wkq, I_DEVB, K_DEV) + wkq = Packet(wkq, I_DEVB, K_DEV) + HandlerTask(I_HANDLERB, 3000, wkq, TaskState( + ).waitingWithPacket(), HandlerTaskRec()) + + wkq = None + DeviceTask(I_DEVA, 4000, wkq, + TaskState().waiting(), DeviceTaskRec()) + DeviceTask(I_DEVB, 5000, wkq, + TaskState().waiting(), DeviceTaskRec()) + + schedule() + + if taskWorkArea.holdCount == 9297 and taskWorkArea.qpktCount == 23246: + pass + else: + return False + + return True + + +def run(): + richard = Richards() + richard.run(1) + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/chaos.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/chaos.py new file mode 100644 index 0000000000..008938367b --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/chaos.py @@ -0,0 +1,314 @@ +"""create chaosgame-like fractals + +Copyright (C) 2005 Carl Friedrich Bolz +""" + +import math +import random +import argparse + + +DEFAULT_THICKNESS = 0.25 +DEFAULT_WIDTH = 256 +DEFAULT_HEIGHT = 256 +DEFAULT_ITERATIONS = 5000 +DEFAULT_RNG_SEED = 1234 + + +class GVector(object): + + def __init__(self, x=0, y=0, z=0): + self.x = x + self.y = y + self.z = z + + def Mag(self): + return math.sqrt(self.x ** 2 + self.y ** 2 + self.z ** 2) + + def dist(self, other): + return math.sqrt((self.x - other.x) ** 2 + + (self.y - other.y) ** 2 + + (self.z - other.z) ** 2) + + def __add__(self, other): + if not isinstance(other, GVector): + raise ValueError("Can't add GVector to " + str(type(other))) + v = GVector(self.x + other.x, self.y + other.y, self.z + other.z) + return v + + def __sub__(self, other): + return self + other * -1 + + def __mul__(self, other): + v = GVector(self.x * other, self.y * other, self.z * other) + return v + __rmul__ = __mul__ + + def linear_combination(self, other, l1, l2=None): + if l2 is None: + l2 = 1 - l1 + v = GVector(self.x * l1 + other.x * l2, + self.y * l1 + other.y * l2, + self.z * l1 + other.z * l2) + return v + + def __str__(self): + return "<%f, %f, %f>" % (self.x, self.y, self.z) + + def __repr__(self): + return "GVector(%f, %f, %f)" % (self.x, self.y, self.z) + + +class Spline(object): + """Class for representing B-Splines and NURBS of arbitrary degree""" + + def __init__(self, points, degree, knots): + """Creates a Spline. + + points is a list of GVector, degree is the degree of the Spline. + """ + if len(points) > len(knots) - degree + 1: + raise ValueError("too many control points") + elif len(points) < len(knots) - degree + 1: + raise ValueError("not enough control points") + last = knots[0] + for cur in knots[1:]: + if cur < last: + raise ValueError("knots not strictly increasing") + last = cur + self.knots = knots + self.points = points + self.degree = degree + + def GetDomain(self): + """Returns the domain of the B-Spline""" + return (self.knots[self.degree - 1], + self.knots[len(self.knots) - self.degree]) + + def __call__(self, u): + """Calculates a point of the B-Spline using de Boors Algorithm""" + dom = self.GetDomain() + if u < dom[0] or u > dom[1]: + raise ValueError("Function value not in domain") + if u == dom[0]: + return self.points[0] + if u == dom[1]: + return self.points[-1] + I = self.GetIndex(u) + d = [self.points[I - self.degree + 1 + ii] + for ii in range(self.degree + 1)] + U = self.knots + for ik in range(1, self.degree + 1): + for ii in range(I - self.degree + ik + 1, I + 2): + ua = U[ii + self.degree - ik] + ub = U[ii - 1] + co1 = (ua - u) / (ua - ub) + co2 = (u - ub) / (ua - ub) + index = ii - I + self.degree - ik - 1 + d[index] = d[index].linear_combination(d[index + 1], co1, co2) + return d[0] + + def GetIndex(self, u): + dom = self.GetDomain() + for ii in range(self.degree - 1, len(self.knots) - self.degree): + if u >= self.knots[ii] and u < self.knots[ii + 1]: + I = ii + break + else: + I = dom[1] - 1 + return I + + def __len__(self): + return len(self.points) + + def __repr__(self): + return "Spline(%r, %r, %r)" % (self.points, self.degree, self.knots) + + +def write_ppm(im, filename): + magic = 'P6\n' + maxval = 255 + w = len(im) + h = len(im[0]) + + with open(filename, "w", encoding="latin1", newline='') as fp: + fp.write(magic) + fp.write('%i %i\n%i\n' % (w, h, maxval)) + for j in range(h): + for i in range(w): + val = im[i][j] + c = val * 255 + fp.write('%c%c%c' % (c, c, c)) + + +class Chaosgame(object): + + def __init__(self, splines, thickness=0.1): + self.splines = splines + self.thickness = thickness + self.minx = min([p.x for spl in splines for p in spl.points]) + self.miny = min([p.y for spl in splines for p in spl.points]) + self.maxx = max([p.x for spl in splines for p in spl.points]) + self.maxy = max([p.y for spl in splines for p in spl.points]) + self.height = self.maxy - self.miny + self.width = self.maxx - self.minx + self.num_trafos = [] + maxlength = thickness * self.width / self.height + for spl in splines: + length = 0 + curr = spl(0) + for i in range(1, 1000): + last = curr + t = 1 / 999 * i + curr = spl(t) + length += curr.dist(last) + self.num_trafos.append(max(1, int(length / maxlength * 1.5))) + self.num_total = sum(self.num_trafos) + + def get_random_trafo(self): + r = random.randrange(int(self.num_total) + 1) + l = 0 + for i in range(len(self.num_trafos)): + if r >= l and r < l + self.num_trafos[i]: + return i, random.randrange(self.num_trafos[i]) + l += self.num_trafos[i] + return len(self.num_trafos) - 1, random.randrange(self.num_trafos[-1]) + + def transform_point(self, point, trafo=None): + x = (point.x - self.minx) / self.width + y = (point.y - self.miny) / self.height + if trafo is None: + trafo = self.get_random_trafo() + start, end = self.splines[trafo[0]].GetDomain() + length = end - start + seg_length = length / self.num_trafos[trafo[0]] + t = start + seg_length * trafo[1] + seg_length * x + basepoint = self.splines[trafo[0]](t) + if t + 1 / 50000 > end: + neighbour = self.splines[trafo[0]](t - 1 / 50000) + derivative = neighbour - basepoint + else: + neighbour = self.splines[trafo[0]](t + 1 / 50000) + derivative = basepoint - neighbour + if derivative.Mag() != 0: + basepoint.x += derivative.y / derivative.Mag() * (y - 0.5) * \ + self.thickness + basepoint.y += -derivative.x / derivative.Mag() * (y - 0.5) * \ + self.thickness + else: + print("r", end='') + self.truncate(basepoint) + return basepoint + + def truncate(self, point): + if point.x >= self.maxx: + point.x = self.maxx + if point.y >= self.maxy: + point.y = self.maxy + if point.x < self.minx: + point.x = self.minx + if point.y < self.miny: + point.y = self.miny + + def create_image_chaos(self, w, h, iterations, filename, rng_seed): + # Always use the same sequence of random numbers + # to get reproductible benchmark + random.seed(rng_seed) + + im = [[1] * h for i in range(w)] + point = GVector((self.maxx + self.minx) / 2, + (self.maxy + self.miny) / 2, 0) + for _ in range(iterations): + point = self.transform_point(point) + x = (point.x - self.minx) / self.width * w + y = (point.y - self.miny) / self.height * h + x = int(x) + y = int(y) + if x == w: + x -= 1 + if y == h: + y -= 1 + im[x][h - y - 1] = 0 + + if filename: + write_ppm(im, filename) + + +def __benchmark__(args): + splines = [ + Spline([ + GVector(1.597350, 3.304460, 0.000000), + GVector(1.575810, 4.123260, 0.000000), + GVector(1.313210, 5.288350, 0.000000), + GVector(1.618900, 5.329910, 0.000000), + GVector(2.889940, 5.502700, 0.000000), + GVector(2.373060, 4.381830, 0.000000), + GVector(1.662000, 4.360280, 0.000000)], + 3, [0, 0, 0, 1, 1, 1, 2, 2, 2]), + Spline([ + GVector(2.804500, 4.017350, 0.000000), + GVector(2.550500, 3.525230, 0.000000), + GVector(1.979010, 2.620360, 0.000000), + GVector(1.979010, 2.620360, 0.000000)], + 3, [0, 0, 0, 1, 1, 1]), + Spline([ + GVector(2.001670, 4.011320, 0.000000), + GVector(2.335040, 3.312830, 0.000000), + GVector(2.366800, 3.233460, 0.000000), + GVector(2.366800, 3.233460, 0.000000)], + 3, [0, 0, 0, 1, 1, 1]) + ] + + chaos = Chaosgame(splines, args.thickness) + chaos.create_image_chaos(args.width, args.height, args.iterations, args.filename, args.rng_seed) + + +def add_cmdline_args(cmd, args): + cmd.append("--width=%s" % args.width) + cmd.append("--height=%s" % args.height) + cmd.append("--thickness=%s" % args.thickness) + cmd.append("--rng-seed=%s" % args.rng_seed) + if args.filename: + cmd.extend(("--filename", args.filename)) + + +def run(): + cmd = argparse.ArgumentParser(prog="python") + cmd.add_argument("--thickness", + type=float, default=DEFAULT_THICKNESS, + help="Thickness (default: %s)" % DEFAULT_THICKNESS) + cmd.add_argument("--width", + type=int, default=DEFAULT_WIDTH, + help="Image width (default: %s)" % DEFAULT_WIDTH) + cmd.add_argument("--height", + type=int, default=DEFAULT_HEIGHT, + help="Image height (default: %s)" % DEFAULT_HEIGHT) + cmd.add_argument("--iterations", + type=int, default=DEFAULT_ITERATIONS, + help="Number of iterations (default: %s)" + % DEFAULT_ITERATIONS) + cmd.add_argument("--filename", metavar="FILENAME.PPM", + help="Output filename of the PPM picture") + cmd.add_argument("--rng-seed", + type=int, default=DEFAULT_RNG_SEED, + help="Random number generator seed (default: %s)" + % DEFAULT_RNG_SEED) + + args = cmd.parse_args() + __benchmark__(args) + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/data/interpreter.tar.bz2 b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/data/interpreter.tar.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..67bf5a89ebca32037c3fe8091cc51f240cfd9bfc GIT binary patch literal 67562 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 literal 0 HcmV?d00001 diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/fannkuch.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/fannkuch.py new file mode 100644 index 0000000000..f802721521 --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/fannkuch.py @@ -0,0 +1,66 @@ +""" +The Computer Language Benchmarks Game +http://benchmarksgame.alioth.debian.org/ + +Contributed by Sokolov Yura, modified by Tupteq. +""" + + +DEFAULT_ARG = 9 + + +def fannkuch(n): + count = list(range(1, n + 1)) + max_flips = 0 + m = n - 1 + r = n + perm1 = list(range(n)) + perm = list(range(n)) + perm1_ins = perm1.insert + perm1_pop = perm1.pop + + while 1: + while r != 1: + count[r - 1] = r + r -= 1 + + if perm1[0] != 0 and perm1[m] != m: + perm = perm1[:] + flips_count = 0 + k = perm[0] + while k: + perm[:k + 1] = perm[k::-1] + flips_count += 1 + k = perm[0] + + if flips_count > max_flips: + max_flips = flips_count + + while r != n: + perm1_ins(r, perm1_pop(0)) + count[r] -= 1 + if count[r] > 0: + break + r += 1 + else: + return max_flips + + +def run(): + fannkuch(DEFAULT_ARG) + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/float.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/float.py new file mode 100644 index 0000000000..3db5c78379 --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/float.py @@ -0,0 +1,70 @@ +""" +Artificial, floating point-heavy benchmark originally used by Factor. +""" +from math import sin, cos, sqrt + + +POINTS = 100000 + + +class Point(object): + __slots__ = ('x', 'y', 'z') + + def __init__(self, i): + self.x = x = sin(i) + self.y = cos(i) * 3 + self.z = (x * x) / 2 + + def __repr__(self): + return "" % (self.x, self.y, self.z) + + def normalize(self): + x = self.x + y = self.y + z = self.z + norm = sqrt(x * x + y * y + z * z) + self.x /= norm + self.y /= norm + self.z /= norm + + def maximize(self, other): + self.x = self.x if self.x > other.x else other.x + self.y = self.y if self.y > other.y else other.y + self.z = self.z if self.z > other.z else other.z + return self + + +def maximize(points): + next = points[0] + for p in points[1:]: + next = next.maximize(p) + return next + + +def benchmark(n): + points = [None] * n + for i in range(n): + points[i] = Point(i) + for p in points: + p.normalize() + return maximize(points) + + +def run(): + benchmark(POINTS) + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/go.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/go.py new file mode 100644 index 0000000000..cd43765c73 --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/go.py @@ -0,0 +1,469 @@ +""" +Go board game +""" +import math +import random + + +SIZE = 9 +GAMES = 200 +KOMI = 7.5 +EMPTY, WHITE, BLACK = 0, 1, 2 +SHOW = {EMPTY: '.', WHITE: 'o', BLACK: 'x'} +PASS = -1 +MAXMOVES = SIZE * SIZE * 3 +TIMESTAMP = 0 +MOVES = 0 + + +def to_pos(x, y): + return y * SIZE + x + + +def to_xy(pos): + y, x = divmod(pos, SIZE) + return x, y + + +class Square: + + def __init__(self, board, pos): + self.board = board + self.pos = pos + self.timestamp = TIMESTAMP + self.removestamp = TIMESTAMP + self.zobrist_strings = [random.randrange(9223372036854775807) + for i in range(3)] + + def set_neighbours(self): + x, y = self.pos % SIZE, self.pos // SIZE + self.neighbours = [] + for dx, dy in [(-1, 0), (1, 0), (0, -1), (0, 1)]: + newx, newy = x + dx, y + dy + if 0 <= newx < SIZE and 0 <= newy < SIZE: + self.neighbours.append(self.board.squares[to_pos(newx, newy)]) + + def move(self, color): + global TIMESTAMP, MOVES + TIMESTAMP += 1 + MOVES += 1 + self.board.zobrist.update(self, color) + self.color = color + self.reference = self + self.ledges = 0 + self.used = True + for neighbour in self.neighbours: + neighcolor = neighbour.color + if neighcolor == EMPTY: + self.ledges += 1 + else: + neighbour_ref = neighbour.find(update=True) + if neighcolor == color: + if neighbour_ref.reference.pos != self.pos: + self.ledges += neighbour_ref.ledges + neighbour_ref.reference = self + self.ledges -= 1 + else: + neighbour_ref.ledges -= 1 + if neighbour_ref.ledges == 0: + neighbour.remove(neighbour_ref) + self.board.zobrist.add() + + def remove(self, reference, update=True): + self.board.zobrist.update(self, EMPTY) + self.removestamp = TIMESTAMP + if update: + self.color = EMPTY + self.board.emptyset.add(self.pos) +# if color == BLACK: +# self.board.black_dead += 1 +# else: +# self.board.white_dead += 1 + for neighbour in self.neighbours: + if neighbour.color != EMPTY and neighbour.removestamp != TIMESTAMP: + neighbour_ref = neighbour.find(update) + if neighbour_ref.pos == reference.pos: + neighbour.remove(reference, update) + else: + if update: + neighbour_ref.ledges += 1 + + def find(self, update=False): + reference = self.reference + if reference.pos != self.pos: + reference = reference.find(update) + if update: + self.reference = reference + return reference + + def __repr__(self): + return repr(to_xy(self.pos)) + + +class EmptySet: + + def __init__(self, board): + self.board = board + self.empties = list(range(SIZE * SIZE)) + self.empty_pos = list(range(SIZE * SIZE)) + + def random_choice(self): + choices = len(self.empties) + while choices: + i = int(random.random() * choices) + pos = self.empties[i] + if self.board.useful(pos): + return pos + choices -= 1 + self.set(i, self.empties[choices]) + self.set(choices, pos) + return PASS + + def add(self, pos): + self.empty_pos[pos] = len(self.empties) + self.empties.append(pos) + + def remove(self, pos): + self.set(self.empty_pos[pos], self.empties[len(self.empties) - 1]) + self.empties.pop() + + def set(self, i, pos): + self.empties[i] = pos + self.empty_pos[pos] = i + + +class ZobristHash: + + def __init__(self, board): + self.board = board + self.hash_set = set() + self.hash = 0 + for square in self.board.squares: + self.hash ^= square.zobrist_strings[EMPTY] + self.hash_set.clear() + self.hash_set.add(self.hash) + + def update(self, square, color): + self.hash ^= square.zobrist_strings[square.color] + self.hash ^= square.zobrist_strings[color] + + def add(self): + self.hash_set.add(self.hash) + + def dupe(self): + return self.hash in self.hash_set + + +class Board: + + def __init__(self): + self.squares = [Square(self, pos) for pos in range(SIZE * SIZE)] + for square in self.squares: + square.set_neighbours() + self.reset() + + def reset(self): + for square in self.squares: + square.color = EMPTY + square.used = False + self.emptyset = EmptySet(self) + self.zobrist = ZobristHash(self) + self.color = BLACK + self.finished = False + self.lastmove = -2 + self.history = [] + self.white_dead = 0 + self.black_dead = 0 + + def move(self, pos): + square = self.squares[pos] + if pos != PASS: + square.move(self.color) + self.emptyset.remove(square.pos) + elif self.lastmove == PASS: + self.finished = True + if self.color == BLACK: + self.color = WHITE + else: + self.color = BLACK + self.lastmove = pos + self.history.append(pos) + + def random_move(self): + return self.emptyset.random_choice() + + def useful_fast(self, square): + if not square.used: + for neighbour in square.neighbours: + if neighbour.color == EMPTY: + return True + return False + + def useful(self, pos): + global TIMESTAMP + TIMESTAMP += 1 + square = self.squares[pos] + if self.useful_fast(square): + return True + old_hash = self.zobrist.hash + self.zobrist.update(square, self.color) + empties = opps = weak_opps = neighs = weak_neighs = 0 + for neighbour in square.neighbours: + neighcolor = neighbour.color + if neighcolor == EMPTY: + empties += 1 + continue + neighbour_ref = neighbour.find() + if neighbour_ref.timestamp != TIMESTAMP: + if neighcolor == self.color: + neighs += 1 + else: + opps += 1 + neighbour_ref.timestamp = TIMESTAMP + neighbour_ref.temp_ledges = neighbour_ref.ledges + neighbour_ref.temp_ledges -= 1 + if neighbour_ref.temp_ledges == 0: + if neighcolor == self.color: + weak_neighs += 1 + else: + weak_opps += 1 + neighbour_ref.remove(neighbour_ref, update=False) + dupe = self.zobrist.dupe() + self.zobrist.hash = old_hash + strong_neighs = neighs - weak_neighs + strong_opps = opps - weak_opps + return not dupe and \ + (empties or weak_opps or (strong_neighs and (strong_opps or weak_neighs))) + + def useful_moves(self): + return [pos for pos in self.emptyset.empties if self.useful(pos)] + + def replay(self, history): + for pos in history: + self.move(pos) + + def score(self, color): + if color == WHITE: + count = KOMI + self.black_dead + else: + count = self.white_dead + for square in self.squares: + squarecolor = square.color + if squarecolor == color: + count += 1 + elif squarecolor == EMPTY: + surround = 0 + for neighbour in square.neighbours: + if neighbour.color == color: + surround += 1 + if surround == len(square.neighbours): + count += 1 + return count + + def check(self): + for square in self.squares: + if square.color == EMPTY: + continue + + members1 = set([square]) + changed = True + while changed: + changed = False + for member in members1.copy(): + for neighbour in member.neighbours: + if neighbour.color == square.color and neighbour not in members1: + changed = True + members1.add(neighbour) + ledges1 = 0 + for member in members1: + for neighbour in member.neighbours: + if neighbour.color == EMPTY: + ledges1 += 1 + + root = square.find() + + # print 'members1', square, root, members1 + # print 'ledges1', square, ledges1 + + members2 = set() + for square2 in self.squares: + if square2.color != EMPTY and square2.find() == root: + members2.add(square2) + + ledges2 = root.ledges + # print 'members2', square, root, members1 + # print 'ledges2', square, ledges2 + + assert members1 == members2 + assert ledges1 == ledges2, ('ledges differ at %r: %d %d' % ( + square, ledges1, ledges2)) + + set(self.emptyset.empties) + + empties2 = set() + for square in self.squares: + if square.color == EMPTY: + empties2.add(square.pos) + + def __repr__(self): + result = [] + for y in range(SIZE): + start = to_pos(0, y) + result.append(''.join( + [SHOW[square.color] + ' ' for square in self.squares[start:start + SIZE]])) + return '\n'.join(result) + + +class UCTNode: + + def __init__(self): + self.bestchild = None + self.pos = -1 + self.wins = 0 + self.losses = 0 + self.pos_child = [None for x in range(SIZE * SIZE)] + self.parent = None + + def play(self, board): + """ uct tree search """ + color = board.color + node = self + path = [node] + while True: + pos = node.select(board) + if pos == PASS: + break + board.move(pos) + child = node.pos_child[pos] + if not child: + child = node.pos_child[pos] = UCTNode() + child.unexplored = board.useful_moves() + child.pos = pos + child.parent = node + path.append(child) + break + path.append(child) + node = child + self.random_playout(board) + self.update_path(board, color, path) + + def select(self, board): + """ select move; unexplored children first, then according to uct value """ + if self.unexplored: + i = random.randrange(len(self.unexplored)) + pos = self.unexplored[i] + self.unexplored[i] = self.unexplored[len(self.unexplored) - 1] + self.unexplored.pop() + return pos + elif self.bestchild: + return self.bestchild.pos + else: + return PASS + + def random_playout(self, board): + """ random play until both players pass """ + for x in range(MAXMOVES): # XXX while not self.finished? + if board.finished: + break + board.move(board.random_move()) + + def update_path(self, board, color, path): + """ update win/loss count along path """ + wins = board.score(BLACK) >= board.score(WHITE) + for node in path: + if color == BLACK: + color = WHITE + else: + color = BLACK + if wins == (color == BLACK): + node.wins += 1 + else: + node.losses += 1 + if node.parent: + node.parent.bestchild = node.parent.best_child() + + def score(self): + winrate = self.wins / float(self.wins + self.losses) + parentvisits = self.parent.wins + self.parent.losses + if not parentvisits: + return winrate + nodevisits = self.wins + self.losses + return winrate + math.sqrt((math.log(parentvisits)) / (5 * nodevisits)) + + def best_child(self): + maxscore = -1 + maxchild = None + for child in self.pos_child: + if child and child.score() > maxscore: + maxchild = child + maxscore = child.score() + return maxchild + + def best_visited(self): + maxvisits = -1 + maxchild = None + for child in self.pos_child: + # if child: + # print to_xy(child.pos), child.wins, child.losses, child.score() + if child and (child.wins + child.losses) > maxvisits: + maxvisits, maxchild = (child.wins + child.losses), child + return maxchild + + +# def user_move(board): +# while True: +# text = input('?').strip() +# if text == 'p': +# return PASS +# if text == 'q': +# raise EOFError +# try: +# x, y = [int(i) for i in text.split()] +# except ValueError: +# continue +# if not (0 <= x < SIZE and 0 <= y < SIZE): +# continue +# pos = to_pos(x, y) +# if board.useful(pos): +# return pos + + +def computer_move(board): + pos = board.random_move() + if pos == PASS: + return PASS + tree = UCTNode() + tree.unexplored = board.useful_moves() + nboard = Board() + for game in range(GAMES): + node = tree + nboard.reset() + nboard.replay(board.history) + node.play(nboard) + return tree.best_visited().pos + + +def versus_cpu(): + random.seed(1) + board = Board() + return computer_move(board) + + +def run(): + versus_cpu() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/hexiom.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/hexiom.py new file mode 100644 index 0000000000..596f0876a3 --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/hexiom.py @@ -0,0 +1,673 @@ +""" +Solver of Hexiom board game. + +Benchmark from Laurent Vaucher. + +Source: https://github.com/slowfrog/hexiom : hexiom2.py, level36.txt + +(Main function tweaked by Armin Rigo.) +""" + +import io +import argparse + +# 2016-07-07: CPython 3.6 takes ~25 ms to solve the board level 25 +DEFAULT_LEVEL = 25 + + +################################## +class Dir(object): + + def __init__(self, x, y): + self.x = x + self.y = y + + +DIRS = [Dir(1, 0), + Dir(-1, 0), + Dir(0, 1), + Dir(0, -1), + Dir(1, 1), + Dir(-1, -1)] + +EMPTY = 7 + +################################## + + +class Done(object): + MIN_CHOICE_STRATEGY = 0 + MAX_CHOICE_STRATEGY = 1 + HIGHEST_VALUE_STRATEGY = 2 + FIRST_STRATEGY = 3 + MAX_NEIGHBORS_STRATEGY = 4 + MIN_NEIGHBORS_STRATEGY = 5 + + def __init__(self, count, empty=False): + self.count = count + self.cells = None if empty else [ + [0, 1, 2, 3, 4, 5, 6, EMPTY] for i in range(count)] + + def clone(self): + ret = Done(self.count, True) + ret.cells = [self.cells[i][:] for i in range(self.count)] + return ret + + def __getitem__(self, i): + return self.cells[i] + + def set_done(self, i, v): + self.cells[i] = [v] + + def already_done(self, i): + return len(self.cells[i]) == 1 + + def remove(self, i, v): + if v in self.cells[i]: + self.cells[i].remove(v) + return True + else: + return False + + def remove_all(self, v): + for i in range(self.count): + self.remove(i, v) + + def remove_unfixed(self, v): + changed = False + for i in range(self.count): + if not self.already_done(i): + if self.remove(i, v): + changed = True + return changed + + def filter_tiles(self, tiles): + for v in range(8): + if tiles[v] == 0: + self.remove_all(v) + + def next_cell_min_choice(self): + minlen = 10 + mini = -1 + for i in range(self.count): + if 1 < len(self.cells[i]) < minlen: + minlen = len(self.cells[i]) + mini = i + return mini + + def next_cell_max_choice(self): + maxlen = 1 + maxi = -1 + for i in range(self.count): + if maxlen < len(self.cells[i]): + maxlen = len(self.cells[i]) + maxi = i + return maxi + + def next_cell_highest_value(self): + maxval = -1 + maxi = -1 + for i in range(self.count): + if (not self.already_done(i)): + maxvali = max(k for k in self.cells[i] if k != EMPTY) + if maxval < maxvali: + maxval = maxvali + maxi = i + return maxi + + def next_cell_first(self): + for i in range(self.count): + if (not self.already_done(i)): + return i + return -1 + + def next_cell_max_neighbors(self, pos): + maxn = -1 + maxi = -1 + for i in range(self.count): + if not self.already_done(i): + cells_around = pos.hex.get_by_id(i).links + n = sum(1 if (self.already_done(nid) and (self[nid][0] != EMPTY)) else 0 + for nid in cells_around) + if n > maxn: + maxn = n + maxi = i + return maxi + + def next_cell_min_neighbors(self, pos): + minn = 7 + mini = -1 + for i in range(self.count): + if not self.already_done(i): + cells_around = pos.hex.get_by_id(i).links + n = sum(1 if (self.already_done(nid) and (self[nid][0] != EMPTY)) else 0 + for nid in cells_around) + if n < minn: + minn = n + mini = i + return mini + + def next_cell(self, pos, strategy=HIGHEST_VALUE_STRATEGY): + if strategy == Done.HIGHEST_VALUE_STRATEGY: + return self.next_cell_highest_value() + elif strategy == Done.MIN_CHOICE_STRATEGY: + return self.next_cell_min_choice() + elif strategy == Done.MAX_CHOICE_STRATEGY: + return self.next_cell_max_choice() + elif strategy == Done.FIRST_STRATEGY: + return self.next_cell_first() + elif strategy == Done.MAX_NEIGHBORS_STRATEGY: + return self.next_cell_max_neighbors(pos) + elif strategy == Done.MIN_NEIGHBORS_STRATEGY: + return self.next_cell_min_neighbors(pos) + else: + raise Exception("Wrong strategy: %d" % strategy) + +################################## + + +class Node(object): + + def __init__(self, pos, id, links): + self.pos = pos + self.id = id + self.links = links + +################################## + + +class Hex(object): + + def __init__(self, size): + self.size = size + self.count = 3 * size * (size - 1) + 1 + self.nodes_by_id = self.count * [None] + self.nodes_by_pos = {} + id = 0 + for y in range(size): + for x in range(size + y): + pos = (x, y) + node = Node(pos, id, []) + self.nodes_by_pos[pos] = node + self.nodes_by_id[node.id] = node + id += 1 + for y in range(1, size): + for x in range(y, size * 2 - 1): + ry = size + y - 1 + pos = (x, ry) + node = Node(pos, id, []) + self.nodes_by_pos[pos] = node + self.nodes_by_id[node.id] = node + id += 1 + + def link_nodes(self): + for node in self.nodes_by_id: + (x, y) = node.pos + for dir in DIRS: + nx = x + dir.x + ny = y + dir.y + if self.contains_pos((nx, ny)): + node.links.append(self.nodes_by_pos[(nx, ny)].id) + + def contains_pos(self, pos): + return pos in self.nodes_by_pos + + def get_by_pos(self, pos): + return self.nodes_by_pos[pos] + + def get_by_id(self, id): + return self.nodes_by_id[id] + + +################################## +class Pos(object): + + def __init__(self, hex, tiles, done=None): + self.hex = hex + self.tiles = tiles + self.done = Done(hex.count) if done is None else done + + def clone(self): + return Pos(self.hex, self.tiles, self.done.clone()) + +################################## + + +def constraint_pass(pos, last_move=None): + changed = False + left = pos.tiles[:] + done = pos.done + + # Remove impossible values from free cells + free_cells = (range(done.count) if last_move is None + else pos.hex.get_by_id(last_move).links) + for i in free_cells: + if not done.already_done(i): + vmax = 0 + vmin = 0 + cells_around = pos.hex.get_by_id(i).links + for nid in cells_around: + if done.already_done(nid): + if done[nid][0] != EMPTY: + vmin += 1 + vmax += 1 + else: + vmax += 1 + + for num in range(7): + if (num < vmin) or (num > vmax): + if done.remove(i, num): + changed = True + + # Computes how many of each value is still free + for cell in done.cells: + if len(cell) == 1: + left[cell[0]] -= 1 + + for v in range(8): + # If there is none, remove the possibility from all tiles + if (pos.tiles[v] > 0) and (left[v] == 0): + if done.remove_unfixed(v): + changed = True + else: + possible = sum((1 if v in cell else 0) for cell in done.cells) + # If the number of possible cells for a value is exactly the number of available tiles + # put a tile in each cell + if pos.tiles[v] == possible: + for i in range(done.count): + cell = done.cells[i] + if (not done.already_done(i)) and (v in cell): + done.set_done(i, v) + changed = True + + # Force empty or non-empty around filled cells + filled_cells = (range(done.count) if last_move is None + else [last_move]) + for i in filled_cells: + if done.already_done(i): + num = done[i][0] + empties = 0 + filled = 0 + unknown = [] + cells_around = pos.hex.get_by_id(i).links + for nid in cells_around: + if done.already_done(nid): + if done[nid][0] == EMPTY: + empties += 1 + else: + filled += 1 + else: + unknown.append(nid) + if len(unknown) > 0: + if num == filled: + for u in unknown: + if EMPTY in done[u]: + done.set_done(u, EMPTY) + changed = True + # else: + # raise Exception("Houston, we've got a problem") + elif num == filled + len(unknown): + for u in unknown: + if done.remove(u, EMPTY): + changed = True + + return changed + + +ASCENDING = 1 +DESCENDING = -1 + + +def find_moves(pos, strategy, order): + done = pos.done + cell_id = done.next_cell(pos, strategy) + if cell_id < 0: + return [] + + if order == ASCENDING: + return [(cell_id, v) for v in done[cell_id]] + else: + # Try higher values first and EMPTY last + moves = list(reversed([(cell_id, v) + for v in done[cell_id] if v != EMPTY])) + if EMPTY in done[cell_id]: + moves.append((cell_id, EMPTY)) + return moves + + +def play_move(pos, move): + (cell_id, i) = move + pos.done.set_done(cell_id, i) + + +def print_pos(pos, output): + hex = pos.hex + done = pos.done + size = hex.size + for y in range(size): + print(" " * (size - y - 1), end="", file=output) + for x in range(size + y): + pos2 = (x, y) + id = hex.get_by_pos(pos2).id + if done.already_done(id): + c = str(done[id][0]) if done[id][0] != EMPTY else "." + else: + c = "?" + print("%s " % c, end="", file=output) + print(end="\n", file=output) + for y in range(1, size): + print(" " * y, end="", file=output) + for x in range(y, size * 2 - 1): + ry = size + y - 1 + pos2 = (x, ry) + id = hex.get_by_pos(pos2).id + if done.already_done(id): + c = str(done[id][0]) if done[id][0] != EMPTY else "." + else: + c = "?" + print("%s " % c, end="", file=output) + print(end="\n", file=output) + + +OPEN = 0 +SOLVED = 1 +IMPOSSIBLE = -1 + + +def solved(pos, output, verbose=False): + hex = pos.hex + tiles = pos.tiles[:] + done = pos.done + exact = True + all_done = True + for i in range(hex.count): + if len(done[i]) == 0: + return IMPOSSIBLE + elif done.already_done(i): + num = done[i][0] + tiles[num] -= 1 + if (tiles[num] < 0): + return IMPOSSIBLE + vmax = 0 + vmin = 0 + if num != EMPTY: + cells_around = hex.get_by_id(i).links + for nid in cells_around: + if done.already_done(nid): + if done[nid][0] != EMPTY: + vmin += 1 + vmax += 1 + else: + vmax += 1 + + if (num < vmin) or (num > vmax): + return IMPOSSIBLE + if num != vmin: + exact = False + else: + all_done = False + + if (not all_done) or (not exact): + return OPEN + + print_pos(pos, output) + return SOLVED + + +def solve_step(prev, strategy, order, output, first=False): + if first: + pos = prev.clone() + while constraint_pass(pos): + pass + else: + pos = prev + + moves = find_moves(pos, strategy, order) + if len(moves) == 0: + return solved(pos, output) + else: + for move in moves: + # print("Trying (%d, %d)" % (move[0], move[1])) + ret = OPEN + new_pos = pos.clone() + play_move(new_pos, move) + # print_pos(new_pos) + while constraint_pass(new_pos, move[0]): + pass + cur_status = solved(new_pos, output) + if cur_status != OPEN: + ret = cur_status + else: + ret = solve_step(new_pos, strategy, order, output) + if ret == SOLVED: + return SOLVED + return IMPOSSIBLE + + +def check_valid(pos): + hex = pos.hex + tiles = pos.tiles + # fill missing entries in tiles + tot = 0 + for i in range(8): + if tiles[i] > 0: + tot += tiles[i] + else: + tiles[i] = 0 + # check total + if tot != hex.count: + raise Exception( + "Invalid input. Expected %d tiles, got %d." % (hex.count, tot)) + + +def solve(pos, strategy, order, output): + check_valid(pos) + return solve_step(pos, strategy, order, output, first=True) + + +# TODO Write an 'iterator' to go over all x,y positions + +def read_file(file): + lines = [line.strip("\r\n") for line in file.splitlines()] + size = int(lines[0]) + hex = Hex(size) + linei = 1 + tiles = 8 * [0] + done = Done(hex.count) + for y in range(size): + line = lines[linei][size - y - 1:] + p = 0 + for x in range(size + y): + tile = line[p:p + 2] + p += 2 + if tile[1] == ".": + inctile = EMPTY + else: + inctile = int(tile) + tiles[inctile] += 1 + # Look for locked tiles + if tile[0] == "+": + # print("Adding locked tile: %d at pos %d, %d, id=%d" % + # (inctile, x, y, hex.get_by_pos((x, y)).id)) + done.set_done(hex.get_by_pos((x, y)).id, inctile) + + linei += 1 + for y in range(1, size): + ry = size - 1 + y + line = lines[linei][y:] + p = 0 + for x in range(y, size * 2 - 1): + tile = line[p:p + 2] + p += 2 + if tile[1] == ".": + inctile = EMPTY + else: + inctile = int(tile) + tiles[inctile] += 1 + # Look for locked tiles + if tile[0] == "+": + # print("Adding locked tile: %d at pos %d, %d, id=%d" % + # (inctile, x, ry, hex.get_by_pos((x, ry)).id)) + done.set_done(hex.get_by_pos((x, ry)).id, inctile) + linei += 1 + hex.link_nodes() + done.filter_tiles(tiles) + return Pos(hex, tiles, done) + + +def solve_file(file, strategy, order, output): + pos = read_file(file) + solve(pos, strategy, order, output) + + +LEVELS = {} + +LEVELS[2] = (""" +2 + . 1 + . 1 1 + 1 . +""", """\ + 1 1 +. . . + 1 1 +""") + +LEVELS[10] = (""" +3 + +.+. . + +. 0 . 2 + . 1+2 1 . + 2 . 0+. + .+.+. +""", """\ + . . 1 + . 1 . 2 +0 . 2 2 . + . . . . + 0 . . +""") + +LEVELS[20] = (""" +3 + . 5 4 + . 2+.+1 + . 3+2 3 . + +2+. 5 . + . 3 . +""", """\ + 3 3 2 + 4 5 . 1 +3 5 2 . . + 2 . . . + . . . +""") + +LEVELS[25] = (""" +3 + 4 . . + . . 2 . + 4 3 2 . 4 + 2 2 3 . + 4 2 4 +""", """\ + 3 4 2 + 2 4 4 . +. . . 4 2 + . 2 4 3 + . 2 . +""") + +LEVELS[30] = (""" +4 + 5 5 . . + 3 . 2+2 6 + 3 . 2 . 5 . + . 3 3+4 4 . 3 + 4 5 4 . 5 4 + 5+2 . . 3 + 4 . . . +""", """\ + 3 4 3 . + 4 6 5 2 . + 2 5 5 . . 2 +. . 5 4 . 4 3 + . 3 5 4 5 4 + . 2 . 3 3 + . . . . +""") + +LEVELS[36] = (""" +4 + 2 1 1 2 + 3 3 3 . . + 2 3 3 . 4 . + . 2 . 2 4 3 2 + 2 2 . . . 2 + 4 3 4 . . + 3 2 3 3 +""", """\ + 3 4 3 2 + 3 4 4 . 3 + 2 . . 3 4 3 +2 . 1 . 3 . 2 + 3 3 . 2 . 2 + 3 . 2 . 2 + 2 2 . 1 +""") + + +def __benchmark__(loops, level): + board, solution = LEVELS[level] + order = DESCENDING + strategy = Done.FIRST_STRATEGY + stream = io.StringIO() + + board = board.strip() + expected = solution.rstrip() + + range_it = range(loops) + + for _ in range_it: + stream = io.StringIO() + solve_file(board, strategy, order, stream) + output = stream.getvalue() + stream = None + + output = '\n'.join(line.rstrip() for line in output.splitlines()) + if output != expected: + raise AssertionError("got a wrong answer:\n%s\nexpected: %s" + % (output, expected)) + + +def add_cmdline_args(cmd, args): + cmd.extend(("--level", str(args.level))) + + +def run(): + levels = sorted(LEVELS) + parser = argparse.ArgumentParser(prog="python") + parser.add_argument("--level", type=int, + choices=levels, + default=DEFAULT_LEVEL, + help="Hexiom board level (default: %s)" + % DEFAULT_LEVEL) + + args = parser.parse_args() + __benchmark__(16, args.level) + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/json_dumps.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/json_dumps.py new file mode 100644 index 0000000000..40c514703e --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/json_dumps.py @@ -0,0 +1,69 @@ +import json +import sys +import argparse + + +EMPTY = ({}, 2000) +SIMPLE_DATA = {'key1': 0, 'key2': True, 'key3': 'value', 'key4': 'foo', + 'key5': 'string'} +SIMPLE = (SIMPLE_DATA, 1000) +NESTED_DATA = {'key1': 0, 'key2': SIMPLE[0], 'key3': 'value', 'key4': SIMPLE[0], + 'key5': SIMPLE[0], 'key': '\u0105\u0107\u017c'} +NESTED = (NESTED_DATA, 1000) +HUGE = ([NESTED[0]] * 1000, 1) + +CASES = ['EMPTY', 'SIMPLE', 'NESTED', 'HUGE'] + + +def bench_json_dumps(data): + for obj, count_it in data: + for _ in count_it: + json.dumps(obj) + + +def add_cmdline_args(cmd, args): + if args.cases: + cmd.extend(("--cases", args.cases)) + + +def run(): + parser = argparse.ArgumentParser(prog="python") + parser.add_argument("--cases", + help="Comma separated list of cases. Available cases: %s. By default, run all cases." + % ', '.join(CASES)) + + args = parser.parse_args() + if args.cases: + cases = [] + for case in args.cases.split(','): + case = case.strip() + if case: + cases.append(case) + if not cases: + print("ERROR: empty list of cases") + sys.exit(1) + else: + cases = CASES + + data = [] + for case in cases: + obj, count = globals()[case] + data.append((obj, range(count))) + + bench_json_dumps(data) + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/json_loads.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/json_loads.py new file mode 100644 index 0000000000..be37c1e169 --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/json_loads.py @@ -0,0 +1,115 @@ + +"""Script for testing the performance of json parsing and serialization. + +This will dump/load several real world-representative objects a few +thousand times. The methodology below was chosen for was chosen to be similar +to real-world scenarios which operate on single objects at a time. +""" + +# Python imports +import json +import random +import sys + + +DICT = { + 'ads_flags': 0, + 'age': 18, + 'bulletin_count': 0, + 'comment_count': 0, + 'country': 'BR', + 'encrypted_id': 'G9urXXAJwjE', + 'favorite_count': 9, + 'first_name': '', + 'flags': 412317970704, + 'friend_count': 0, + 'gender': 'm', + 'gender_for_display': 'Male', + 'id': 302935349, + 'is_custom_profile_icon': 0, + 'last_name': '', + 'locale_preference': 'pt_BR', + 'member': 0, + 'tags': ['a', 'b', 'c', 'd', 'e', 'f', 'g'], + 'profile_foo_id': 827119638, + 'secure_encrypted_id': 'Z_xxx2dYx3t4YAdnmfgyKw', + 'session_number': 2, + 'signup_id': '201-19225-223', + 'status': 'A', + 'theme': 1, + 'time_created': 1225237014, + 'time_updated': 1233134493, + 'unread_message_count': 0, + 'user_group': '0', + 'username': 'collinwinter', + 'play_count': 9, + 'view_count': 7, + 'zip': ''} + +TUPLE = ( + [265867233, 265868503, 265252341, 265243910, 265879514, + 266219766, 266021701, 265843726, 265592821, 265246784, + 265853180, 45526486, 265463699, 265848143, 265863062, + 265392591, 265877490, 265823665, 265828884, 265753032], 60) + + +def mutate_dict(orig_dict, random_source): + new_dict = dict(orig_dict) + for key, value in new_dict.items(): + rand_val = random_source.random() * sys.maxsize + if isinstance(key, (int, bytes, str)): + new_dict[key] = type(key)(rand_val) + return new_dict + + +random_source = random.Random(5) # Fixed seed. +DICT_GROUP = [mutate_dict(DICT, random_source) for _ in range(3)] + + +def bench_json_loads(objs): + for obj in objs: + # 20 loads + json.loads(obj) + json.loads(obj) + json.loads(obj) + json.loads(obj) + json.loads(obj) + json.loads(obj) + json.loads(obj) + json.loads(obj) + json.loads(obj) + json.loads(obj) + json.loads(obj) + json.loads(obj) + json.loads(obj) + json.loads(obj) + json.loads(obj) + json.loads(obj) + json.loads(obj) + json.loads(obj) + json.loads(obj) + json.loads(obj) + + +def run(): + json_dict = json.dumps(DICT) + json_tuple = json.dumps(TUPLE) + json_dict_group = json.dumps(DICT_GROUP) + objs = (json_dict, json_tuple, json_dict_group) + bench_json_loads(objs) + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/meteor_contest.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/meteor_contest.py new file mode 100644 index 0000000000..ec8be6098b --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/meteor_contest.py @@ -0,0 +1,231 @@ +""" +Meteor Puzzle board: +http://benchmarksgame.alioth.debian.org/u32/meteor-description.html#meteor + +The Computer Language Benchmarks Game +http://benchmarksgame.alioth.debian.org/ + +contributed by Daniel Nanz, 2008-08-21 +""" + +from bisect import bisect + + +SOLVE_ARG = 60 + +WIDTH, HEIGHT = 5, 10 +DIR_NO = 6 +S, E = WIDTH * HEIGHT, 2 +SE = S + (E / 2) +SW = SE - E +W, NW, NE = -E, -SE, -SW + +SOLUTIONS = [ + '00001222012661126155865558633348893448934747977799', + '00001222012771127148774485464855968596835966399333', + '00001222012771127148774485494855998596835966366333', + '00001222012771127148774485994855948596835966366333', + '00001222012771127166773863384653846538445584959999', + '00001222012771127183778834833348555446554666969999', + '00001222012771127183778834833348555446554966699996', + '00001223012331123166423564455647456775887888979999', + '00001555015541144177484726877268222683336689399993', + '00001555015541144177484728677286222863338669399993', + '00001599015591159148594482224827748276837766366333', + '00001777017871184155845558449984669662932629322333', + '00004222042664426774996879687759811598315583153331', + '00004222042774427384773183331866118615586555969999', + '00004223042334423784523785771855718566186611969999', + '00004227042874428774528735833155831566316691169999', + '00004333045534455384175781777812228116286662969999', + '00004333045934459384559185991866118612286727267772', + '00004333047734427384277182221866118615586555969999', + '00004555045514411224172621768277368736683339899998', + '00004555045514411224172721777299998966836688368333', + '00004555045534413334132221177266172677886888969999', + '00004555045534473334739967792617926192661882211888', + '00004555045564466694699992288828811233317273177731', + '00004555045564466694699997773172731233312881122888', + '00004555045564496664999962288828811233317273177731', + '00004555045564496664999967773172731233312881122888', + '00004555045584411884171187722866792679236992369333', + '00004555045584411884191189999832226333267372677766', + '00004555045584411884191189999866222623336727367773', + '13335138551389511895778697869947762446624022240000', + '13777137271333211882888226999946669446554055540000', + '13777137271333211882888229999649666446554055540000', + '27776272768221681166819958195548395443954033340000', + '33322392623926696648994485554855148117871077710000', + '33366366773867284772842228449584195119551099510000', + '33366366953869584955849958447784172117721022210000', + '33366366953869589955849458447784172117721022210000', + '33386388663866989999277712727142211441554055540000', + '33396329963297629766822778117148811448554055540000', + '33399366953869586955846458447784172117721022210000', + '37776372763332622266899998119148811448554055540000', + '39999396683336822268277682748477144114551055510000', + '39999398663338622286277862748477144114551055510000', + '66777627376233362223899998119148811448554055540000', + '69999666945564455584333843887738172117721022210000', + '88811228816629162971629776993743337443554055540000', + '88822118821333213727137776999946669446554055540000', + '88822118821333213727137779999649666446554055540000', + '89999893338663786377286712627142211441554055540000', + '99777974743984439884333685556855162116621022210000', + '99995948554483564835648336837766172117721022210000', + '99996119661366513855133853782547782447824072240000', + '99996911668166581755817758732548732443324032240000', + '99996926668261182221877718757148355443554033340000', + '99996955568551681166812228177248372443774033340000', + '99996955568551681166813338137748372447724022240000', + '99996966645564455584333843887738172117721022210000', + '99996988868877627166277112223143331443554055540000', + '99997988878857765474655446532466132113321032210000'] + + +def rotate(ido, rd={E: NE, NE: NW, NW: W, W: SW, SW: SE, SE: E}): + return [rd[o] for o in ido] + + +def flip(ido, fd={E: E, NE: SE, NW: SW, W: W, SW: NW, SE: NE}): + return [fd[o] for o in ido] + + +def permute(ido, r_ido, rotate=rotate, flip=flip): + ps = [ido] + for r in range(DIR_NO - 1): + ps.append(rotate(ps[-1])) + if ido == r_ido: # C2-symmetry + ps = ps[0:DIR_NO // 2] + for pp in ps[:]: + ps.append(flip(pp)) + return ps + + +def convert(ido): + '''incremental direction offsets -> "coordinate offsets" ''' + out = [0] + for o in ido: + out.append(out[-1] + o) + return list(set(out)) + + +def get_footprints(board, cti, pieces): + fps = [[[] for p in range(len(pieces))] for ci in range(len(board))] + for c in board: + for pi, p in enumerate(pieces): + for pp in p: + fp = frozenset([cti[c + o] for o in pp if (c + o) in cti]) + if len(fp) == 5: + fps[min(fp)][pi].append(fp) + return fps + + +def get_senh(board, cti): + '''-> south-east neighborhood''' + se_nh = [] + nh = [E, SW, SE] + for c in board: + se_nh.append(frozenset([cti[c + o] for o in nh if (c + o) in cti])) + return se_nh + + +def get_puzzle(width, height): + board = [E * x + S * y + (y % 2) + for y in range(height) + for x in range(width)] + cti = dict((board[i], i) for i in range(len(board))) + + # Incremental direction offsets + idos = [[E, E, E, SE], + [SE, SW, W, SW], + [W, W, SW, SE], + [E, E, SW, SE], + [NW, W, NW, SE, SW], + [E, E, NE, W], + [NW, NE, NE, W], + [NE, SE, E, NE], + [SE, SE, E, SE], + [E, NW, NW, NW]] + + # Restrict piece 4 + perms = (permute(p, idos[3]) for p in idos) + pieces = [[convert(pp) for pp in p] for p in perms] + return (board, cti, pieces) + + +def solve(n, i_min, free, curr_board, pieces_left, solutions, fps, se_nh, + # Hack to use a fast local variable to avoid a global lookup + bisect=bisect): + + fp_i_cands = fps[i_min] + for p in pieces_left: + fp_cands = fp_i_cands[p] + for fp in fp_cands: + if fp <= free: + n_curr_board = curr_board[:] + for ci in fp: + n_curr_board[ci] = p + + if len(pieces_left) > 1: + n_free = free - fp + n_i_min = min(n_free) + if len(n_free & se_nh[n_i_min]) > 0: + n_pieces_left = pieces_left[:] + n_pieces_left.remove(p) + solve(n, n_i_min, n_free, n_curr_board, + n_pieces_left, solutions, fps, se_nh) + else: + s = ''.join(map(str, n_curr_board)) + solutions.insert(bisect(solutions, s), s) + rs = s[::-1] + solutions.insert(bisect(solutions, rs), rs) + if len(solutions) >= n: + return + + if len(solutions) >= n: + return + + +def bench_meteor_contest(loops, board, pieces, solve_arg, fps, se_nh): + range_it = range(loops) + + for _ in range_it: + free = frozenset(range(len(board))) + curr_board = [-1] * len(board) + pieces_left = list(range(len(pieces))) + solutions = [] + solve(solve_arg, 0, free, curr_board, pieces_left, + solutions, fps, se_nh) + + if solutions != SOLUTIONS: + raise ValueError("unexpected solutions") + + +def __benchmark__(): + board, cti, pieces = get_puzzle(WIDTH, HEIGHT) + fps = get_footprints(board, cti, pieces) + se_nh = get_senh(board, cti) + + solve_arg = SOLVE_ARG + bench_meteor_contest(1, board, pieces, solve_arg, fps, se_nh) + + +def run(): + __benchmark__() + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/nbody.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/nbody.py new file mode 100644 index 0000000000..f25816e09d --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/nbody.py @@ -0,0 +1,167 @@ +""" +N-body benchmark from the Computer Language Benchmarks Game. + +This is intended to support Unladen Swallow's pyperf.py. Accordingly, it has been +modified from the Shootout version: +- Accept standard Unladen Swallow benchmark options. +- Run report_energy()/advance() in a loop. +- Reimplement itertools.combinations() to work with older Python versions. + +Pulled from: +http://benchmarksgame.alioth.debian.org/u64q/program.php?test=nbody&lang=python3&id=1 + +Contributed by Kevin Carson. +Modified by Tupteq, Fredrik Johansson, and Daniel Nanz. +""" + +import argparse + +__contact__ = "collinwinter@google.com (Collin Winter)" +DEFAULT_ITERATIONS = 20000 +DEFAULT_REFERENCE = 'sun' + + +def combinations(l): + """Pure-Python implementation of itertools.combinations(l, 2).""" + result = [] + for x in range(len(l) - 1): + ls = l[x + 1:] + for y in ls: + result.append((l[x], y)) + return result + + +PI = 3.14159265358979323 +SOLAR_MASS = 4 * PI * PI +DAYS_PER_YEAR = 365.24 + +BODIES = { + 'sun': ([0.0, 0.0, 0.0], [0.0, 0.0, 0.0], SOLAR_MASS), + + 'jupiter': ([4.84143144246472090e+00, + -1.16032004402742839e+00, + -1.03622044471123109e-01], + [1.66007664274403694e-03 * DAYS_PER_YEAR, + 7.69901118419740425e-03 * DAYS_PER_YEAR, + -6.90460016972063023e-05 * DAYS_PER_YEAR], + 9.54791938424326609e-04 * SOLAR_MASS), + + 'saturn': ([8.34336671824457987e+00, + 4.12479856412430479e+00, + -4.03523417114321381e-01], + [-2.76742510726862411e-03 * DAYS_PER_YEAR, + 4.99852801234917238e-03 * DAYS_PER_YEAR, + 2.30417297573763929e-05 * DAYS_PER_YEAR], + 2.85885980666130812e-04 * SOLAR_MASS), + + 'uranus': ([1.28943695621391310e+01, + -1.51111514016986312e+01, + -2.23307578892655734e-01], + [2.96460137564761618e-03 * DAYS_PER_YEAR, + 2.37847173959480950e-03 * DAYS_PER_YEAR, + -2.96589568540237556e-05 * DAYS_PER_YEAR], + 4.36624404335156298e-05 * SOLAR_MASS), + + 'neptune': ([1.53796971148509165e+01, + -2.59193146099879641e+01, + 1.79258772950371181e-01], + [2.68067772490389322e-03 * DAYS_PER_YEAR, + 1.62824170038242295e-03 * DAYS_PER_YEAR, + -9.51592254519715870e-05 * DAYS_PER_YEAR], + 5.15138902046611451e-05 * SOLAR_MASS)} + + +SYSTEM = list(BODIES.values()) +PAIRS = combinations(SYSTEM) + + +def advance(dt, n, bodies=SYSTEM, pairs=PAIRS): + for i in range(n): + for (([x1, y1, z1], v1, m1), + ([x2, y2, z2], v2, m2)) in pairs: + dx = x1 - x2 + dy = y1 - y2 + dz = z1 - z2 + mag = dt * ((dx * dx + dy * dy + dz * dz) ** (-1.5)) + b1m = m1 * mag + b2m = m2 * mag + v1[0] -= dx * b2m + v1[1] -= dy * b2m + v1[2] -= dz * b2m + v2[0] += dx * b1m + v2[1] += dy * b1m + v2[2] += dz * b1m + for (r, [vx, vy, vz], m) in bodies: + r[0] += dt * vx + r[1] += dt * vy + r[2] += dt * vz + + +def report_energy(bodies=SYSTEM, pairs=PAIRS, e=0.0): + for (((x1, y1, z1), v1, m1), + ((x2, y2, z2), v2, m2)) in pairs: + dx = x1 - x2 + dy = y1 - y2 + dz = z1 - z2 + e -= (m1 * m2) / ((dx * dx + dy * dy + dz * dz) ** 0.5) + for (r, [vx, vy, vz], m) in bodies: + e += m * (vx * vx + vy * vy + vz * vz) / 2. + return e + + +def offset_momentum(ref, bodies=SYSTEM, px=0.0, py=0.0, pz=0.0): + for (r, [vx, vy, vz], m) in bodies: + px -= vx * m + py -= vy * m + pz -= vz * m + (r, v, m) = ref + v[0] = px / m + v[1] = py / m + v[2] = pz / m + + +def bench_nbody(loops, reference, iterations): + # Set up global state + offset_momentum(BODIES[reference]) + + range_it = range(loops) + + for _ in range_it: + report_energy() + advance(0.01, iterations) + report_energy() + + +def add_cmdline_args(cmd, args): + cmd.extend(("--iterations", str(args.iterations))) + + +def run(): + parser = argparse.ArgumentParser(prog="python") + parser.add_argument("--iterations", + type=int, default=DEFAULT_ITERATIONS, + help="Number of nbody advance() iterations " + "(default: %s)" % DEFAULT_ITERATIONS) + parser.add_argument("--reference", + type=str, default=DEFAULT_REFERENCE, + help="nbody reference (default: %s)" + % DEFAULT_REFERENCE) + + args = parser.parse_args() + bench_nbody(1, args.reference, args.iterations) + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/nqueens.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/nqueens.py new file mode 100644 index 0000000000..61e3eb6547 --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/nqueens.py @@ -0,0 +1,72 @@ +"""Simple, brute-force N-Queens solver.""" + +__author__ = "collinwinter@google.com (Collin Winter)" + + +# Pure-Python implementation of itertools.permutations(). +def permutations(iterable, r=None): + """permutations(range(3), 2) --> (0,1) (0,2) (1,0) (1,2) (2,0) (2,1)""" + pool = tuple(iterable) + n = len(pool) + if r is None: + r = n + indices = list(range(n)) + cycles = list(range(n - r + 1, n + 1))[::-1] + yield tuple(pool[i] for i in indices[:r]) + while n: + for i in reversed(range(r)): + cycles[i] -= 1 + if cycles[i] == 0: + indices[i:] = indices[i + 1:] + indices[i:i + 1] + cycles[i] = n - i + else: + j = cycles[i] + indices[i], indices[-j] = indices[-j], indices[i] + yield tuple(pool[i] for i in indices[:r]) + break + else: + return + + +# From http://code.activestate.com/recipes/576647/ +def n_queens(queen_count): + """N-Queens solver. + + Args: + queen_count: the number of queens to solve for. This is also the + board size. + + Yields: + Solutions to the problem. Each yielded value is looks like + (3, 8, 2, 1, 4, ..., 6) where each number is the column position for the + queen, and the index into the tuple indicates the row. + """ + cols = range(queen_count) + for vec in permutations(cols): + if (queen_count == len(set(vec[i] + i for i in cols)) + == len(set(vec[i] - i for i in cols))): + yield vec + + +def bench_n_queens(queen_count): + list(n_queens(queen_count)) + + +def run(): + bench_n_queens(8) + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/pickle_dict.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/pickle_dict.py new file mode 100644 index 0000000000..b74c4ebfaf --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/pickle_dict.py @@ -0,0 +1,28 @@ +import sys +import os +# Add benchmark directory to path to allow import of bm_pickle.py +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +import bm_pickle + +def run(): + bm_pickle.__benchmark__(["pickle_dict"]) + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + return ["bm_pickle.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/pickle_list.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/pickle_list.py new file mode 100644 index 0000000000..f4bd72b3fc --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/pickle_list.py @@ -0,0 +1,28 @@ +import sys +import os +# Add benchmark directory to path to allow import of bm_pickle.py +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +import bm_pickle + +def run(): + bm_pickle.__benchmark__(["pickle_list"]) + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + return ["bm_pickle.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/pidigits.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/pidigits.py new file mode 100644 index 0000000000..ecf859d56a --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/pidigits.py @@ -0,0 +1,81 @@ +# coding: utf-8 +""" +Calculating some of the digits of π. + +This benchmark stresses big integer arithmetic. + +Adapted from code on: +http://benchmarksgame.alioth.debian.org/ +""" + +import itertools +import argparse + + +DEFAULT_DIGITS = 2000 +icount = itertools.count +islice = itertools.islice + + +def gen_x(): + return map(lambda k: (k, 4 * k + 2, 0, 2 * k + 1), icount(1)) + + +def compose(a, b): + aq, ar, as_, at = a + bq, br, bs, bt = b + return (aq * bq, + aq * br + ar * bt, + as_ * bq + at * bs, + as_ * br + at * bt) + + +def extract(z, j): + q, r, s, t = z + return (q * j + r) // (s * j + t) + + +def gen_pi_digits(): + z = (1, 0, 0, 1) + x = gen_x() + while 1: + y = extract(z, 3) + while y != extract(z, 4): + z = compose(z, next(x)) + y = extract(z, 3) + z = compose((10, -10 * y, 0, 1), z) + yield y + + +def calc_ndigits(n): + return list(islice(gen_pi_digits(), n)) + + +def add_cmdline_args(cmd, args): + cmd.extend(("--digits", str(args.digits))) + + +def run(): + cmd = argparse.ArgumentParser(prog="python") + cmd.add_argument("--digits", type=int, default=DEFAULT_DIGITS, + help="Number of computed pi digits (default: %s)" + % DEFAULT_DIGITS) + + args = cmd.parse_args() + calc_ndigits(args.digits) + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/pyflate.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/pyflate.py new file mode 100755 index 0000000000..2372fae59f --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/pyflate.py @@ -0,0 +1,676 @@ +#!/usr/bin/env python +""" +Copyright 2006--2007-01-21 Paul Sladen +http://www.paul.sladen.org/projects/compression/ + +You may use and distribute this code under any DFSG-compatible +license (eg. BSD, GNU GPLv2). + +Stand-alone pure-Python DEFLATE (gzip) and bzip2 decoder/decompressor. +This is probably most useful for research purposes/index building; there +is certainly some room for improvement in the Huffman bit-matcher. + +With the as-written implementation, there was a known bug in BWT +decoding to do with repeated strings. This has been worked around; +see 'bwt_reverse()'. Correct output is produced in all test cases +but ideally the problem would be found... +""" + +import hashlib +import os +import struct + + +int2byte = struct.Struct(">B").pack + + +class BitfieldBase(object): + + def __init__(self, x): + if isinstance(x, BitfieldBase): + self.f = x.f + self.bits = x.bits + self.bitfield = x.bitfield + self.count = x.bitfield + else: + self.f = x + self.bits = 0 + self.bitfield = 0x0 + self.count = 0 + + def _read(self, n): + s = self.f.read(n) + if not s: + raise "Length Error" + self.count += len(s) + return s + + def needbits(self, n): + while self.bits < n: + self._more() + + def _mask(self, n): + return (1 << n) - 1 + + def toskip(self): + return self.bits & 0x7 + + def align(self): + self.readbits(self.toskip()) + + def dropbits(self, n=8): + while n >= self.bits and n > 7: + n -= self.bits + self.bits = 0 + n -= len(self.f._read(n >> 3)) << 3 + if n: + self.readbits(n) + # No return value + + def dropbytes(self, n=1): + self.dropbits(n << 3) + + def tell(self): + return self.count - ((self.bits + 7) >> 3), 7 - ((self.bits - 1) & 0x7) + + def tellbits(self): + bytes, bits = self.tell() + return (bytes << 3) + bits + + +class Bitfield(BitfieldBase): + + def _more(self): + c = self._read(1) + self.bitfield += ord(c) << self.bits + self.bits += 8 + + def snoopbits(self, n=8): + if n > self.bits: + self.needbits(n) + return self.bitfield & self._mask(n) + + def readbits(self, n=8): + if n > self.bits: + self.needbits(n) + r = self.bitfield & self._mask(n) + self.bits -= n + self.bitfield >>= n + return r + + +class RBitfield(BitfieldBase): + + def _more(self): + c = self._read(1) + self.bitfield <<= 8 + self.bitfield += ord(c) + self.bits += 8 + + def snoopbits(self, n=8): + if n > self.bits: + self.needbits(n) + return (self.bitfield >> (self.bits - n)) & self._mask(n) + + def readbits(self, n=8): + if n > self.bits: + self.needbits(n) + r = (self.bitfield >> (self.bits - n)) & self._mask(n) + self.bits -= n + self.bitfield &= ~(self._mask(n) << self.bits) + return r + + +def printbits(v, n): + o = '' + for i in range(n): + if v & 1: + o = '1' + o + else: + o = '0' + o + v >>= 1 + return o + + +class HuffmanLength(object): + + def __init__(self, code, bits=0): + self.code = code + self.bits = bits + self.symbol = None + self.reverse_symbol = None + + def __repr__(self): + return repr((self.code, self.bits, self.symbol, self.reverse_symbol)) + + @staticmethod + def _sort_func(obj): + return (obj.bits, obj.code) + + +def reverse_bits(v, n): + a = 1 << 0 + b = 1 << (n - 1) + z = 0 + for i in range(n - 1, -1, -2): + z |= (v >> i) & a + z |= (v << i) & b + a <<= 1 + b >>= 1 + return z + + +def reverse_bytes(v, n): + a = 0xff << 0 + b = 0xff << (n - 8) + z = 0 + for i in range(n - 8, -8, -16): + z |= (v >> i) & a + z |= (v << i) & b + a <<= 8 + b >>= 8 + return z + + +class HuffmanTable(object): + + def __init__(self, bootstrap): + l = [] + start, bits = bootstrap[0] + for finish, endbits in bootstrap[1:]: + if bits: + for code in range(start, finish): + l.append(HuffmanLength(code, bits)) + start, bits = finish, endbits + if endbits == -1: + break + l.sort(key=HuffmanLength._sort_func) + self.table = l + + def populate_huffman_symbols(self): + bits, symbol = -1, -1 + for x in self.table: + symbol += 1 + if x.bits != bits: + symbol <<= (x.bits - bits) + bits = x.bits + x.symbol = symbol + x.reverse_symbol = reverse_bits(symbol, bits) + + def tables_by_bits(self): + d = {} + for x in self.table: + try: + d[x.bits].append(x) + except: # noqa + d[x.bits] = [x] + + def min_max_bits(self): + self.min_bits, self.max_bits = 16, -1 + for x in self.table: + if x.bits < self.min_bits: + self.min_bits = x.bits + if x.bits > self.max_bits: + self.max_bits = x.bits + + def _find_symbol(self, bits, symbol, table): + for h in table: + if h.bits == bits and h.reverse_symbol == symbol: + return h.code + return -1 + + def find_next_symbol(self, field, reversed=True): + cached_length = -1 + cached = None + for x in self.table: + if cached_length != x.bits: + cached = field.snoopbits(x.bits) + cached_length = x.bits + if (reversed and x.reverse_symbol == cached) or (not reversed and x.symbol == cached): + field.readbits(x.bits) + return x.code + raise Exception("unfound symbol, even after end of table @%r" + % field.tell()) + + for bits in range(self.min_bits, self.max_bits + 1): + r = self._find_symbol(bits, field.snoopbits(bits), self.table) + if 0 <= r: + field.readbits(bits) + return r + elif bits == self.max_bits: + raise "unfound symbol, even after max_bits" + + +class OrderedHuffmanTable(HuffmanTable): + + def __init__(self, lengths): + l = len(lengths) + z = list(zip(range(l), lengths)) + [(l, -1)] + HuffmanTable.__init__(self, z) + + +def code_length_orders(i): + return (16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, + 13, 2, 14, 1, 15)[i] + + +def distance_base(i): + return (1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, + 12289, 16385, 24577)[i] + + +def length_base(i): + return (3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, + 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258)[i - 257] + + +def extra_distance_bits(n): + if 0 <= n <= 1: + return 0 + elif 2 <= n <= 29: + return (n >> 1) - 1 + else: + raise "illegal distance code" + + +def extra_length_bits(n): + if 257 <= n <= 260 or n == 285: + return 0 + elif 261 <= n <= 284: + return ((n - 257) >> 2) - 1 + else: + raise "illegal length code" + + +def move_to_front(l, c): + l[:] = l[c:c + 1] + l[0:c] + l[c + 1:] + + +def bwt_transform(L): + # Semi-inefficient way to get the character counts + F = bytes(sorted(L)) + base = [] + for i in range(256): + base.append(F.find(int2byte(i))) + + pointers = [-1] * len(L) + for i, symbol in enumerate(L): + pointers[base[symbol]] = i + base[symbol] += 1 + return pointers + + +def bwt_reverse(L, end): + out = [] + if len(L): + T = bwt_transform(L) + + # STRAGENESS WARNING: There was a bug somewhere here in that + # if the output of the BWT resolves to a perfect copy of N + # identical strings (think exact multiples of 255 'X' here), + # then a loop is formed. When decoded, the output string would + # be cut off after the first loop, typically '\0\0\0\0\xfb'. + # The previous loop construct was: + # + # next = T[end] + # while next != end: + # out += L[next] + # next = T[next] + # out += L[next] + # + # For the moment, I've instead replaced it with a check to see + # if there has been enough output generated. I didn't figured + # out where the off-by-one-ism is yet---that actually produced + # the cyclic loop. + + for i in range(len(L)): + end = T[end] + out.append(L[end]) + + return bytes(out) + + +def compute_used(b): + huffman_used_map = b.readbits(16) + map_mask = 1 << 15 + used = [] + while map_mask > 0: + if huffman_used_map & map_mask: + huffman_used_bitmap = b.readbits(16) + bit_mask = 1 << 15 + while bit_mask > 0: + if huffman_used_bitmap & bit_mask: + pass + used += [bool(huffman_used_bitmap & bit_mask)] + bit_mask >>= 1 + else: + used += [False] * 16 + map_mask >>= 1 + return used + + +def compute_selectors_list(b, huffman_groups): + selectors_used = b.readbits(15) + mtf = list(range(huffman_groups)) + selectors_list = [] + for i in range(selectors_used): + # zero-terminated bit runs (0..62) of MTF'ed huffman table + c = 0 + while b.readbits(1): + c += 1 + if c >= huffman_groups: + raise "Bzip2 chosen selector greater than number of groups (max 6)" + if c >= 0: + move_to_front(mtf, c) + selectors_list.append(mtf[0]) + return selectors_list + + +def compute_tables(b, huffman_groups, symbols_in_use): + groups_lengths = [] + for j in range(huffman_groups): + length = b.readbits(5) + lengths = [] + for i in range(symbols_in_use): + if not 0 <= length <= 20: + raise "Bzip2 Huffman length code outside range 0..20" + while b.readbits(1): + length -= (b.readbits(1) * 2) - 1 + lengths += [length] + groups_lengths += [lengths] + + tables = [] + for g in groups_lengths: + codes = OrderedHuffmanTable(g) + codes.populate_huffman_symbols() + codes.min_max_bits() + tables.append(codes) + return tables + + +def decode_huffman_block(b, out): + randomised = b.readbits(1) + if randomised: + raise "Bzip2 randomised support not implemented" + pointer = b.readbits(24) + used = compute_used(b) + + huffman_groups = b.readbits(3) + if not 2 <= huffman_groups <= 6: + raise Exception("Bzip2: Number of Huffman groups not in range 2..6") + + selectors_list = compute_selectors_list(b, huffman_groups) + symbols_in_use = sum(used) + 2 # remember RUN[AB] RLE symbols + tables = compute_tables(b, huffman_groups, symbols_in_use) + + favourites = [int2byte(i) for i, x in enumerate(used) if x] + + selector_pointer = 0 + decoded = 0 + # Main Huffman loop + repeat = repeat_power = 0 + buffer = [] + t = None + while True: + decoded -= 1 + if decoded <= 0: + decoded = 50 # Huffman table re-evaluate/switch length + if selector_pointer <= len(selectors_list): + t = tables[selectors_list[selector_pointer]] + selector_pointer += 1 + + r = t.find_next_symbol(b, False) + if 0 <= r <= 1: + if repeat == 0: + repeat_power = 1 + repeat += repeat_power << r + repeat_power <<= 1 + continue + elif repeat > 0: + # Remember kids: If there is only one repeated + # real symbol, it is encoded with *zero* Huffman + # bits and not output... so buffer[-1] doesn't work. + buffer.append(favourites[0] * repeat) + repeat = 0 + if r == symbols_in_use - 1: + break + else: + o = favourites[r - 1] + move_to_front(favourites, r - 1) + buffer.append(o) + pass + + nt = nearly_there = bwt_reverse(b"".join(buffer), pointer) + i = 0 + # Pointless/irritating run-length encoding step + while i < len(nearly_there): + if i < len(nearly_there) - 4 and nt[i] == nt[i + 1] == nt[i + 2] == nt[i + 3]: + out.append(nearly_there[i:i + 1] * (ord(nearly_there[i + 4:i + 5]) + 4)) + i += 5 + else: + out.append(nearly_there[i:i + 1]) + i += 1 + +# Sixteen bits of magic have been removed by the time we start decoding + + +def bzip2_main(input): + b = RBitfield(input) + + method = b.readbits(8) + if method != ord('h'): + raise Exception( + "Unknown (not type 'h'uffman Bzip2) compression method") + + blocksize = b.readbits(8) + if ord('1') <= blocksize <= ord('9'): + blocksize = blocksize - ord('0') + else: + raise Exception("Unknown (not size '0'-'9') Bzip2 blocksize") + + out = [] + while True: + blocktype = b.readbits(48) + b.readbits(32) # crc + if blocktype == 0x314159265359: # (pi) + decode_huffman_block(b, out) + elif blocktype == 0x177245385090: # sqrt(pi) + b.align() + break + else: + raise Exception("Illegal Bzip2 blocktype") + return b''.join(out) + + +# Sixteen bits of magic have been removed by the time we start decoding +def gzip_main(field): + b = Bitfield(field) + method = b.readbits(8) + if method != 8: + raise Exception("Unknown (not type eight DEFLATE) compression method") + + # Use flags, drop modification time, extra flags and OS creator type. + flags = b.readbits(8) + b.readbits(32) # mtime + b.readbits(8) # extra_flags + b.readbits(8) # os_type + + if flags & 0x04: # structured GZ_FEXTRA miscellaneous data + xlen = b.readbits(16) + b.dropbytes(xlen) + while flags & 0x08: # original GZ_FNAME filename + if not b.readbits(8): + break + while flags & 0x10: # human readable GZ_FCOMMENT + if not b.readbits(8): + break + if flags & 0x02: # header-only GZ_FHCRC checksum + b.readbits(16) + + out = [] + while True: + lastbit = b.readbits(1) + blocktype = b.readbits(2) + + if blocktype == 0: + b.align() + length = b.readbits(16) + if length & b.readbits(16): + raise Exception("stored block lengths do not match each other") + for i in range(length): + out.append(int2byte(b.readbits(8))) + + elif blocktype == 1 or blocktype == 2: # Huffman + main_literals, main_distances = None, None + + if blocktype == 1: # Static Huffman + static_huffman_bootstrap = [ + (0, 8), (144, 9), (256, 7), (280, 8), (288, -1)] + static_huffman_lengths_bootstrap = [(0, 5), (32, -1)] + main_literals = HuffmanTable(static_huffman_bootstrap) + main_distances = HuffmanTable(static_huffman_lengths_bootstrap) + + elif blocktype == 2: # Dynamic Huffman + literals = b.readbits(5) + 257 + distances = b.readbits(5) + 1 + code_lengths_length = b.readbits(4) + 4 + + l = [0] * 19 + for i in range(code_lengths_length): + l[code_length_orders(i)] = b.readbits(3) + + dynamic_codes = OrderedHuffmanTable(l) + dynamic_codes.populate_huffman_symbols() + dynamic_codes.min_max_bits() + + # Decode the code_lengths for both tables at once, + # then split the list later + + code_lengths = [] + n = 0 + while n < (literals + distances): + r = dynamic_codes.find_next_symbol(b) + if 0 <= r <= 15: # literal bitlength for this code + count = 1 + what = r + elif r == 16: # repeat last code + count = 3 + b.readbits(2) + # Is this supposed to default to '0' if in the zeroth + # position? + what = code_lengths[-1] + elif r == 17: # repeat zero + count = 3 + b.readbits(3) + what = 0 + elif r == 18: # repeat zero lots + count = 11 + b.readbits(7) + what = 0 + else: + raise Exception( + "next code length is outside of the range 0 <= r <= 18") + code_lengths += [what] * count + n += count + + main_literals = OrderedHuffmanTable(code_lengths[:literals]) + main_distances = OrderedHuffmanTable(code_lengths[literals:]) + + # Common path for both Static and Dynamic Huffman decode now + + main_literals.populate_huffman_symbols() + main_distances.populate_huffman_symbols() + + main_literals.min_max_bits() + main_distances.min_max_bits() + + literal_count = 0 + while True: + r = main_literals.find_next_symbol(b) + if 0 <= r <= 255: + literal_count += 1 + out.append(int2byte(r)) + elif r == 256: + if literal_count > 0: + literal_count = 0 + break + elif 257 <= r <= 285: # dictionary lookup + if literal_count > 0: + literal_count = 0 + length_extra = b.readbits(extra_length_bits(r)) + length = length_base(r) + length_extra + + r1 = main_distances.find_next_symbol(b) + if 0 <= r1 <= 29: + distance = distance_base( + r1) + b.readbits(extra_distance_bits(r1)) + while length > distance: + out += out[-distance:] + length -= distance + if length == distance: + out += out[-distance:] + else: + out += out[-distance:length - distance] + elif 30 <= r1 <= 31: + raise Exception("illegal unused distance symbol " + "in use @%r" % b.tell()) + elif 286 <= r <= 287: + raise Exception("illegal unused literal/length symbol " + "in use @%r" % b.tell()) + elif blocktype == 3: + raise Exception("illegal unused blocktype in use @%r" % b.tell()) + + if lastbit: + break + + b.align() + b.readbits(32) # crc + b.readbits(32) # final_length + return "".join(out) + + +def bench_pyflake(loops, filename): + input_fp = open(filename, 'rb') + range_it = range(loops) + + for _ in range_it: + input_fp.seek(0) + field = RBitfield(input_fp) + + magic = field.readbits(16) + if magic == 0x1f8b: # GZip + out = gzip_main(field) + elif magic == 0x425a: # BZip2 + out = bzip2_main(field) + else: + raise Exception("Unknown file magic %x, not a gzip/bzip2 file" + % hex(magic)) + + input_fp.close() + + if hashlib.md5(out).hexdigest() != "afa004a630fe072901b1d9628b960974": + raise Exception("MD5 checksum mismatch") + + +def run(): + filename = os.path.join(os.path.dirname(__file__), + "data", "interpreter.tar.bz2") + bench_pyflake(1, filename) + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + return ["data/interpreter.tar.bz2"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/regex_compile.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/regex_compile.py new file mode 100644 index 0000000000..fe8f79c628 --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/regex_compile.py @@ -0,0 +1,83 @@ + +"""Benchmark how quickly Python's regex implementation can compile regexes. + +We bring in all the regexes used by the other regex benchmarks, capture them by +stubbing out the re module, then compile those regexes repeatedly. We muck with +the re module's caching to force it to recompile every regex we give it. +""" + +# Python imports +import re +import sys +import os + + +def capture_regexes(): + regexes = [] + + real_compile = re.compile + real_search = re.search + real_sub = re.sub + + def capture_compile(regex, flags=0): + regexes.append((regex, flags)) + return real_compile(regex, flags) + + def capture_search(regex, target, flags=0): + regexes.append((regex, flags)) + return real_search(regex, target, flags) + + def capture_sub(regex, *args): + regexes.append((regex, 0)) + return real_sub(regex, *args) + + re.compile = capture_compile + re.search = capture_search + re.sub = capture_sub + try: + sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + import regex_effbot + regex_effbot.bench_regex_effbot(1) + + import regex_v8 + regex_v8.bench_regex_v8(1) + finally: + re.compile = real_compile + re.search = real_search + re.sub = real_sub + return regexes + + +def bench_regex_compile(loops, regexes): + range_it = range(loops) + + for _ in range_it: + for regex, flags in regexes: + re.purge() + # ignore result (compiled regex) + re.compile(regex, flags) + + +def run(): + regexes = capture_regexes() + bench_regex_compile(1, regexes) + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + return ["regex_effbot.py", "regex_v8.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/regex_dna.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/regex_dna.py new file mode 100644 index 0000000000..b275c3081d --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/regex_dna.py @@ -0,0 +1,239 @@ +#!/usr/bin/env python +""" +The Computer Language Benchmarks Game +http://benchmarksgame.alioth.debian.org/ + +regex-dna Python 3 #5 program: +contributed by Dominique Wahli +2to3 +modified by Justin Peel + +fasta Python 3 #3 program: +modified by Ian Osgood +modified again by Heinrich Acker +modified by Justin Peel +Modified by Christopher Sean Forgeron +""" + +import bisect +import re +import argparse + + +DEFAULT_INIT_LEN = 100000 +DEFAULT_RNG_SEED = 42 + +ALU = ('GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG' + 'GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA' + 'CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT' + 'ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA' + 'GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG' + 'AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC' + 'AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA') + +IUB = list(zip('acgtBDHKMNRSVWY', [0.27, 0.12, 0.12, 0.27] + [0.02] * 11)) + +HOMOSAPIENS = [ + ('a', 0.3029549426680), + ('c', 0.1979883004921), + ('g', 0.1975473066391), + ('t', 0.3015094502008), +] + + +def make_cumulative(table): + P = [] + C = [] + prob = 0. + for char, p in table: + prob += p + P += [prob] + C += [ord(char)] + return (P, C) + + +def repeat_fasta(src, n, nprint): + width = 60 + + is_trailing_line = False + count_modifier = 0.0 + + len_of_src = len(src) + ss = src + src + src[:n % len_of_src] + # CSF - It's faster to work with a bytearray than a string + s = bytearray(ss, encoding='utf8') + + if n % width: + # We don't end on a 60 char wide line + is_trailing_line = True + count_modifier = 1.0 + + # CSF - Here we are stuck with using an int instead of a float for the loop, + # but testing showed it still to be faster than a for loop + count = 0 + end = (n / float(width)) - count_modifier + while count < end: + i = count * 60 % len_of_src + nprint(s[i:i + 60] + b'\n') + count += 1 + if is_trailing_line: + nprint(s[-(n % width):] + b'\n') + + +def random_fasta(table, n, seed, nprint): + width = 60 + r = range(width) + bb = bisect.bisect + + # If we don't have a multiple of the width, then we will have a trailing + # line, which needs a slightly different approach + is_trailing_line = False + count_modifier = 0.0 + + line = bytearray(width + 1) # Width of 60 + 1 for the \n char + + probs, chars = make_cumulative(table) + + # pRNG Vars + im = 139968.0 + seed = float(seed) + + if n % width: + # We don't end on a 60 char wide line + is_trailing_line = True + count_modifier = 1.0 + + # CSF - Loops with a high iteration count run faster as a while/float loop. + count = 0.0 + end = (n / float(width)) - count_modifier + while count < end: + # CSF - Low iteration count loops may run faster as a for loop. + for i in r: + # CSF - Python is faster for all float math than it is for int, on my + # machine at least. + seed = (seed * 3877.0 + 29573.0) % 139968.0 + # CSF - While real values, not variables are faster for most things, on my + # machine, it's faster to have 'im' already in a var + line[i] = chars[bb(probs, seed / im)] + + line[60] = 10 # End of Line + nprint(line) + count += 1.0 + + if is_trailing_line: + for i in range(n % width): + seed = (seed * 3877.0 + 29573.0) % 139968.0 + line[i] = chars[bb(probs, seed / im)] + + nprint(line[:i + 1] + b"\n") + + return seed + + +def init_benchmarks(n, rng_seed): + result = bytearray() + nprint = result.extend + nprint(b'>ONE Homo sapiens alu\n') + repeat_fasta(ALU, n * 2, nprint=nprint) + + # We need to keep track of the state of 'seed' so we pass it in, and return + # it back so our output can pass the diff test + nprint(b'>TWO IUB ambiguity codes\n') + seed = random_fasta(IUB, n * 3, seed=rng_seed, nprint=nprint) + + nprint(b'>THREE Homo sapiens frequency\n') + random_fasta(HOMOSAPIENS, n * 5, seed, nprint=nprint) + + return bytes(result) + + +VARIANTS = ( + b'agggtaaa|tttaccct', + b'[cgt]gggtaaa|tttaccc[acg]', + b'a[act]ggtaaa|tttacc[agt]t', + b'ag[act]gtaaa|tttac[agt]ct', + b'agg[act]taaa|ttta[agt]cct', + b'aggg[acg]aaa|ttt[cgt]ccct', + b'agggt[cgt]aa|tt[acg]accct', + b'agggta[cgt]a|t[acg]taccct', + b'agggtaa[cgt]|[acg]ttaccct', +) + +SUBST = ( + (b'B', b'(c|g|t)'), (b'D', b'(a|g|t)'), (b'H', b'(a|c|t)'), + (b'K', b'(g|t)'), (b'M', b'(a|c)'), (b'N', b'(a|c|g|t)'), + (b'R', b'(a|g)'), (b'S', b'(c|g)'), (b'V', b'(a|c|g)'), + (b'W', b'(a|t)'), (b'Y', b'(c|t)'), +) + + +def run_benchmarks(seq): + ilen = len(seq) + + seq = re.sub(b'>.*\n|\n', b'', seq) + clen = len(seq) + + results = [] + for f in VARIANTS: + results.append(len(re.findall(f, seq))) + + for f, r in SUBST: + seq = re.sub(f, r, seq) + + return results, ilen, clen, len(seq) + + +def bench_regex_dna(loops, seq, expected_res): + range_it = range(loops) + + for i in range_it: + res = run_benchmarks(seq) + + if (expected_res is not None) and (res != expected_res): + raise Exception("run_benchmarks() error") + + +def add_cmdline_args(cmd, args): + cmd.extend(("--fasta-length", str(args.fasta_length), + "--rng-seed", str(args.rng_seed))) + + +def run(): + cmd = argparse.ArgumentParser(prog="python") + cmd.add_argument("--fasta-length", type=int, default=DEFAULT_INIT_LEN, + help="Length of the fasta sequence " + "(default: %s)" % DEFAULT_INIT_LEN) + cmd.add_argument("--rng-seed", type=int, default=DEFAULT_RNG_SEED, + help="Seed of the random number generator " + "(default: %s)" % DEFAULT_RNG_SEED) + + args = cmd.parse_args() + if args.fasta_length == 100000: + expected_len = 1016745 + expected_res = ([6, 26, 86, 58, 113, 31, 31, 32, 43], + 1016745, 1000000, 1336326) + else: + expected_len = None + expected_res = None + + seq = init_benchmarks(args.fasta_length, args.rng_seed) + if (expected_len is not None) and (len(seq) != expected_len): + raise Exception("init_benchmarks() error") + + bench_regex_dna(1, seq, expected_res) + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/regex_effbot.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/regex_effbot.py new file mode 100644 index 0000000000..4fb1b26915 --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/regex_effbot.py @@ -0,0 +1,183 @@ + +"""Benchmarks for Python's regex engine. + +These are some of the original benchmarks used to tune Python's regex engine +in 2000 written by Fredrik Lundh. Retreived from +http://mail.python.org/pipermail/python-dev/2000-August/007797.html and +integrated into Unladen Swallow's pyperf.py in 2009 by David Laing. + +These benchmarks are of interest since they helped to guide the original +optimization of the sre engine, and we shouldn't necessarily ignore them just +because they're "old". +""" + +# Python imports +import re +import argparse + +USE_BYTES = False + + +def re_compile(s): + if USE_BYTES: + return re.compile(s.encode('latin1')) + else: + return re.compile(s) + +# These are the regular expressions to be tested. These sync up, +# index-for-index with the list of strings generated by gen_string_table() +# below. + + +def gen_regex_table(): + return [ + re_compile('Python|Perl'), + re_compile('Python|Perl'), + re_compile('(Python|Perl)'), + re_compile('(?:Python|Perl)'), + re_compile('Python'), + re_compile('Python'), + re_compile('.*Python'), + re_compile('.*Python.*'), + re_compile('.*(Python)'), + re_compile('.*(?:Python)'), + re_compile('Python|Perl|Tcl'), + re_compile('Python|Perl|Tcl'), + re_compile('(Python|Perl|Tcl)'), + re_compile('(?:Python|Perl|Tcl)'), + re_compile('(Python)\\1'), + re_compile('(Python)\\1'), + re_compile('([0a-z][a-z0-9]*,)+'), + re_compile('(?:[0a-z][a-z0-9]*,)+'), + re_compile('([a-z][a-z0-9]*,)+'), + re_compile('(?:[a-z][a-z0-9]*,)+'), + re_compile('.*P.*y.*t.*h.*o.*n.*')] + + +def gen_string_table(n): + """Generates the list of strings that will be used in the benchmarks. + + All strings have repeated prefixes and suffices, and n specifies the + number of repetitions. + """ + strings = [] + + def append(s): + if USE_BYTES: + strings.append(s.encode('latin1')) + else: + strings.append(s) + append('-' * n + 'Perl' + '-' * n) + append('P' * n + 'Perl' + 'P' * n) + append('-' * n + 'Perl' + '-' * n) + append('-' * n + 'Perl' + '-' * n) + append('-' * n + 'Python' + '-' * n) + append('P' * n + 'Python' + 'P' * n) + append('-' * n + 'Python' + '-' * n) + append('-' * n + 'Python' + '-' * n) + append('-' * n + 'Python' + '-' * n) + append('-' * n + 'Python' + '-' * n) + append('-' * n + 'Perl' + '-' * n) + append('P' * n + 'Perl' + 'P' * n) + append('-' * n + 'Perl' + '-' * n) + append('-' * n + 'Perl' + '-' * n) + append('-' * n + 'PythonPython' + '-' * n) + append('P' * n + 'PythonPython' + 'P' * n) + append('-' * n + 'a5,b7,c9,' + '-' * n) + append('-' * n + 'a5,b7,c9,' + '-' * n) + append('-' * n + 'a5,b7,c9,' + '-' * n) + append('-' * n + 'a5,b7,c9,' + '-' * n) + append('-' * n + 'Python' + '-' * n) + return strings + + +def init_benchmarks(n_values=None): + """Initialize the strings we'll run the regexes against. + + The strings used in the benchmark are prefixed and suffixed by + strings that are repeated n times. + + The sequence n_values contains the values for n. + If n_values is None the values of n from the original benchmark + are used. + + The generated list of strings is cached in the string_tables + variable, which is indexed by n. + + Returns: + A list of string prefix/suffix lengths. + """ + + if n_values is None: + n_values = (0, 5, 50, 250, 1000, 5000, 10000) + + string_tables = {n: gen_string_table(n) for n in n_values} + regexs = gen_regex_table() + + data = [] + for n in n_values: + for id in range(len(regexs)): + regex = regexs[id] + string = string_tables[n][id] + data.append((regex, string)) + return data + + +def bench_regex_effbot(loops): + if bench_regex_effbot.data is None: + bench_regex_effbot.data = init_benchmarks() + data = bench_regex_effbot.data + + range_it = range(loops) + search = re.search + + for _ in range_it: + # Runs all of the benchmarks for a given value of n. + for regex, string in data: + # search 10 times + search(regex, string) + search(regex, string) + search(regex, string) + search(regex, string) + search(regex, string) + search(regex, string) + search(regex, string) + search(regex, string) + search(regex, string) + search(regex, string) + + +# cached data, generated at the first call +bench_regex_effbot.data = None + + +def add_cmdline_args(cmd, args): + if args.force_bytes: + cmd.append("--force_bytes") + + +def run(): + parser = argparse.ArgumentParser(prog="python") + parser.add_argument("-B", "--force_bytes", action="store_true", + help="test bytes regexps") + options = parser.parse_args() + if options.force_bytes: + USE_BYTES = True + + bench_regex_effbot(4) + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/regex_v8.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/regex_v8.py new file mode 100644 index 0000000000..74ad1c868e --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/regex_v8.py @@ -0,0 +1,1798 @@ +# Copyright 2009 the V8 project authors. All rights reserved. +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# Automatically generated on 2009-01-30. + +# This benchmark is generated by loading 50 of the most popular pages +# on the web and logging all regexp operations performed. Each +# operation is given a weight that is calculated from an estimate of +# the popularity of the pages where it occurs and the number of times +# it is executed while loading each page. Finally the literal +# letters in the data are encoded using ROT13 in a way that does not +# affect how the regexps match their input. + + +# Ported to Python for Unladen Swallow. The original JS version can be found at +# https://github.com/v8/v8/blob/master/benchmarks/regexp.js, r1243. + +# Python imports +import re + + +# The precompiled regexs that were in vars in the V8 code, split into +# tuples of (regex, flags). +compiled_regex_strings = [ + (r'^ba', ''), + (r'(((\w+):\/\/)([^\/:]*)(:(\d+))?)?([^#?]*)(\?([^#]*))?(#(.*))?', ''), + (r'^\s*|\s*$', 'g'), + (r'\bQBZPbageby_cynprubyqre\b', ''), + (r',', ''), + (r'\bQBZPbageby_cynprubyqre\b', 'g'), + (r'^[\s\xa0]+|[\s\xa0]+$', 'g'), + (r'(\d*)(\D*)', 'g'), + (r'=', ''), + (r'(^|\s)lhv\-h(\s|$)', ''), + (r'\#', 'g'), + (r'\.', 'g'), + (r'\'', 'g'), + (r'\?[\w\W]*(sevraqvq|punaaryvq|tebhcvq)=([^\&\?#]*)', 'i'), + (r'\s+', 'g'), + (r'^\s*(\S*(\s+\S+)*)\s*$', ''), + (r'(-[a-z])', 'i'), + (r'(^|[^\\])\"\\\/Qngr\((-?[0-9]+)\)\\\/\"', 'g'), + (r'^\s+|\s+$', 'g'), + (r'(?:^|\s+)ba(?:\s+|$)', ''), + (r'[+, ]', ''), + (r'ybnqrq|pbzcyrgr', ''), + (r'\bso_zrah\b', ''), + (r'^(?:(?:[^:\/?#]+):)?(?:\/\/(?:[^\/?#]*))?([^?#]*)(?:\?([^#]*))?(?:#(.*))?', ''), + (r'uggcf?:\/\/([^\/]+\.)?snprobbx\.pbz\/', ''), + (r'"', 'g'), + (r'^([^?#]+)(?:\?([^#]*))?(#.*)?', ''), + (r'-\D', 'g'), + (r'\bnpgvingr\b', ''), + (r'%2R', 'gi'), + (r'%2S', 'gi'), + (r'^(mu-(PA|GJ)|wn|xb)$', ''), + (r'\s?;\s?', ''), + (r'%\w?$', ''), + (r'TNQP=([^;]*)', 'i'), + (r'[<>]', 'g'), + (r'uers|fep|fryrpgrq', ''), + (r'\s*([+>~\s])\s*([a-zA-Z#.*:\[])', 'g'), + (r'^(\w+|\*)$', ''), + (r'\\\\', 'g'), + (r' ', 'g'), + (r'\/\xc4\/t', ''), + (r'\/\xd6\/t', ''), + (r'\/\xdc\/t', ''), + (r'\/\xdf\/t', ''), + (r'\/\xe4\/t', ''), + (r'\/\xf6\/t', ''), + (r'\/\xfc\/t', ''), + (r'\W', 'g'), + (r'uers|fep|fglyr', ''), + (r'(?:^|\s+)fryrpgrq(?:\s+|$)', ''), + (r'\&', 'g'), + (r'\+', 'g'), + (r'\?', 'g'), + (r'\t', 'g'), + (r'(\$\{nqiHey\})|(\$nqiHey\b)', 'g'), + (r'(\$\{cngu\})|(\$cngu\b)', 'g'), + (r'##yv4##', 'gi'), + (r'##yv16##', 'gi'), + (r'##yv19##', 'gi'), + (r'(?:^|\s+)bss(?:\s+|$)', ''), + (r'^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$', ''), + (r'^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$', ''), + (r'\{0\}', 'g'), + (r'\b[a-z]', 'g'), + (r'^uggc:\/\/', ''), + (r'(?:^|\s+)qvfnoyrq(?:\s+|$)', ''), + (r'zrah_byq', 'g'), + (r'^([#.]?)((?:[\w' + '\u0128-\uffff' + r'*_-]|\\.)*)', ''), + (r'\{1\}', 'g'), + (r'\s+', ''), + (r'(\$\{4\})|(\$4\b)', 'g'), + (r'(\$\{5\})|(\$5\b)', 'g'), + (r'\{2\}', 'g'), + (r'[^+>] [^+>]', ''), + (r'\bucpyv\s*=\s*([^;]*)', 'i'), + (r'\bucuvqr\s*=\s*([^;]*)', 'i'), + (r'\bucfie\s*=\s*([^;]*)', 'i'), + (r'\bhfucjrn\s*=\s*([^;]*)', 'i'), + (r'\bmvc\s*=\s*([^;]*)', 'i'), + (r'^((?:[\w' + '\u0128-\uffff' + r'*_-]|\\.)+)(#)((?:[\w' + + '\u0128-\uffff' + r'*_-]|\\.)+)', ''), + (r'^([>+~])\s*(\w*)', 'i'), + (r'^>\s*((?:[\w' + '\u0128-\uffff' + r'*_-]|\\.)+)', ''), + (r'^[\s[]?shapgvba', ''), + (r'v\/g.tvs#(.*)', 'i'), + (r'eaq_zbqobkva', ''), + (r';\s*', ''), + (r'(\$\{inyhr\})|(\$inyhr\b)', 'g'), + (r'(\$\{abj\})|(\$abj\b)', 'g'), + (r'\s+$', ''), + (r'^\s+', ''), + (r'(\\\"|\x00-|\x1f|\x7f-|\x9f|' + + '\u00ad|\u0600-|\u0604|\u070f|\u17b4|\u17b5|\u200c-|\u200f|\u2028-|\u202f|\u2060-|\u206f|\ufeff|\ufff0-|\uffff' + r')', 'g'), + (r'^(:)([\w-]+)\("?\'?(.*?(\(.*?\))?[^(]*?)"?\'?\)', ''), + (r'^([:.#]*)((?:[\w' + '\u0128-\uffff' + r'*_-]|\\.)+)', ''), + (r'^(\[) *@?([\w-]+) *([!*$^~=]*) *(\'?"?)(.*?)\4 *\]', '')] + + +# The V8 javascript engine only does one replacement unless the regexp has +# the 'g' flag. Python's sub has count = 1 to do 1 replacement and count = 0 +# to replace all matches. We set this up here. + +regexs = [] +subcount = [] + +for s in compiled_regex_strings: + if 'g' in s[1]: + subcount.append(0) + else: + subcount.append(1) + + if 'i' in s[1]: + regexs.append(re.compile(s[0], re.IGNORECASE | re.UNICODE)) + else: + regexs.append(re.compile(s[0], re.UNICODE)) + +# The strings that were in vars in the V8 benchmark + +strings = [ + r'Zbmvyyn/5.0 (Jvaqbjf; H; Jvaqbjf AG 5.1; ra-HF) NccyrJroXvg/528.9 (XUGZY, yvxr Trpxb) Puebzr/2.0.157.0 Fnsnev/528.9', + r'Fubpxjnir Synfu 9.0 e115', + r'{"anzr":"","ahzoreSbezng":{"PheeraplQrpvznyQvtvgf":2,"PheeraplQrpvznyFrcnengbe":".","VfErnqBayl":gehr,"PheeraplTebhcFvmrf":[3],"AhzoreTebhcFvmrf":[3],"CrepragTebhcFvmrf":[3],"PheeraplTebhcFrcnengbe":",","PheeraplFlzoby":"\xa4","AnAFlzoby":"AnA","PheeraplArtngvirCnggrea":0,"AhzoreArtngvirCnggrea":1,"CrepragCbfvgvirCnggrea":0,"CrepragArtngvirCnggrea":0,"ArtngvirVasvavglFlzoby":"-Vasvavgl","ArtngvirFvta":"-","AhzoreQrpvznyQvtvgf":2,"AhzoreQrpvznyFrcnengbe":".","AhzoreTebhcFrcnengbe":",","PheeraplCbfvgvirCnggrea":0,"CbfvgvirVasvavglFlzoby":"Vasvavgl","CbfvgvirFvta":"+","CrepragQrpvznyQvtvgf":2,"CrepragQrpvznyFrcnengbe":".","CrepragTebhcFrcnengbe":",","CrepragFlzoby":"%","CreZvyyrFlzoby":"\u2030","AngvirQvtvgf":["0","1","2","3","4","5","6","7","8","9"],"QvtvgFhofgvghgvba":1},"qngrGvzrSbezng":{"NZQrfvtangbe":"NZ","Pnyraqne":{"ZvaFhccbegrqQngrGvzr":"@-62135568000000@","ZnkFhccbegrqQngrGvzr":"@253402300799999@","NytbevguzGlcr":1,"PnyraqneGlcr":1,"Renf":[1],"GjbQvtvgLrneZnk":2029,"VfErnqBayl":gehr},"QngrFrcnengbe":"/","SvefgQnlBsJrrx":0,"PnyraqneJrrxEhyr":0,"ShyyQngrGvzrCnggrea":"qqqq, qq ZZZZ llll UU:zz:ff","YbatQngrCnggrea":"qqqq, qq ZZZZ llll","YbatGvzrCnggrea":"UU:zz:ff","ZbaguQnlCnggrea":"ZZZZ qq","CZQrfvtangbe":"CZ","ESP1123Cnggrea":"qqq, qq ZZZ llll UU\':\'zz\':\'ff \'TZG\'","FubegQngrCnggrea":"ZZ/qq/llll","FubegGvzrCnggrea":"UU:zz","FbegnoyrQngrGvzrCnggrea":"llll\'-\'ZZ\'-\'qq\'G\'UU\':\'zz\':\'ff","GvzrFrcnengbe":":","HavirefnyFbegnoyrQngrGvzrCnggrea":"llll\'-\'ZZ\'-\'qq UU\':\'zz\':\'ff\'M\'","LrneZbaguCnggrea":"llll ZZZZ","NooerivngrqQnlAnzrf":["Fha","Zba","Ghr","Jrq","Guh","Sev","Fng"],"FubegrfgQnlAnzrf":["Fh","Zb","Gh","Jr","Gu","Se","Fn"],"QnlAnzrf":["Fhaqnl","Zbaqnl","Ghrfqnl","Jrqarfqnl","Guhefqnl","Sevqnl","Fngheqnl"],"NooerivngrqZbaguAnzrf":["Wna","Sro","Zne","Nce","Znl","Wha","Why","Nht","Frc","Bpg","Abi","Qrp",""],"ZbaguAnzrf":["Wnahnel","Sroehnel","Znepu","Ncevy","Znl","Whar","Whyl","Nhthfg","Frcgrzore","Bpgbore","Abirzore","Qrprzore",""],"VfErnqBayl":gehr,"AngvirPnyraqneAnzr":"Tertbevna Pnyraqne","NooerivngrqZbaguTravgvirAnzrf":["Wna","Sro","Zne","Nce","Znl","Wha","Why","Nht","Frc","Bpg","Abi","Qrp",""],"ZbaguTravgvirAnzrf":["Wnahnel","Sroehnel","Znepu","Ncevy","Znl","Whar","Whyl","Nhthfg","Frcgrzore","Bpgbore","Abirzore","Qrprzore",""]}}', + r'{"anzr":"ra-HF","ahzoreSbezng":{"PheeraplQrpvznyQvtvgf":2,"PheeraplQrpvznyFrcnengbe":".","VfErnqBayl":snyfr,"PheeraplTebhcFvmrf":[3],"AhzoreTebhcFvmrf":[3],"CrepragTebhcFvmrf":[3],"PheeraplTebhcFrcnengbe":",","PheeraplFlzoby":"$","AnAFlzoby":"AnA","PheeraplArtngvirCnggrea":0,"AhzoreArtngvirCnggrea":1,"CrepragCbfvgvirCnggrea":0,"CrepragArtngvirCnggrea":0,"ArtngvirVasvavglFlzoby":"-Vasvavgl","ArtngvirFvta":"-","AhzoreQrpvznyQvtvgf":2,"AhzoreQrpvznyFrcnengbe":".","AhzoreTebhcFrcnengbe":",","PheeraplCbfvgvirCnggrea":0,"CbfvgvirVasvavglFlzoby":"Vasvavgl","CbfvgvirFvta":"+","CrepragQrpvznyQvtvgf":2,"CrepragQrpvznyFrcnengbe":".","CrepragTebhcFrcnengbe":",","CrepragFlzoby":"%","CreZvyyrFlzoby":"\u2030","AngvirQvtvgf":["0","1","2","3","4","5","6","7","8","9"],"QvtvgFhofgvghgvba":1},"qngrGvzrSbezng":{"NZQrfvtangbe":"NZ","Pnyraqne":{"ZvaFhccbegrqQngrGvzr":"@-62135568000000@","ZnkFhccbegrqQngrGvzr":"@253402300799999@","NytbevguzGlcr":1,"PnyraqneGlcr":1,"Renf":[1],"GjbQvtvgLrneZnk":2029,"VfErnqBayl":snyfr},"QngrFrcnengbe":"/","SvefgQnlBsJrrx":0,"PnyraqneJrrxEhyr":0,"ShyyQngrGvzrCnggrea":"qqqq, ZZZZ qq, llll u:zz:ff gg","YbatQngrCnggrea":"qqqq, ZZZZ qq, llll","YbatGvzrCnggrea":"u:zz:ff gg","ZbaguQnlCnggrea":"ZZZZ qq","CZQrfvtangbe":"CZ","ESP1123Cnggrea":"qqq, qq ZZZ llll UU\':\'zz\':\'ff \'TZG\'","FubegQngrCnggrea":"Z/q/llll","FubegGvzrCnggrea":"u:zz gg","FbegnoyrQngrGvzrCnggrea":"llll\'-\'ZZ\'-\'qq\'G\'UU\':\'zz\':\'ff","GvzrFrcnengbe":":","HavirefnyFbegnoyrQngrGvzrCnggrea":"llll\'-\'ZZ\'-\'qq UU\':\'zz\':\'ff\'M\'","LrneZbaguCnggrea":"ZZZZ, llll","NooerivngrqQnlAnzrf":["Fha","Zba","Ghr","Jrq","Guh","Sev","Fng"],"FubegrfgQnlAnzrf":["Fh","Zb","Gh","Jr","Gu","Se","Fn"],"QnlAnzrf":["Fhaqnl","Zbaqnl","Ghrfqnl","Jrqarfqnl","Guhefqnl","Sevqnl","Fngheqnl"],"NooerivngrqZbaguAnzrf":["Wna","Sro","Zne","Nce","Znl","Wha","Why","Nht","Frc","Bpg","Abi","Qrp",""],"ZbaguAnzrf":["Wnahnel","Sroehnel","Znepu","Ncevy","Znl","Whar","Whyl","Nhthfg","Frcgrzore","Bpgbore","Abirzore","Qrprzore",""],"VfErnqBayl":snyfr,"AngvirPnyraqneAnzr":"Tertbevna Pnyraqne","NooerivngrqZbaguTravgvirAnzrf":["Wna","Sro","Zne","Nce","Znl","Wha","Why","Nht","Frc","Bpg","Abi","Qrp",""],"ZbaguTravgvirAnzrf":["Wnahnel","Sroehnel","Znepu","Ncevy","Znl","Whar","Whyl","Nhthfg","Frcgrzore","Bpgbore","Abirzore","Qrprzore",""]}}', + r'HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q', + r'HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=', + r'uggc://jjj.snprobbx.pbz/vaqrk.cuc', + r';;jvaqbj.IjPurpxZbhfrCbfvgvbaNQ_VQ=shapgvba(r){vs(!r)ine r=jvaqbj.rirag;ine c=-1;vs(d1)c=d1.EbyybssCnary;ine bo=IjTrgBow("IjCnayNQ_VQ_"+c);vs(bo&&bo.fglyr.ivfvovyvgl=="ivfvoyr"){ine fns=IjFns?8:0;ine pheK=r.pyvragK+IjBOFpe("U")+fns,pheL=r.pyvragL+IjBOFpe("I")+fns;ine y=IjBOEC(NQ_VQ,bo,"Y"),g=IjBOEC(NQ_VQ,bo,"G");ine e=y+d1.Cnaryf[c].Jvqgu,o=g+d1.Cnaryf[c].Urvtug;vs((pheKe)||(pheLo)){vs(jvaqbj.IjBaEbyybssNQ_VQ)IjBaEbyybssNQ_VQ(c);ryfr IjPybfrNq(NQ_VQ,c,gehr,"");}ryfr erghea;}IjPnapryZbhfrYvfgrareNQ_VQ();};;jvaqbj.IjFrgEbyybssCnaryNQ_VQ=shapgvba(c){ine z="zbhfrzbir",q=qbphzrag,s=IjPurpxZbhfrCbfvgvbaNQ_VQ;c=IjTc(NQ_VQ,c);vs(d1&&d1.EbyybssCnary>-1)IjPnapryZbhfrYvfgrareNQ_VQ();vs(d1)d1.EbyybssCnary=c;gel{vs(q.nqqRiragYvfgrare)q.nqqRiragYvfgrare(z,s,snyfr);ryfr vs(q.nggnpuRirag)q.nggnpuRirag("ba"+z,s);}pngpu(r){}};;jvaqbj.IjPnapryZbhfrYvfgrareNQ_VQ=shapgvba(){ine z="zbhfrzbir",q=qbphzrag,s=IjPurpxZbhfrCbfvgvbaNQ_VQ;vs(d1)d1.EbyybssCnary=-1;gel{vs(q.erzbirRiragYvfgrare)q.erzbirRiragYvfgrare(z,s,snyfr);ryfr vs(q.qrgnpuRirag)q.qrgnpuRirag("ba"+z,s);}pngpu(r){}};;d1.IjTc=d2(n,c){ine nq=d1;vs(vfAnA(c)){sbe(ine v=0;v0){vs(nq.FzV.yratgu>0)nq.FzV+="/";nq.FzV+=vh[v];nq.FtZ[nq.FtZ.yratgu]=snyfr;}}};;d1.IjYvzvg0=d2(n,f){ine nq=d1,vh=f.fcyvg("/");sbe(ine v=0;v0){vs(nq.OvC.yratgu>0)nq.OvC+="/";nq.OvC+=vh[v];}}};;d1.IjRVST=d2(n,c){jvaqbj["IjCnayNQ_VQ_"+c+"_Bow"]=IjTrgBow("IjCnayNQ_VQ_"+c+"_Bow");vs(jvaqbj["IjCnayNQ_VQ_"+c+"_Bow"]==ahyy)frgGvzrbhg("IjRVST(NQ_VQ,"+c+")",d1.rvsg);};;d1.IjNavzSHC=d2(n,c){ine nq=d1;vs(c>nq.Cnaryf.yratgu)erghea;ine cna=nq.Cnaryf[c],nn=gehr,on=gehr,yn=gehr,en=gehr,cn=nq.Cnaryf[0],sf=nq.ShF,j=cn.Jvqgu,u=cn.Urvtug;vs(j=="100%"){j=sf;en=snyfr;yn=snyfr;}vs(u=="100%"){u=sf;nn=snyfr;on=snyfr;}vs(cn.YnY=="Y")yn=snyfr;vs(cn.YnY=="E")en=snyfr;vs(cn.GnY=="G")nn=snyfr;vs(cn.GnY=="O")on=snyfr;ine k=0,l=0;fjvgpu(nq.NshP%8){pnfr 0:oernx;pnfr 1:vs(nn)l=-sf;oernx;pnfr 2:k=j-sf;oernx;pnfr 3:vs(en)k=j;oernx;pnfr 4:k=j-sf;l=u-sf;oernx;pnfr 5:k=j-sf;vs(on)l=u;oernx;pnfr 6:l=u-sf;oernx;pnfr 7:vs(yn)k=-sf;l=u-sf;oernx;}vs(nq.NshP++ 0)||(nethzragf.yratgu==3&&bG>0))){pyrneGvzrbhg(cay.UgU);cay.UgU=frgGvzrbhg(cay.UvqrNpgvba,(nethzragf.yratgu==3?bG:cay.UvqrGvzrbhgInyhr));}};;d1.IjErfrgGvzrbhg=d2(n,c,bG){c=IjTc(n,c);IjPnapryGvzrbhg(n,c);riny("IjFgnegGvzrbhg(NQ_VQ,c"+(nethzragf.yratgu==3?",bG":"")+")");};;d1.IjErfrgNyyGvzrbhgf=d2(n){sbe(ine c=0;ce)||(pheLo)){vs(jvaqbj.IjBaEbyybssNQ_VQ)IjBaEbyybssNQ_VQ(c);ryfr IjPybfrNq(NQ_VQ,c,gehr,"");}ryfr erghea;}IjPnapryZbhfrYvfgrareNQ_VQ();};;jvaqbj.IjFrgEbyybssCnaryNQ_VQ=shapgvba(c){ine z="zbhfrzbir",q=qbphzrag,s=IjPurpxZbhfrCbfvgvbaNQ_VQ;c=IjTc(NQ_VQ,c);vs(jvaqbj.IjNqNQ_VQ&&jvaqbj.IjNqNQ_VQ.EbyybssCnary>-1)IjPnapryZbhfrYvfgrareNQ_VQ();vs(jvaqbj.IjNqNQ_VQ)jvaqbj.IjNqNQ_VQ.EbyybssCnary=c;gel{vs(q.nqqRiragYvfgrare)q.nqqRiragYvfgrare(z,s,snyfr);ryfr vs(q.nggnpuRirag)q.nggnpuRirag("ba"+z,s);}pngpu(r){}};;jvaqbj.IjPnapryZbhfrYvfgrareNQ_VQ=shapgvba(){ine z="zbhfrzbir",q=qbphzrag,s=IjPurpxZbhfrCbfvgvbaNQ_VQ;vs(jvaqbj.IjNqNQ_VQ)jvaqbj.IjNqNQ_VQ.EbyybssCnary=-1;gel{vs(q.erzbirRiragYvfgrare)q.erzbirRiragYvfgrare(z,s,snyfr);ryfr vs(q.qrgnpuRirag)q.qrgnpuRirag("ba"+z,s);}pngpu(r){}};;jvaqbj.IjNqNQ_VQ.IjTc=shapgvba(n,c){ine nq=jvaqbj.IjNqNQ_VQ;vs(vfAnA(c)){sbe(ine v=0;v0){vs(nq.FzV.yratgu>0)nq.FzV+="/";nq.FzV+=vh[v];nq.FtZ[nq.FtZ.yratgu]=snyfr;}}};;jvaqbj.IjNqNQ_VQ.IjYvzvg0=shapgvba(n,f){ine nq=jvaqbj.IjNqNQ_VQ,vh=f.fcyvg("/");sbe(ine v=0;v0){vs(nq.OvC.yratgu>0)nq.OvC+="/";nq.OvC+=vh[v];}}};;jvaqbj.IjNqNQ_VQ.IjRVST=shapgvba(n,c){jvaqbj["IjCnayNQ_VQ_"+c+"_Bow"]=IjTrgBow("IjCnayNQ_VQ_"+c+"_Bow");vs(jvaqbj["IjCnayNQ_VQ_"+c+"_Bow"]==ahyy)frgGvzrbhg("IjRVST(NQ_VQ,"+c+")",jvaqbj.IjNqNQ_VQ.rvsg);};;jvaqbj.IjNqNQ_VQ.IjNavzSHC=shapgvba(n,c){ine nq=jvaqbj.IjNqNQ_VQ;vs(c>nq.Cnaryf.yratgu)erghea;ine cna=nq.Cnaryf[c],nn=gehr,on=gehr,yn=gehr,en=gehr,cn=nq.Cnaryf[0],sf=nq.ShF,j=cn.Jvqgu,u=cn.Urvtug;vs(j=="100%"){j=sf;en=snyfr;yn=snyfr;}vs(u=="100%"){u=sf;nn=snyfr;on=snyfr;}vs(cn.YnY=="Y")yn=snyfr;vs(cn.YnY=="E")en=snyfr;vs(cn.GnY=="G")nn=snyfr;vs(cn.GnY=="O")on=snyfr;ine k=0,l=0;fjvgpu(nq.NshP%8){pnfr 0:oernx;pnfr 1:vs(nn)l=-sf;oernx;pnfr 2:k=j-sf;oernx;pnfr 3:vs(en)k=j;oernx;pnfr 4:k=j-sf;l=u-sf;oernx;pnfr 5:k=j-sf;vs(on)l=u;oernx;pnfr 6:l=u-sf;oernx;pnfr 7:vs(yn)k=-sf;l=u-sf;oernx;}vs(nq.NshP++ 0)||(nethzragf.yratgu==3&&bG>0))){pyrneGvzrbhg(cay.UgU);cay.UgU=frgGvzrbhg(cay.UvqrNpgvba,(nethzragf.yratgu==3?bG:cay.UvqrGvzrbhgInyhr));}};;jvaqbj.IjNqNQ_VQ.IjErfrgGvzrbhg=shapgvba(n,c,bG){c=IjTc(n,c);IjPnapryGvzrbhg(n,c);riny("IjFgnegGvzrbhg(NQ_VQ,c"+(nethzragf.yratgu==3?",bG":"")+")");};;jvaqbj.IjNqNQ_VQ.IjErfrgNyyGvzrbhgf=shapgvba(n){sbe(ine c=0;ce)||(pheLo)){vs(jvaqbj.IjBaEbyybssNQ_VQ)IjBaEbyybssNQ_VQ(c);ryfr IjPybfrNq(NQ_VQ,c,gehr,"");}ryfr erghea;}IjPnapryZbhfrYvfgrareNQ_VQ();};;jvaqbj.IjFrgEbyybssCnaryNQ_VQ=shapgvba(c){ine z="zbhfrzbir",q=qbphzrag,s=IjPurpxZbhfrCbfvgvbaNQ_VQ;c=IjTc(NQ_VQ,c);vs(jvaqbj.IjNqNQ_VQ&&jvaqbj.IjNqNQ_VQ.EbyybssCnary>-1)IjPnapryZbhfrYvfgrareNQ_VQ();vs(jvaqbj.IjNqNQ_VQ)jvaqbj.IjNqNQ_VQ.EbyybssCnary=c;gel{vs(q.nqqRiragYvfgrare)q.nqqRiragYvfgrare(z,s,snyfr);ryfr vs(q.nggnpuRirag)q.nggnpuRirag("ba"+z,s);}pngpu(r){}};;jvaqbj.IjPnapryZbhfrYvfgrareNQ_VQ=shapgvba(){ine z="zbhfrzbir",q=qbphzrag,s=IjPurpxZbhfrCbfvgvbaNQ_VQ;vs(jvaqbj.IjNqNQ_VQ)jvaqbj.IjNqNQ_VQ.EbyybssCnary=-1;gel{vs(q.erzbirRiragYvfgrare)q.erzbirRiragYvfgrare(z,s,snyfr);ryfr vs(q.qrgnpuRirag)q.qrgnpuRirag("ba"+z,s);}pngpu(r){}};;jvaqbj.IjNqNQ_VQ.IjTc=d2(n,c){ine nq=jvaqbj.IjNqNQ_VQ;vs(vfAnA(c)){sbe(ine v=0;v0){vs(nq.FzV.yratgu>0)nq.FzV+="/";nq.FzV+=vh[v];nq.FtZ[nq.FtZ.yratgu]=snyfr;}}};;jvaqbj.IjNqNQ_VQ.IjYvzvg0=d2(n,f){ine nq=jvaqbj.IjNqNQ_VQ,vh=f.fcyvg("/");sbe(ine v=0;v0){vs(nq.OvC.yratgu>0)nq.OvC+="/";nq.OvC+=vh[v];}}};;jvaqbj.IjNqNQ_VQ.IjRVST=d2(n,c){jvaqbj["IjCnayNQ_VQ_"+c+"_Bow"]=IjTrgBow("IjCnayNQ_VQ_"+c+"_Bow");vs(jvaqbj["IjCnayNQ_VQ_"+c+"_Bow"]==ahyy)frgGvzrbhg("IjRVST(NQ_VQ,"+c+")",jvaqbj.IjNqNQ_VQ.rvsg);};;jvaqbj.IjNqNQ_VQ.IjNavzSHC=d2(n,c){ine nq=jvaqbj.IjNqNQ_VQ;vs(c>nq.Cnaryf.yratgu)erghea;ine cna=nq.Cnaryf[c],nn=gehr,on=gehr,yn=gehr,en=gehr,cn=nq.Cnaryf[0],sf=nq.ShF,j=cn.Jvqgu,u=cn.Urvtug;vs(j=="100%"){j=sf;en=snyfr;yn=snyfr;}vs(u=="100%"){u=sf;nn=snyfr;on=snyfr;}vs(cn.YnY=="Y")yn=snyfr;vs(cn.YnY=="E")en=snyfr;vs(cn.GnY=="G")nn=snyfr;vs(cn.GnY=="O")on=snyfr;ine k=0,l=0;fjvgpu(nq.NshP%8){pnfr 0:oernx;pnfr 1:vs(nn)l=-sf;oernx;pnfr 2:k=j-sf;oernx;pnfr 3:vs(en)k=j;oernx;pnfr 4:k=j-sf;l=u-sf;oernx;pnfr 5:k=j-sf;vs(on)l=u;oernx;pnfr 6:l=u-sf;oernx;pnfr 7:vs(yn)k=-sf;l=u-sf;oernx;}vs(nq.NshP++ 0)||(nethzragf.yratgu==3&&bG>0))){pyrneGvzrbhg(cay.UgU);cay.UgU=frgGvzrbhg(cay.UvqrNpgvba,(nethzragf.yratgu==3?bG:cay.UvqrGvzrbhgInyhr));}};;jvaqbj.IjNqNQ_VQ.IjErfrgGvzrbhg=d2(n,c,bG){c=IjTc(n,c);IjPnapryGvzrbhg(n,c);riny("IjFgnegGvzrbhg(NQ_VQ,c"+(nethzragf.yratgu==3?",bG":"")+")");};;jvaqbj.IjNqNQ_VQ.IjErfrgNyyGvzrbhgf=d2(n){sbe(ine c=0;c##yv4##Cbjreshy Zvpebfbsg grpuabybtl urycf svtug fcnz naq vzcebir frphevgl.##yv19##Trg zber qbar gunaxf gb terngre rnfr naq fcrrq.##yv16##Ybgf bs fgbentr (5 TO) - zber pbby fghss ba gur jnl.##OE## ##OE## ##N##Yrnea zber##/N##', + r'Cbjreshy Zvpebfbsg grpuabybtl urycf svtug fcnz naq vzcebir frphevgl.##yv19##Trg zber qbar gunaxf gb terngre rnfr naq fcrrq.##yv16##Ybgf bs fgbentr (5 TO) - zber pbby fghss ba gur jnl.##OE## ##OE## ##N##Yrnea zber##/N##', + r'Cbjreshy Zvpebfbsg grpuabybtl urycf svtug fcnz naq vzcebir frphevgl.##yv19##Trg zber qbar gunaxf gb terngre rnfr naq fcrrq.Ybgf bs fgbentr (5 TO) - zber pbby fghss ba gur jnl.##OE## ##OE## ##N##Yrnea zber##/N##', + r'Cbjreshy Zvpebfbsg grpuabybtl urycf svtug fcnz naq vzcebir frphevgl.Trg zber qbar gunaxf gb terngre rnfr naq fcrrq.Ybgf bs fgbentr (5 TO) - zber pbby fghss ba gur jnl.##OE## ##OE## ##N##Yrnea zber##/N##', + r'Cbjreshy Zvpebfbsg grpuabybtl urycf svtug fcnz naq vzcebir frphevgl.Trg zber qbar gunaxf gb terngre rnfr naq fcrrq.Ybgf bs fgbentr (5 TO) - zber pbby fghss ba gur jnl. ##N##Yrnea zber##/N##', + r'Cbjreshy Zvpebfbsg grpuabybtl urycf svtug fcnz naq vzcebir frphevgl.Trg zber qbar gunaxf gb terngre rnfr naq fcrrq.Ybgf bs fgbentr (5 TO) - zber pbby fghss ba gur jnl. Yrnea zber##/N##', + r'Bar Jvaqbjf Yvir VQ trgf lbh vagb Ubgznvy, Zrffratre, Kobk YVIR \u2014 naq bgure cynprf lbh frr #~#argjbexybtb#~#', + r'${1}://${2}${3}${4}${5}', + r' O=6gnyg0g4znrrn&o=3&f=gc; Q=_lyu=K3bQZGSxnT4lZzD3OS9GNmV3ZGLkAQxRpTyxNmRlZmRmAmNkAQLRqTImqNZjOUEgpTjQnJ5xMKtgoN--; SCF=qy', + r'FrffvbaQQS2=4ss747o77904333q374or84qrr1s9r0nprp8r5q81534o94n; ZFPhygher=VC=74.125.75.20&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669321699093060&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=; AFP_zp_tfwsbrg-aowb_80=4413268q3660', + r'FrffvbaQQS2=4ss747o77904333q374or84qrr1s9r0nprp8r5q81534o94n; AFP_zp_tfwsbrg-aowb_80=4413268q3660; __hgzm=144631658.1231364074.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar); __hgzn=144631658.2294274870215848400.1231364074.1231364074.1231364074.1; __hgzo=144631658.0.10.1231364074; __hgzp=144631658; ZFPhygher=VC=74.125.75.20&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669321699093060&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q', + r'uggc://tbbtyrnqf.t.qbhoyrpyvpx.arg/cntrnq/nqf?pyvrag=pn-svz_zlfcnpr_zlfcnpr-ubzrcntr_wf&qg=1231364057761&uy=ra&nqfnsr=uvtu&br=hgs8&ahz_nqf=4&bhgchg=wf&nqgrfg=bss&pbeeryngbe=1231364057761&punaary=svz_zlfcnpr_ubzrcntr_abgybttrqva%2Psvz_zlfcnpr_aba_HTP%2Psvz_zlfcnpr_havgrq-fgngrf&hey=uggc%3N%2S%2Ssevraqf.zlfcnpr.pbz%2Svaqrk.psz&nq_glcr=grkg&rvq=6083027&rn=0&sez=0&tn_ivq=1667363813.1231364061&tn_fvq=1231364061&tn_uvq=1917563877&synfu=9.0.115&h_u=768&h_j=1024&h_nu=738&h_nj=1024&h_pq=24&h_gm=-480&h_uvf=2&h_wnin=gehr&h_acyht=7&h_azvzr=22', + r'ZFPhygher=VC=74.125.75.20&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669321699093060&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q', + r'ZFPhygher=VC=74.125.75.20&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669321699093060&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=', + r'uggc://cebsvyr.zlfcnpr.pbz/Zbqhyrf/Nccyvpngvbaf/Cntrf/Pnainf.nfck', + r'FrffvbaQQS2=473qq1rs0n2r70q9qo1pq48n021s9468ron90nps048p4p29; ZFPhygher=VC=74.125.75.3&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669325184628362&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=', + r'FrffvbaQQS2=473qq1rs0n2r70q9qo1pq48n021s9468ron90nps048p4p29; __hgzm=144631658.1231364380.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar); __hgzn=144631658.3931862196947939300.1231364380.1231364380.1231364380.1; __hgzo=144631658.0.10.1231364380; __hgzp=144631658; ZFPhygher=VC=74.125.75.3&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669325184628362&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q', + r'uggc://tbbtyrnqf.t.qbhoyrpyvpx.arg/cntrnq/nqf?pyvrag=pn-svz_zlfcnpr_vzntrf_wf&qg=1231364373088&uy=ra&nqfnsr=uvtu&br=hgs8&ahz_nqf=4&bhgchg=wf&nqgrfg=bss&pbeeryngbe=1231364373088&punaary=svz_zlfcnpr_hfre-ivrj-pbzzragf%2Psvz_zlfcnpr_havgrq-fgngrf&hey=uggc%3N%2S%2Spbzzrag.zlfcnpr.pbz%2Svaqrk.psz&nq_glcr=grkg&rvq=6083027&rn=0&sez=0&tn_ivq=1158737789.1231364375&tn_fvq=1231364375&tn_uvq=415520832&synfu=9.0.115&h_u=768&h_j=1024&h_nu=738&h_nj=1024&h_pq=24&h_gm=-480&h_uvf=2&h_wnin=gehr&h_acyht=7&h_azvzr=22', + r'ZFPhygher=VC=74.125.75.3&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669325184628362&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q', + r'ZFPhygher=VC=74.125.75.3&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669325184628362&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=', + r'#Zbq-Vasb-Vasb-WninFpevcgUvag', + r',n.svryqOgaPnapry', + r'FrffvbaQQS2=p98s8o9q42nr21or1r61pqorn1n002nsss569635984s6qp7; ZFPhygher=VC=74.125.75.3&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669357391353591&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=; AFP_zp_kkk-gdzogv_80=4413241q3660', + r'FrffvbaQQS2=p98s8o9q42nr21or1r61pqorn1n002nsss569635984s6qp7; AFP_zp_kkk-gdzogv_80=4413241q3660; AFP_zp_kkk-aowb_80=4413235p3660; __hgzm=144631658.1231367708.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar); __hgzn=144631658.2770915348920628700.1231367708.1231367708.1231367708.1; __hgzo=144631658.0.10.1231367708; __hgzp=144631658; ZFPhygher=VC=74.125.75.3&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669357391353591&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q', + r'uggc://tbbtyrnqf.t.qbhoyrpyvpx.arg/cntrnq/nqf?pyvrag=pn-svz_zlfcnpr_zlfcnpr-ubzrcntr_wf&qg=1231367691141&uy=ra&nqfnsr=uvtu&br=hgs8&ahz_nqf=4&bhgchg=wf&nqgrfg=bss&pbeeryngbe=1231367691141&punaary=svz_zlfcnpr_ubzrcntr_abgybttrqva%2Psvz_zlfcnpr_aba_HTP%2Psvz_zlfcnpr_havgrq-fgngrf&hey=uggc%3N%2S%2Sjjj.zlfcnpr.pbz%2S&nq_glcr=grkg&rvq=6083027&rn=0&sez=0&tn_ivq=320757904.1231367694&tn_fvq=1231367694&tn_uvq=1758792003&synfu=9.0.115&h_u=768&h_j=1024&h_nu=738&h_nj=1024&h_pq=24&h_gm=-480&h_uvf=2&h_wnin=gehr&h_acyht=7&h_azvzr=22', + r'uggc://zfacbegny.112.2b7.arg/o/ff/zfacbegnyubzr/1/U.7-cqi-2/f55332979829981?[NDO]&aqu=1&g=7%2S0%2S2009%2014%3N38%3N42%203%20480&af=zfacbegny&cntrAnzr=HF%20UCZFSGJ&t=uggc%3N%2S%2Sjjj.zfa.pbz%2S&f=1024k768&p=24&x=L&oj=994&ou=634&uc=A&{2}&[NDR]', + r'cnerag puebzr6 fvatyr1 gno fryrpgrq ovaq qbhoyr2 ps', + r'ZFPhygher=VC=74.125.75.3&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669357391353591&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q', + r'ZFPhygher=VC=74.125.75.3&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669357391353591&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=', + r'ne;ng;nh;or;oe;pn;pu;py;pa;qr;qx;rf;sv;se;to;ux;vq;vr;va;vg;wc;xe;zk;zl;ay;ab;am;cu;cy;cg;eh;fr;ft;gu;ge;gj;mn;', + r'ZP1=I=3&THVQ=6nnpr9q661804s33nnop45nosqp17q85; zu=ZFSG; PHYGHER=RA-HF; SyvtugTebhcVq=97; SyvtugVq=OnfrCntr; ucfie=Z:5|S:5|G:5|R:5|Q:oyh|J:S; ucpyv=J.U|Y.|F.|E.|H.Y|P.|U.; hfucjrn=jp:HFPN0746; ZHVQ=Q783SN9O14054831N4869R51P0SO8886&GHVQ=1', + r'ZP1=I=3&THVQ=6nnpr9q661804s33nnop45nosqp17q85; zu=ZFSG; PHYGHER=RA-HF; SyvtugTebhcVq=97; SyvtugVq=OnfrCntr; ucfie=Z:5|S:5|G:5|R:5|Q:oyh|J:S; ucpyv=J.U|Y.|F.|E.|H.Y|P.|U.; hfucjrn=jp:HFPN0746; ZHVQ=Q783SN9O14054831N4869R51P0SO8886', + r'ZP1=I=3&THVQ=6nnpr9q661804s33nnop45nosqp17q85; zu=ZFSG; PHYGHER=RA-HF; SyvtugTebhcVq=97; SyvtugVq=OnfrCntr; ucfie=Z:5|S:5|G:5|R:5|Q:oyh|J:S; ucpyv=J.U|Y.|F.|E.|H.Y|P.|U.; hfucjrn=jp:HFPN0746; ZHVQ=Q783SN9O14054831N4869R51P0SO8886; mvc=m:94043|yn:37.4154|yb:-122.0585|p:HF|ue:1', + r'ZP1=I=3&THVQ=6nnpr9q661804s33nnop45nosqp17q85; zu=ZFSG; PHYGHER=RA-HF; SyvtugTebhcVq=97; SyvtugVq=OnfrCntr; ucfie=Z:5|S:5|G:5|R:5|Q:oyh|J:S; ucpyv=J.U|Y.|F.|E.|H.Y|P.|U.; hfucjrn=jp:HFPN0746; ZHVQ=Q783SN9O14054831N4869R51P0SO8886; mvc=m:94043|yn:37.4154|yb:-122.0585|p:HF', + r'uggc://gx2.fgp.f-zfa.pbz/oe/uc/11/ra-hf/pff/v/g.tvs#uggc://gx2.fgo.f-zfa.pbz/v/29/4RQP4969777N048NPS4RRR3PO2S7S.wct', + r'uggc://gx2.fgp.f-zfa.pbz/oe/uc/11/ra-hf/pff/v/g.tvs#uggc://gx2.fgo.f-zfa.pbz/v/OQ/63NP9O94NS5OQP1249Q9S1ROP7NS3.wct', + r'zbmvyyn/5.0 (jvaqbjf; h; jvaqbjf ag 5.1; ra-hf) nccyrjroxvg/528.9 (xugzy, yvxr trpxb) puebzr/2.0.157.0 fnsnev/528.9', + r'1231365729213', + r'74.125.75.3-1057165600.29978900', + r'74.125.75.3-1057165600.29978900.1231365730214', + r'Frnepu%20Zvpebfbsg.pbz', + r'FrffvbaQQS2=8sqq78r9n442851q565599o401385sp3s04r92rnn7o19ssn; ZFPhygher=VC=74.125.75.17&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669340386893867&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=', + r'FrffvbaQQS2=8sqq78r9n442851q565599o401385sp3s04r92rnn7o19ssn; __hgzm=144631658.1231365779.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar); __hgzn=144631658.1877536177953918500.1231365779.1231365779.1231365779.1; __hgzo=144631658.0.10.1231365779; __hgzp=144631658; ZFPhygher=VC=74.125.75.17&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669340386893867&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q', + r'I=3%26THVQ=757q3ss871q44o7o805n8113n5p72q52', + r'I=3&THVQ=757q3ss871q44o7o805n8113n5p72q52', + r'uggc://tbbtyrnqf.t.qbhoyrpyvpx.arg/cntrnq/nqf?pyvrag=pn-svz_zlfcnpr_zlfcnpr-ubzrcntr_wf&qg=1231365765292&uy=ra&nqfnsr=uvtu&br=hgs8&ahz_nqf=4&bhgchg=wf&nqgrfg=bss&pbeeryngbe=1231365765292&punaary=svz_zlfcnpr_ubzrcntr_abgybttrqva%2Psvz_zlfcnpr_aba_HTP%2Psvz_zlfcnpr_havgrq-fgngrf&hey=uggc%3N%2S%2Sohyyrgvaf.zlfcnpr.pbz%2Svaqrk.psz&nq_glcr=grkg&rvq=6083027&rn=0&sez=0&tn_ivq=1579793869.1231365768&tn_fvq=1231365768&tn_uvq=2056210897&synfu=9.0.115&h_u=768&h_j=1024&h_nu=738&h_nj=1024&h_pq=24&h_gm=-480&h_uvf=2&h_wnin=gehr&h_acyht=7&h_azvzr=22', + r'frnepu.zvpebfbsg.pbz', + r'frnepu.zvpebfbsg.pbz/', + r'ZFPhygher=VC=74.125.75.17&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669340386893867&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q', + r'ZFPhygher=VC=74.125.75.17&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669340386893867&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=', + r'#fubhgobk .pybfr', + r'FrffvbaQQS2=102n9o0o9pq60132qn0337rr867p75953502q2s27s2s5r98; ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669341278771470&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=; AFP_zp_dfctwzssrwh-aowb_80=441326q33660', + r'FrffvbaQQS2=102n9o0o9pq60132qn0337rr867p75953502q2s27s2s5r98; AFP_zp_dfctwzssrwh-aowb_80=441326q33660; __hgzm=144631658.1231365869.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar); __hgzn=144631658.1670816052019209000.1231365869.1231365869.1231365869.1; __hgzo=144631658.0.10.1231365869; __hgzp=144631658; ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669341278771470&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q', + r'FrffvbaQQS2=9995p6rp12rrnr893334ro7nq70o7p64p69rqn844prs1473; ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669350559478880&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=; AFP_zp_dfctwzs-aowb_80=441327q73660', + r'FrffvbaQQS2=9995p6rp12rrnr893334ro7nq70o7p64p69rqn844prs1473; AFP_zp_dfctwzs-aowb_80=441327q73660; __hgzm=144631658.1231367054.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar); __hgzn=144631658.1796080716621419500.1231367054.1231367054.1231367054.1; __hgzo=144631658.0.10.1231367054; __hgzp=144631658; ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669350559478880&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q', + r'[glcr=fhozvg]', + r'n.svryqOga,n.svryqOgaPnapry', + r'n.svryqOgaPnapry', + r'oyvpxchaxg', + r'qvi.bow-nppbeqvba qg', + r'uggc://tbbtyrnqf.t.qbhoyrpyvpx.arg/cntrnq/nqf?pyvrag=pn-svz_zlfcnpr_nccf_wf&qg=1231367052227&uy=ra&nqfnsr=uvtu&br=hgs8&ahz_nqf=4&bhgchg=wf&nqgrfg=bss&pbeeryngbe=1231367052227&punaary=svz_zlfcnpr_nccf-pnainf%2Psvz_zlfcnpr_havgrq-fgngrf&hey=uggc%3N%2S%2Scebsvyr.zlfcnpr.pbz%2SZbqhyrf%2SNccyvpngvbaf%2SCntrf%2SPnainf.nfck&nq_glcr=grkg&rvq=6083027&rn=0&sez=1&tn_ivq=716357910.1231367056&tn_fvq=1231367056&tn_uvq=1387206491&synfu=9.0.115&h_u=768&h_j=1024&h_nu=738&h_nj=1024&h_pq=24&h_gm=-480&h_uvf=2&h_wnin=gehr&h_acyht=7&h_azvzr=22', + r'uggc://tbbtyrnqf.t.qbhoyrpyvpx.arg/cntrnq/nqf?pyvrag=pn-svz_zlfcnpr_zlfcnpr-ubzrcntr_wf&qg=1231365851658&uy=ra&nqfnsr=uvtu&br=hgs8&ahz_nqf=4&bhgchg=wf&nqgrfg=bss&pbeeryngbe=1231365851658&punaary=svz_zlfcnpr_ubzrcntr_abgybttrqva%2Psvz_zlfcnpr_aba_HTP%2Psvz_zlfcnpr_havgrq-fgngrf&hey=uggc%3N%2S%2Scebsvyrrqvg.zlfcnpr.pbz%2Svaqrk.psz&nq_glcr=grkg&rvq=6083027&rn=0&sez=0&tn_ivq=1979828129.1231365855&tn_fvq=1231365855&tn_uvq=2085229649&synfu=9.0.115&h_u=768&h_j=1024&h_nu=738&h_nj=1024&h_pq=24&h_gm=-480&h_uvf=2&h_wnin=gehr&h_acyht=7&h_azvzr=22', + r'uggc://zfacbegny.112.2b7.arg/o/ff/zfacbegnyubzr/1/U.7-cqi-2/f55023338617756?[NDO]&aqu=1&g=7%2S0%2S2009%2014%3N12%3N47%203%20480&af=zfacbegny&cntrAnzr=HF%20UCZFSGJ&t=uggc%3N%2S%2Sjjj.zfa.pbz%2S&f=0k0&p=43835816&x=A&oj=994&ou=634&uc=A&{2}&[NDR]', + r'zrgn[anzr=nwnkHey]', + r'anpuevpugra', + r'b oS={\'oT\':1.1};x $8n(B){z(B!=o9)};x $S(B){O(!$8n(B))z A;O(B.4L)z\'T\';b S=7t B;O(S==\'2P\'&&B.p4){23(B.7f){12 1:z\'T\';12 3:z/\S/.2g(B.8M)?\'ox\':\'oh\'}}O(S==\'2P\'||S==\'x\'){23(B.nE){12 2V:z\'1O\';12 7I:z\'5a\';12 18:z\'4B\'}O(7t B.I==\'4F\'){O(B.3u)z\'pG\';O(B.8e)z\'1p\'}}z S};x $2p(){b 4E={};Z(b v=0;v<1p.I;v++){Z(b X 1o 1p[v]){b nc=1p[v][X];b 6E=4E[X];O(6E&&$S(nc)==\'2P\'&&$S(6E)==\'2P\')4E[X]=$2p(6E,nc);17 4E[X]=nc}}z 4E};b $E=7p.E=x(){b 1d=1p;O(!1d[1])1d=[p,1d[0]];Z(b X 1o 1d[1])1d[0][X]=1d[1][X];z 1d[0]};b $4D=7p.pJ=x(){Z(b v=0,y=1p.I;v-1:p.3F(2R)>-1},nX:x(){z p.3y(/([.*+?^${}()|[\]\/\\])/t,\'\\$1\')}});2V.E({5V:x(1O){O(p.I<3)z A;O(p.I==4&&p[3]==0&&!1O)z\'p5\';b 3P=[];Z(b v=0;v<3;v++){b 52=(p[v]-0).4h(16);3P.1x((52.I==1)?\'0\'+52:52)}z 1O?3P:\'#\'+3P.2u(\'\')},5U:x(1O){O(p.I!=3)z A;b 1i=[];Z(b v=0;v<3;v++){1i.1x(5K((p[v].I==1)?p[v]+p[v]:p[v],16))}z 1O?1i:\'1i(\'+1i.2u(\',\')+\')\'}});7F.E({3n:x(P){b J=p;P=$2p({\'L\':J,\'V\':A,\'1p\':1S,\'2x\':A,\'4s\':A,\'6W\':A},P);O($2O(P.1p)&&$S(P.1p)!=\'1O\')P.1p=[P.1p];z x(V){b 1d;O(P.V){V=V||H.V;1d=[(P.V===1r)?V:Y P.V(V)];O(P.1p)1d.E(P.1p)}17 1d=P.1p||1p;b 3C=x(){z J.3H($5S(P', + r'hagreunyghat', + r'ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669341278771470&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q', + r'ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669350559478880&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q', + r'ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669341278771470&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=', + r'ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669350559478880&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=', + r'shapgvba (){Cuk.Nccyvpngvba.Frghc.Pber();Cuk.Nccyvpngvba.Frghc.Nwnk();Cuk.Nccyvpngvba.Frghc.Synfu();Cuk.Nccyvpngvba.Frghc.Zbqhyrf()}'] + +# The 12 benchmarking blocks + + +def block0(): + for i in range(6511): + regexs[0].search(r'pyvpx') + + for i in range(1844): + regexs[1].search(r'uggc://jjj.snprobbx.pbz/ybtva.cuc') + + for i in range(739): + regexs[2].sub(r'', 'QBZPbageby_cynprubyqre', subcount[2]) + + for i in range(598): + regexs[1].search(r'uggc://jjj.snprobbx.pbz/') + + for i in range(454): + regexs[1].search(r'uggc://jjj.snprobbx.pbz/fepu.cuc') + + for i in range(352): + re.search( + r'qqqq|qqq|qq|q|ZZZZ|ZZZ|ZZ|Z|llll|ll|l|uu|u|UU|U|zz|z|ff|f|gg|g|sss|ss|s|mmm|mm|m', 'qqqq, ZZZ q, llll') + + for i in range(312): + regexs[3].search(r'vachggrkg QBZPbageby_cynprubyqre') + + for i in range(282): + regexs[4].search(r'/ZlFcnprUbzrcntr/Vaqrk-FvgrUbzr,10000000') + + for i in range(177): + regexs[5].sub(r'', 'vachggrkg', subcount[5]) + + for i in range(170): + regexs[6].sub(r'', '528.9', subcount[6]) + regexs[7].search(r'528') + + for i in range(156): + regexs[8].search(r'VCPhygher=ra-HF') + regexs[8].search(r'CersreerqPhygher=ra-HF') + + for i in range(144): + regexs[0].search(r'xrlcerff') + + for i in range(139): + regexs[6].sub(r'', '521', subcount[6]) + + # This has a different output to the V8 version. + # It could just be a difference in the engines. + regexs[7].search(r'521') + regexs[9].search(r'') + re.search(r'JroXvg\/(\S+)', strings[0]) + + for i in range(137): + regexs[10].sub(r'', 'qvi .so_zrah', subcount[10]) + re.sub(r'\[', '', 'qvi .so_zrah', 0) + regexs[11].sub(r'', 'qvi.so_zrah', subcount[11]) + + for i in range(117): + regexs[2].sub(r'', 'uvqqra_ryrz', subcount[2]) + + for i in range(95): + re.search(r'(?:^|;)\s*sevraqfgre_ynat=([^;]*)', + 'sevraqfgre_naba=nvq%3Qn6ss9p85n868ro9s059pn854735956o3%26ers%3Q%26df%3Q%26vpgl%3QHF') + + for i in range(93): + regexs[12].sub(r'', 'uggc://ubzr.zlfcnpr.pbz/vaqrk.psz', subcount[12]) + regexs[13].search(r'uggc://ubzr.zlfcnpr.pbz/vaqrk.psz') + + for i in range(92): + re.sub(r'([a-zA-Z]|\s)+', '', strings[1], 1) + + for i in range(85): + regexs[14].sub(r'', 'svefg', subcount[14]) + regexs[15].sub(r'', 'svefg', subcount[15]) + regexs[12].sub( + r'', 'uggc://cebsvyr.zlfcnpr.pbz/vaqrk.psz', subcount[12]) + regexs[14].sub(r'', 'ynfg', subcount[14]) + regexs[15].sub(r'', 'ynfg', subcount[15]) + regexs[16].search(r'qvfcynl') + regexs[13].search(r'uggc://cebsvyr.zlfcnpr.pbz/vaqrk.psz') + + +def block1(): + for i in range(81): + regexs[8].search(r'VC=74.125.75.1') + + for i in range(78): + re.sub(r'(\s)+e', '', '9.0 e115', 1) + re.sub(r'.', '', 'k', 1) + + # This prints a unicode escape where the V8 version prints the + # unicode character. + regexs[17].sub(r'', strings[2], subcount[17]) + + # This prints a unicode escape where the V8 version prints the + # unicode character. + regexs[17].sub(r'', strings[3], subcount[17]) + + regexs[8].search(r'144631658') + regexs[8].search(r'Pbhagel=IIZ%3Q') + regexs[8].search(r'Pbhagel=IIZ=') + regexs[8].search(r'CersreerqPhygherCraqvat=') + regexs[8].search(strings[4]) + regexs[8].search(strings[5]) + regexs[8].search(r'__hgzp=144631658') + regexs[8].search(r'gvzrMbar=-8') + regexs[8].search(r'gvzrMbar=0') + re.search(r'Fnsnev\/(\d+\.\d+)', strings[0]) + regexs[3].search(r'vachggrkg QBZPbageby_cynprubyqre') + regexs[0].search(r'xrlqbja') + regexs[0].search(r'xrlhc') + + for i in range(77): + regexs[12].sub( + r'', 'uggc://zrffntvat.zlfcnpr.pbz/vaqrk.psz', subcount[12]) + regexs[13].search(r'uggc://zrffntvat.zlfcnpr.pbz/vaqrk.psz') + + for i in range(73): + regexs[18].sub( + r'', 'FrffvbaFgbentr=%7O%22GnoThvq%22%3N%7O%22thvq%22%3N1231367125017%7Q%7Q', subcount[18]) + + for i in range(72): + regexs[1].search(strings[6]) + + for i in range(71): + regexs[19].search(r'') + + for i in range(70): + regexs[11].sub(r'', '3.5.0.0', subcount[11]) + re.sub(r'd1', '', strings[7], 0) + re.sub(r'NQ_VQ', '', strings[8], 0) + re.sub(r'd2', '', strings[9], 0) + re.sub( + r'_', '', 'NI%3Q1_CI%3Q1_PI%3Q1_EI%3Q1_HI%3Q1_HP%3Q1_IC%3Q0.0.0.0_IH%3Q0', 0) + regexs[20].split( + r'svz_zlfcnpr_ubzrcntr_abgybttrqva,svz_zlfcnpr_aba_HTP,svz_zlfcnpr_havgrq-fgngrf') + regexs[21].search(r'ybnqvat') + + for i in range(68): + regexs[1].search(r'#') + re.search( + r'(?:ZFVR.(\d+\.\d+))|(?:(?:Sversbk|TenaCnenqvfb|Vprjrnfry).(\d+\.\d+))|(?:Bcren.(\d+\.\d+))|(?:NccyrJroXvg.(\d+(?:\.\d+)?))', strings[0]) + re.search(r'(Znp BF K)|(Jvaqbjf;)', strings[0]) + re.search(r'Trpxb\/([0-9]+)', strings[0]) + regexs[21].search(r'ybnqrq') + + for i in range(49): + regexs[16].search(r'pbybe') + + for i in range(44): + regexs[12].sub( + r'', 'uggc://sevraqf.zlfcnpr.pbz/vaqrk.psz', subcount[12]) + regexs[13].search(r'uggc://sevraqf.zlfcnpr.pbz/vaqrk.psz') + + +def block2(): + for i in range(40): + regexs[14].sub(r'', 'fryrpgrq', subcount[14]) + regexs[15].sub(r'', 'fryrpgrq', subcount[15]) + + for i in range(39): + re.sub(r'\buvqqra_ryrz\b', '', 'vachggrkg uvqqra_ryrz', 0) + regexs[3].search(r'vachggrkg ') + regexs[3].search(r'vachggrkg') + regexs[22].search(r'HVYvaxOhggba') + regexs[22].search(r'HVYvaxOhggba_E') + regexs[22].search(r'HVYvaxOhggba_EJ') + regexs[22].search(r'zrah_ybtva_pbagnvare') + re.search(r'\buvqqra_ryrz\b', 'vachgcnffjbeq') + + for i in range(37): + regexs[8].search(r'111soqs57qo8o8480qo18sor2011r3n591q7s6s37r120904') + regexs[8].search(r'SbeprqRkcvengvba=633669315660164980') + regexs[8].search( + r'FrffvbaQQS2=111soqs57qo8o8480qo18sor2011r3n591q7s6s37r120904') + + for i in range(35): + regexs[14].sub(r'', 'puvyq p1 svefg', subcount[14]) + regexs[15].sub(r'', 'puvyq p1 svefg', subcount[15]) + regexs[14].sub(r'', 'sylbhg pybfrq', subcount[14]) + regexs[15].sub(r'', 'sylbhg pybfrq', subcount[15]) + + for i in range(34): + regexs[19].search(r'gno2') + regexs[19].search(r'gno3') + regexs[8].search(r'44132r503660') + regexs[8].search(r'SbeprqRkcvengvba=633669316860113296') + regexs[8].search(r'AFP_zp_dfctwzs-aowb_80=44132r503660') + regexs[8].search( + r'FrffvbaQQS2=s6r4579npn4rn2135s904r0s75pp1o5334p6s6pospo12696') + regexs[8].search(r's6r4579npn4rn2135s904r0s75pp1o5334p6s6pospo12696') + + for i in range(32): + re.search(r'puebzr', strings[0], re.IGNORECASE) + + for i in range(31): + regexs[23].sub(r'', 'uggc://jjj.snprobbx.pbz/', subcount[23]) + regexs[8].search(r'SbeprqRkcvengvba=633669358527244818') + regexs[8].search(r'VC=66.249.85.130') + regexs[8].search( + r'FrffvbaQQS2=s15q53p9n372sn76npr13o271n4s3p5r29p235746p908p58') + regexs[8].search(r's15q53p9n372sn76npr13o271n4s3p5r29p235746p908p58') + regexs[24].search(r'uggc://jjj.snprobbx.pbz/') + + for i in range(30): + regexs[6].sub(r'', '419', subcount[6]) + re.search(r'(?:^|\s+)gvzrfgnzc(?:\s+|$)', 'gvzrfgnzc') + regexs[7].search(r'419') + + for i in range(29): + regexs[23].sub(r'', 'uggc://jjj.snprobbx.pbz/ybtva.cuc', subcount[23]) + + for i in range(28): + regexs[25].sub(r'', 'Funer guvf tnqtrg', subcount[25]) + regexs[12].sub(r'', 'Funer guvf tnqtrg', subcount[12]) + regexs[26].search(r'uggc://jjj.tbbtyr.pbz/vt/qverpgbel') + + +def block3(): + for i in range(27): + re.sub(r'[A-Za-z]', '', 'e115', 0) + + for i in range(23): + regexs[27].sub(r'', 'qvfcynl', subcount[27]) + regexs[27].sub(r'', 'cbfvgvba', subcount[27]) + + for i in range(22): + regexs[14].sub(r'', 'unaqyr', subcount[14]) + regexs[15].sub(r'', 'unaqyr', subcount[15]) + regexs[14].sub(r'', 'yvar', subcount[14]) + regexs[15].sub(r'', 'yvar', subcount[15]) + regexs[14].sub(r'', 'cnerag puebzr6 fvatyr1 gno', subcount[14]) + regexs[15].sub(r'', 'cnerag puebzr6 fvatyr1 gno', subcount[15]) + regexs[14].sub(r'', 'fyvqre', subcount[14]) + regexs[15].sub(r'', 'fyvqre', subcount[15]) + regexs[28].search(r'') + + for i in range(21): + regexs[12].sub(r'', 'uggc://jjj.zlfcnpr.pbz/', subcount[12]) + regexs[13].search(r'uggc://jjj.zlfcnpr.pbz/') + + for i in range(20): + regexs[29].sub(r'', 'cntrivrj', subcount[29]) + regexs[30].sub(r'', 'cntrivrj', subcount[30]) + regexs[19].search(r'ynfg') + regexs[19].search(r'ba svefg') + regexs[8].search(r'VC=74.125.75.3') + + for i in range(19): + regexs[31].search(r'ra') + + for i in range(18): + regexs[32].split(strings[10]) + regexs[32].split(strings[11]) + regexs[33].sub(r'', strings[12], subcount[33]) + regexs[8].search(r'144631658.0.10.1231363570') + regexs[8].search( + r'144631658.1231363570.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)') + regexs[8].search( + r'144631658.3426875219718084000.1231363570.1231363570.1231363570.1') + regexs[8].search(strings[13]) + regexs[8].search(strings[14]) + regexs[8].search( + r'__hgzn=144631658.3426875219718084000.1231363570.1231363570.1231363570.1') + regexs[8].search(r'__hgzo=144631658.0.10.1231363570') + regexs[8].search( + r'__hgzm=144631658.1231363570.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)') + regexs[34].search(strings[10]) + regexs[34].search(strings[11]) + + for i in range(17): + re.match(r'zfvr', strings[0], re.IGNORECASE) + re.match(r'bcren', strings[0], re.IGNORECASE) + regexs[32].split(strings[15]) + regexs[32].split(strings[16]) + regexs[14].sub(r'', 'ohggba', subcount[14]) + regexs[15].sub(r'', 'ohggba', subcount[15]) + regexs[14].sub(r'', 'puvyq p1 svefg sylbhg pybfrq', subcount[14]) + regexs[15].sub(r'', 'puvyq p1 svefg sylbhg pybfrq', subcount[15]) + regexs[14].sub(r'', 'pvgvrf', subcount[14]) + regexs[15].sub(r'', 'pvgvrf', subcount[15]) + regexs[14].sub(r'', 'pybfrq', subcount[14]) + regexs[15].sub(r'', 'pybfrq', subcount[15]) + regexs[14].sub(r'', 'qry', subcount[14]) + regexs[15].sub(r'', 'qry', subcount[15]) + regexs[14].sub(r'', 'uqy_zba', subcount[14]) + regexs[15].sub(r'', 'uqy_zba', subcount[15]) + regexs[33].sub(r'', strings[17], subcount[33]) + re.sub(r'%3P', '', strings[18], 0) + re.sub(r'%3R', '', strings[18], 0) + re.sub(r'%3q', '', strings[18], 0) + regexs[35].sub(r'', strings[18], subcount[35]) + regexs[14].sub(r'', 'yvaxyvfg16', subcount[14]) + regexs[15].sub(r'', 'yvaxyvfg16', subcount[15]) + regexs[14].sub(r'', 'zvahf', subcount[14]) + regexs[15].sub(r'', 'zvahf', subcount[15]) + regexs[14].sub(r'', 'bcra', subcount[14]) + regexs[15].sub(r'', 'bcra', subcount[15]) + regexs[14].sub(r'', 'cnerag puebzr5 fvatyr1 ps NU', subcount[14]) + regexs[15].sub(r'', 'cnerag puebzr5 fvatyr1 ps NU', subcount[15]) + regexs[14].sub(r'', 'cynlre', subcount[14]) + regexs[15].sub(r'', 'cynlre', subcount[15]) + regexs[14].sub(r'', 'cyhf', subcount[14]) + regexs[15].sub(r'', 'cyhf', subcount[15]) + regexs[14].sub(r'', 'cb_uqy', subcount[14]) + regexs[15].sub(r'', 'cb_uqy', subcount[15]) + regexs[14].sub(r'', 'hyJVzt', subcount[14]) + regexs[15].sub(r'', 'hyJVzt', subcount[15]) + regexs[8].search(r'144631658.0.10.1231363638') + regexs[8].search( + r'144631658.1231363638.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)') + regexs[8].search( + r'144631658.965867047679498800.1231363638.1231363638.1231363638.1') + regexs[8].search(r'4413268q3660') + regexs[8].search(r'4ss747o77904333q374or84qrr1s9r0nprp8r5q81534o94n') + regexs[8].search(r'SbeprqRkcvengvba=633669321699093060') + regexs[8].search(r'VC=74.125.75.20') + regexs[8].search(strings[19]) + regexs[8].search(strings[20]) + regexs[8].search(r'AFP_zp_tfwsbrg-aowb_80=4413268q3660') + regexs[8].search( + r'FrffvbaQQS2=4ss747o77904333q374or84qrr1s9r0nprp8r5q81534o94n') + regexs[8].search( + r'__hgzn=144631658.965867047679498800.1231363638.1231363638.1231363638.1') + regexs[8].search(r'__hgzo=144631658.0.10.1231363638') + regexs[8].search( + r'__hgzm=144631658.1231363638.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)') + regexs[34].search(strings[15]) + regexs[34].search(strings[16]) + + +def block4(): + for i in range(16): + re.sub(r'\*', '', '', 0) + re.search(r'\bnpgvir\b', 'npgvir') + re.search(r'sversbk', strings[0], re.IGNORECASE) + regexs[36].search(r'glcr') + re.search(r'zfvr', strings[0], re.IGNORECASE) + re.search(r'bcren', strings[0], re.IGNORECASE) + + for i in range(15): + regexs[32].split(strings[21]) + regexs[32].split(strings[22]) + regexs[12].sub( + r'', 'uggc://ohyyrgvaf.zlfcnpr.pbz/vaqrk.psz', subcount[12]) + regexs[33].sub(r'', strings[23], subcount[33]) + regexs[37].sub(r'', 'yv', subcount[37]) + regexs[18].sub(r'', 'yv', subcount[18]) + regexs[8].search(r'144631658.0.10.1231367822') + regexs[8].search( + r'144631658.1231367822.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)') + regexs[8].search( + r'144631658.4127520630321984500.1231367822.1231367822.1231367822.1') + regexs[8].search(strings[24]) + regexs[8].search(strings[25]) + regexs[8].search( + r'__hgzn=144631658.4127520630321984500.1231367822.1231367822.1231367822.1') + regexs[8].search(r'__hgzo=144631658.0.10.1231367822') + regexs[8].search( + r'__hgzm=144631658.1231367822.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)') + regexs[34].search(strings[21]) + regexs[34].search(strings[22]) + + # FIXME + # The \{0,65534} should be a * + # There's a current python bug that will stop the regex compilation + # when a * appears there http://bugs.python.org/issue6156. + re.search( + r'\.([\w-]+)|\[(\w+)(?:([!*^$~|]?=)["\']?(.*?)["\']?)?\]|:([\w-]+)(?:\(["\']?(.\{0,65534}?)?["\']?\)|$)', strings[26]) + + regexs[13].search(r'uggc://ohyyrgvaf.zlfcnpr.pbz/vaqrk.psz') + regexs[38].search(r'yv') + + for i in range(14): + regexs[18].sub(r'', '', subcount[18]) + re.sub(r'(\s+e|\s+o[0-9]+)', '', '9.0 e115', 1) + re.sub(r'<', '', 'Funer guvf tnqtrg', 0) + re.sub(r'>', '', 'Funer guvf tnqtrg', 0) + regexs[39].sub(r'', 'Funer guvf tnqtrg', subcount[39]) + regexs[12].sub( + r'', 'uggc://cebsvyrrqvg.zlfcnpr.pbz/vaqrk.psz', subcount[12]) + regexs[40].sub(r'', 'grnfre', subcount[40]) + regexs[41].sub(r'', 'grnfre', subcount[41]) + regexs[42].sub(r'', 'grnfre', subcount[42]) + regexs[43].sub(r'', 'grnfre', subcount[43]) + regexs[44].sub(r'', 'grnfre', subcount[44]) + regexs[45].sub(r'', 'grnfre', subcount[45]) + regexs[46].sub(r'', 'grnfre', subcount[46]) + regexs[47].sub(r'', 'grnfre', subcount[47]) + regexs[48].sub(r'', 'grnfre', subcount[48]) + regexs[16].search(r'znetva-gbc') + regexs[16].search(r'cbfvgvba') + regexs[19].search(r'gno1') + regexs[9].search(r'qz') + regexs[9].search(r'qg') + regexs[9].search(r'zbqobk') + regexs[9].search(r'zbqobkva') + regexs[9].search(r'zbqgvgyr') + regexs[13].search(r'uggc://cebsvyrrqvg.zlfcnpr.pbz/vaqrk.psz') + regexs[26].search(r'/vt/znvytnqtrg') + regexs[49].search(r'glcr') + + +def block5(): + for i in range(13): + regexs[14].sub(r'', 'purpx', subcount[14]) + regexs[15].sub(r'', 'purpx', subcount[15]) + regexs[14].sub(r'', 'pvgl', subcount[14]) + regexs[15].sub(r'', 'pvgl', subcount[15]) + regexs[14].sub(r'', 'qrpe fyvqrgrkg', subcount[14]) + regexs[15].sub(r'', 'qrpe fyvqrgrkg', subcount[15]) + regexs[14].sub(r'', 'svefg fryrpgrq', subcount[14]) + regexs[15].sub(r'', 'svefg fryrpgrq', subcount[15]) + regexs[14].sub(r'', 'uqy_rag', subcount[14]) + regexs[15].sub(r'', 'uqy_rag', subcount[15]) + regexs[14].sub(r'', 'vape fyvqrgrkg', subcount[14]) + regexs[15].sub(r'', 'vape fyvqrgrkg', subcount[15]) + regexs[5].sub(r'', 'vachggrkg QBZPbageby_cynprubyqre', subcount[5]) + regexs[14].sub( + r'', 'cnerag puebzr6 fvatyr1 gno fryrpgrq', subcount[14]) + regexs[15].sub( + r'', 'cnerag puebzr6 fvatyr1 gno fryrpgrq', subcount[15]) + regexs[14].sub(r'', 'cb_guz', subcount[14]) + regexs[15].sub(r'', 'cb_guz', subcount[15]) + regexs[14].sub(r'', 'fhozvg', subcount[14]) + regexs[15].sub(r'', 'fhozvg', subcount[15]) + regexs[50].search(r'') + re.search(r'NccyrJroXvg\/([^\s]*)', strings[0]) + re.search(r'XUGZY', strings[0]) + + for i in range(12): + re.sub(r'(\$\{cebg\})|(\$cebg\b)', '', + '${cebg}://${ubfg}${cngu}/${dz}', 0) + regexs[40].sub(r'', '1', subcount[40]) + regexs[10].sub(r'', '1', subcount[10]) + regexs[51].sub(r'', '1', subcount[51]) + regexs[52].sub(r'', '1', subcount[52]) + regexs[53].sub(r'', '1', subcount[53]) + regexs[39].sub(r'', '1', subcount[39]) + regexs[54].sub(r'', '1', subcount[54]) + re.sub(r'^(.*)\..*$', '', '9.0 e115', 1) + re.sub(r'^.*e(.*)$', '', '9.0 e115', 1) + regexs[55].sub(r'', '', subcount[55]) + regexs[55].sub( + r'', '', subcount[55]) + re.sub(r'^.*\s+(\S+\s+\S+$)', '', strings[1], 1) + regexs[30].sub(r'', 'tzk%2Subzrcntr%2Sfgneg%2Sqr%2S', subcount[30]) + regexs[30].sub(r'', 'tzk', subcount[30]) + re.sub(r'(\$\{ubfg\})|(\$ubfg\b)', '', + 'uggc://${ubfg}${cngu}/${dz}', 0) + regexs[56].sub( + r'', 'uggc://nqpyvrag.hvzfrei.arg${cngu}/${dz}', subcount[56]) + re.sub(r'(\$\{dz\})|(\$dz\b)', '', + 'uggc://nqpyvrag.hvzfrei.arg/wf.at/${dz}', 0) + regexs[29].sub(r'', 'frpgvba', subcount[29]) + regexs[30].sub(r'', 'frpgvba', subcount[30]) + regexs[29].sub(r'', 'fvgr', subcount[29]) + regexs[30].sub(r'', 'fvgr', subcount[30]) + regexs[29].sub(r'', 'fcrpvny', subcount[29]) + regexs[30].sub(r'', 'fcrpvny', subcount[30]) + regexs[36].search(r'anzr') + re.search(r'e', '9.0 e115') + + +def block6(): + for i in range(11): + re.sub(r'(?i)##yv0##', '', strings[27], 0) + regexs[57].sub(r'', strings[27], subcount[57]) + regexs[58].sub(r'', strings[28], subcount[58]) + regexs[59].sub(r'', strings[29], subcount[59]) + re.sub(r'(?i)##\/o##', '', strings[30], 0) + re.sub(r'(?i)##\/v##', '', strings[30], 0) + re.sub(r'(?i)##\/h##', '', strings[30], 0) + re.sub(r'(?i)##o##', '', strings[30], 0) + re.sub(r'(?i)##oe##', '', strings[30], 0) + re.sub(r'(?i)##v##', '', strings[30], 0) + re.sub(r'(?i)##h##', '', strings[30], 0) + re.sub(r'(?i)##n##', '', strings[31], 0) + re.sub(r'(?i)##\/n##', '', strings[32], 0) + + # This prints a unicode escape where the V8 version + # prints the unicode character. + re.sub(r'#~#argjbexybtb#~#', '', strings[33], 0) + + re.search(r' Zbovyr\/', strings[0]) + re.search(r'##yv1##', strings[27], re.IGNORECASE) + re.search(r'##yv10##', strings[28], re.IGNORECASE) + re.search(r'##yv11##', strings[28], re.IGNORECASE) + re.search(r'##yv12##', strings[28], re.IGNORECASE) + re.search(r'##yv13##', strings[28], re.IGNORECASE) + re.search(r'##yv14##', strings[28], re.IGNORECASE) + re.search(r'##yv15##', strings[28], re.IGNORECASE) + regexs[58].search(strings[28]) + re.search(r'##yv17##', strings[29], re.IGNORECASE) + re.search(r'##yv18##', strings[29], re.IGNORECASE) + regexs[59].search(strings[29]) + re.search(r'##yv2##', strings[27], re.IGNORECASE) + re.search(r'##yv20##', strings[30], re.IGNORECASE) + re.search(r'##yv21##', strings[30], re.IGNORECASE) + re.search(r'##yv22##', strings[30], re.IGNORECASE) + re.search(r'##yv23##', strings[30], re.IGNORECASE) + re.search(r'##yv3##', strings[27], re.IGNORECASE) + regexs[57].search(strings[27]) + re.search(r'##yv5##', strings[28], re.IGNORECASE) + re.search(r'##yv6##', strings[28], re.IGNORECASE) + re.search(r'##yv7##', strings[28], re.IGNORECASE) + re.search(r'##yv8##', strings[28], re.IGNORECASE) + re.search(r'##yv9##', strings[28], re.IGNORECASE) + regexs[8].search(r'473qq1rs0n2r70q9qo1pq48n021s9468ron90nps048p4p29') + regexs[8].search(r'SbeprqRkcvengvba=633669325184628362') + regexs[8].search( + r'FrffvbaQQS2=473qq1rs0n2r70q9qo1pq48n021s9468ron90nps048p4p29') + re.search(r'AbxvnA[^\/]*', strings[0]) + + for i in range(10): + re.sub(r'(?:^|\s+)bss(?:\s+|$)', '', ' bss', 0) + re.sub(r'(\$\{0\})|(\$0\b)', '', strings[34], 0) + re.sub(r'(\$\{1\})|(\$1\b)', '', strings[34], 0) + re.sub(r'(\$\{pbzcyrgr\})|(\$pbzcyrgr\b)', '', strings[34], 0) + re.sub(r'(\$\{sentzrag\})|(\$sentzrag\b)', '', strings[34], 0) + re.sub(r'(\$\{ubfgcbeg\})|(\$ubfgcbeg\b)', '', strings[34], 0) + regexs[56].sub(r'', strings[34], subcount[56]) + re.sub(r'(\$\{cebgbpby\})|(\$cebgbpby\b)', '', strings[34], 0) + re.sub(r'(\$\{dhrel\})|(\$dhrel\b)', '', strings[34], 0) + regexs[29].sub(r'', 'nqfvmr', subcount[29]) + regexs[30].sub(r'', 'nqfvmr', subcount[30]) + re.sub(r'(\$\{2\})|(\$2\b)', '', 'uggc://${2}${3}${4}${5}', 0) + re.sub(r'(\$\{3\})|(\$3\b)', '', + 'uggc://wf.hv-cbegny.qr${3}${4}${5}', 0) + regexs[40].sub(r'', 'arjf', subcount[40]) + regexs[41].sub(r'', 'arjf', subcount[41]) + regexs[42].sub(r'', 'arjf', subcount[42]) + regexs[43].sub(r'', 'arjf', subcount[43]) + regexs[44].sub(r'', 'arjf', subcount[44]) + regexs[45].sub(r'', 'arjf', subcount[45]) + regexs[46].sub(r'', 'arjf', subcount[46]) + regexs[47].sub(r'', 'arjf', subcount[47]) + regexs[48].sub(r'', 'arjf', subcount[48]) + re.search(r' PC=i=(\d+)&oe=(.)', strings[35]) + regexs[60].search(r' ') + regexs[60].search(r' bss') + regexs[60].search(r'') + regexs[19].search(r' ') + regexs[19].search(r'svefg ba') + regexs[19].search(r'ynfg vtaber') + regexs[19].search(r'ba') + regexs[9].search(r'scnq so ') + regexs[9].search(r'zrqvgobk') + regexs[9].search(r'hsgy') + regexs[9].search(r'lhv-h') + re.search(r'Fnsnev|Xbadhrebe|XUGZY', strings[0], re.IGNORECASE) + regexs[61].search( + r'uggc://wf.hv-cbegny.qr/tzk/ubzr/wf/20080602/onfr.wf') + regexs[62].search(r'#Ybtva_rznvy') + + +def block7(): + for i in range(9): + regexs[40].sub(r'', '0', subcount[40]) + regexs[10].sub(r'', '0', subcount[10]) + regexs[51].sub(r'', '0', subcount[51]) + regexs[52].sub(r'', '0', subcount[52]) + regexs[53].sub(r'', '0', subcount[53]) + regexs[39].sub(r'', '0', subcount[39]) + regexs[54].sub(r'', '0', subcount[54]) + regexs[40].sub(r'', 'Lrf', subcount[40]) + regexs[10].sub(r'', 'Lrf', subcount[10]) + regexs[51].sub(r'', 'Lrf', subcount[51]) + regexs[52].sub(r'', 'Lrf', subcount[52]) + regexs[53].sub(r'', 'Lrf', subcount[53]) + regexs[39].sub(r'', 'Lrf', subcount[39]) + regexs[54].sub(r'', 'Lrf', subcount[54]) + + for i in range(8): + regexs[63].sub(r'', 'Pybfr {0}', subcount[63]) + regexs[63].sub(r'', 'Bcra {0}', subcount[63]) + regexs[32].split(strings[36]) + regexs[32].split(strings[37]) + regexs[14].sub(r'', 'puvyq p1 svefg gnournqref', subcount[14]) + regexs[15].sub(r'', 'puvyq p1 svefg gnournqref', subcount[15]) + regexs[14].sub(r'', 'uqy_fcb', subcount[14]) + regexs[15].sub(r'', 'uqy_fcb', subcount[15]) + regexs[14].sub(r'', 'uvag', subcount[14]) + regexs[15].sub(r'', 'uvag', subcount[15]) + regexs[33].sub(r'', strings[38], subcount[33]) + regexs[14].sub(r'', 'yvfg', subcount[14]) + regexs[15].sub(r'', 'yvfg', subcount[15]) + regexs[30].sub(r'', 'at_bhgre', subcount[30]) + regexs[14].sub(r'', 'cnerag puebzr5 qbhoyr2 NU', subcount[14]) + regexs[15].sub(r'', 'cnerag puebzr5 qbhoyr2 NU', subcount[15]) + regexs[14].sub( + r'', 'cnerag puebzr5 dhnq5 ps NU osyvax zbarl', subcount[14]) + regexs[15].sub( + r'', 'cnerag puebzr5 dhnq5 ps NU osyvax zbarl', subcount[15]) + regexs[14].sub(r'', 'cnerag puebzr6 fvatyr1', subcount[14]) + regexs[15].sub(r'', 'cnerag puebzr6 fvatyr1', subcount[15]) + regexs[14].sub(r'', 'cb_qrs', subcount[14]) + regexs[15].sub(r'', 'cb_qrs', subcount[15]) + regexs[14].sub(r'', 'gnopbagrag', subcount[14]) + regexs[15].sub(r'', 'gnopbagrag', subcount[15]) + regexs[30].sub(r'', 'iv_svefg_gvzr', subcount[30]) + re.search(r'(^|.)(ronl|qri-ehf3.wbg)(|fgberf|zbgbef|yvirnhpgvbaf|jvxv|rkcerff|punggre).(pbz(|.nh|.pa|.ux|.zl|.ft|.oe|.zk)|pb(.hx|.xe|.am)|pn|qr|se|vg|ay|or|ng|pu|vr|va|rf|cy|cu|fr)$', 'cntrf.ronl.pbz', re.IGNORECASE) + regexs[8].search(r'144631658.0.10.1231364074') + regexs[8].search( + r'144631658.1231364074.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)') + regexs[8].search( + r'144631658.2294274870215848400.1231364074.1231364074.1231364074.1') + regexs[8].search(r'4413241q3660') + regexs[8].search(r'SbeprqRkcvengvba=633669357391353591') + regexs[8].search(strings[39]) + regexs[8].search(strings[40]) + regexs[8].search(r'AFP_zp_kkk-gdzogv_80=4413241q3660') + regexs[8].search( + r'FrffvbaQQS2=p98s8o9q42nr21or1r61pqorn1n002nsss569635984s6qp7') + regexs[8].search( + r'__hgzn=144631658.2294274870215848400.1231364074.1231364074.1231364074.1') + regexs[8].search(r'__hgzo=144631658.0.10.1231364074') + regexs[8].search( + r'__hgzm=144631658.1231364074.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)') + regexs[8].search(r'p98s8o9q42nr21or1r61pqorn1n002nsss569635984s6qp7') + regexs[34].search(strings[36]) + regexs[34].search(strings[37]) + + +def block8(): + for i in range(7): + re.match(r'\d+', strings[1]) + regexs[64].sub(r'', 'nsgre', subcount[64]) + regexs[64].sub(r'', 'orsber', subcount[64]) + regexs[64].sub(r'', 'obggbz', subcount[64]) + regexs[65].sub(r'', 'ohvygva_jrngure.kzy', subcount[65]) + regexs[37].sub(r'', 'ohggba', subcount[37]) + regexs[18].sub(r'', 'ohggba', subcount[18]) + regexs[65].sub(r'', 'qngrgvzr.kzy', subcount[65]) + regexs[65].sub( + r'', 'uggc://eff.paa.pbz/eff/paa_gbcfgbevrf.eff', subcount[65]) + regexs[37].sub(r'', 'vachg', subcount[37]) + regexs[18].sub(r'', 'vachg', subcount[18]) + regexs[64].sub(r'', 'vafvqr', subcount[64]) + regexs[27].sub(r'', 'cbvagre', subcount[27]) + re.sub(r'[A-Z]', '', 'cbfvgvba', 0) + regexs[27].sub(r'', 'gbc', subcount[27]) + regexs[64].sub(r'', 'gbc', subcount[64]) + regexs[37].sub(r'', 'hy', subcount[37]) + regexs[18].sub(r'', 'hy', subcount[18]) + regexs[37].sub(r'', strings[26], subcount[37]) + regexs[18].sub(r'', strings[26], subcount[18]) + regexs[65].sub(r'', 'lbhghor_vtbbtyr/i2/lbhghor.kzy', subcount[65]) + regexs[27].sub(r'', 'm-vaqrk', subcount[27]) + re.search(r'#([\w-]+)', strings[26]) + regexs[16].search(r'urvtug') + regexs[16].search(r'znetvaGbc') + regexs[16].search(r'jvqgu') + regexs[19].search(r'gno0 svefg ba') + regexs[19].search(r'gno0 ba') + regexs[19].search(r'gno4 ynfg') + regexs[19].search(r'gno4') + regexs[19].search(r'gno5') + regexs[19].search(r'gno6') + regexs[19].search(r'gno7') + regexs[19].search(r'gno8') + re.search(r'NqborNVE\/([^\s]*)', strings[0]) + re.search(r'NccyrJroXvg\/([^ ]*)', strings[0]) + re.search(r'XUGZY', strings[0], re.IGNORECASE) + re.search(r'^(?:obql|ugzy)$', 'YV', re.IGNORECASE) + regexs[38].search(r'ohggba') + regexs[38].search(r'vachg') + regexs[38].search(r'hy') + regexs[38].search(strings[26]) + re.search(r'^(\w+|\*)', strings[26]) + re.search(r'znp|jva|yvahk', 'Jva32', re.IGNORECASE) + re.search(r'eton?\([\d\s,]+\)', 'fgngvp') + + for i in range(6): + re.sub(r'\r', '', '', 0) + regexs[40].sub(r'', '/', subcount[40]) + regexs[10].sub(r'', '/', subcount[10]) + regexs[51].sub(r'', '/', subcount[51]) + regexs[52].sub(r'', '/', subcount[52]) + regexs[53].sub(r'', '/', subcount[53]) + regexs[39].sub(r'', '/', subcount[39]) + regexs[54].sub(r'', '/', subcount[54]) + regexs[63].sub( + r'', 'uggc://zfacbegny.112.2b7.arg/o/ff/zfacbegnyubzr/1/U.7-cqi-2/{0}?[NDO]&{1}&{2}&[NDR]', subcount[63]) + regexs[12].sub(r'', strings[41], subcount[12]) + regexs[23].sub(r'', 'uggc://jjj.snprobbx.pbz/fepu.cuc', subcount[23]) + regexs[40].sub(r'', 'freivpr', subcount[40]) + regexs[41].sub(r'', 'freivpr', subcount[41]) + regexs[42].sub(r'', 'freivpr', subcount[42]) + regexs[43].sub(r'', 'freivpr', subcount[43]) + regexs[44].sub(r'', 'freivpr', subcount[44]) + regexs[45].sub(r'', 'freivpr', subcount[45]) + regexs[46].sub(r'', 'freivpr', subcount[46]) + regexs[47].sub(r'', 'freivpr', subcount[47]) + regexs[48].sub(r'', 'freivpr', subcount[48]) + re.search(r'((ZFVR\s+([6-9]|\d\d)\.))', strings[0]) + regexs[66].search(r'') + regexs[50].search(r'fryrpgrq') + regexs[8].search(r'8sqq78r9n442851q565599o401385sp3s04r92rnn7o19ssn') + regexs[8].search(r'SbeprqRkcvengvba=633669340386893867') + regexs[8].search(r'VC=74.125.75.17') + regexs[8].search( + r'FrffvbaQQS2=8sqq78r9n442851q565599o401385sp3s04r92rnn7o19ssn') + re.search(r'Xbadhrebe|Fnsnev|XUGZY', strings[0]) + regexs[13].search(strings[41]) + regexs[49].search(r'unfsbphf') + + +def block9(): + for i in range(5): + regexs[32].split(strings[42]) + regexs[32].split(strings[43]) + regexs[20].split( + r'svz_zlfcnpr_hfre-ivrj-pbzzragf,svz_zlfcnpr_havgrq-fgngrf') + regexs[33].sub(r'', strings[44], subcount[33]) + regexs[67].sub( + r'', 'zrah_arj zrah_arj_gbttyr zrah_gbttyr', subcount[67]) + regexs[67].sub( + r'', 'zrah_byq zrah_byq_gbttyr zrah_gbttyr', subcount[67]) + regexs[8].search(r'102n9o0o9pq60132qn0337rr867p75953502q2s27s2s5r98') + regexs[8].search(r'144631658.0.10.1231364380') + regexs[8].search( + r'144631658.1231364380.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)') + regexs[8].search( + r'144631658.3931862196947939300.1231364380.1231364380.1231364380.1') + regexs[8].search(r'441326q33660') + regexs[8].search(r'SbeprqRkcvengvba=633669341278771470') + regexs[8].search(strings[45]) + regexs[8].search(strings[46]) + regexs[8].search(r'AFP_zp_dfctwzssrwh-aowb_80=441326q33660') + regexs[8].search( + r'FrffvbaQQS2=102n9o0o9pq60132qn0337rr867p75953502q2s27s2s5r98') + regexs[8].search( + r'__hgzn=144631658.3931862196947939300.1231364380.1231364380.1231364380.1') + regexs[8].search(r'__hgzo=144631658.0.10.1231364380') + regexs[8].search( + r'__hgzm=144631658.1231364380.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)') + + for i in range(4): + regexs[14].sub(r'', ' yvfg1', subcount[14]) + regexs[15].sub(r'', ' yvfg1', subcount[15]) + regexs[14].sub(r'', ' yvfg2', subcount[14]) + regexs[15].sub(r'', ' yvfg2', subcount[15]) + regexs[14].sub(r'', ' frneputebhc1', subcount[14]) + regexs[15].sub(r'', ' frneputebhc1', subcount[15]) + regexs[68].sub(r'', strings[47], subcount[68]) + regexs[18].sub(r'', strings[47], subcount[18]) + re.sub(r'&', '', '', 0) + regexs[35].sub(r'', '', subcount[35]) + regexs[63].sub(r'', '(..-{0})(|(d+)|)', subcount[63]) + regexs[18].sub(r'', strings[48], subcount[18]) + regexs[56].sub( + r'', '//vzt.jro.qr/vij/FC/${cngu}/${anzr}/${inyhr}?gf=${abj}', subcount[56]) + re.sub(r'(\$\{anzr\})|(\$anzr\b)', '', + '//vzt.jro.qr/vij/FC/tzk_uc/${anzr}/${inyhr}?gf=${abj}', 0) + regexs[69].sub( + r'', 'Jvaqbjf Yvir Ubgznvy{1}', subcount[69]) + regexs[63].sub( + r'', '{0}{1}', subcount[63]) + regexs[69].sub( + r'', '{1}', subcount[69]) + regexs[63].sub( + r'', '{1}', subcount[63]) + regexs[15].sub(r'', 'Vzntrf', subcount[15]) + regexs[15].sub(r'', 'ZFA', subcount[15]) + regexs[15].sub(r'', 'Zncf', subcount[15]) + regexs[39].sub(r'', 'Zbq-Vasb-Vasb-WninFpevcgUvag', subcount[39]) + regexs[15].sub(r'', 'Arjf', subcount[15]) + regexs[32].split(strings[49]) + regexs[32].split(strings[50]) + regexs[15].sub(r'', 'Ivqrb', subcount[15]) + regexs[15].sub(r'', 'Jro', subcount[15]) + regexs[39].sub(r'', 'n', subcount[39]) + regexs[70].split(r'nwnkFgneg') + regexs[70].split(r'nwnkFgbc') + regexs[14].sub(r'', 'ovaq', subcount[14]) + regexs[15].sub(r'', 'ovaq', subcount[15]) + regexs[63].sub( + r'', 'oevatf lbh zber. Zber fcnpr (5TO), zber frphevgl, fgvyy serr.', subcount[63]) + regexs[14].sub(r'', 'puvyq p1 svefg qrpx', subcount[14]) + regexs[15].sub(r'', 'puvyq p1 svefg qrpx', subcount[15]) + regexs[14].sub(r'', 'puvyq p1 svefg qbhoyr2', subcount[14]) + regexs[15].sub(r'', 'puvyq p1 svefg qbhoyr2', subcount[15]) + regexs[14].sub(r'', 'puvyq p2 ynfg', subcount[14]) + regexs[15].sub(r'', 'puvyq p2 ynfg', subcount[15]) + regexs[14].sub(r'', 'puvyq p2', subcount[14]) + regexs[15].sub(r'', 'puvyq p2', subcount[15]) + regexs[14].sub(r'', 'puvyq p3', subcount[14]) + regexs[15].sub(r'', 'puvyq p3', subcount[15]) + regexs[14].sub(r'', 'puvyq p4 ynfg', subcount[14]) + regexs[15].sub(r'', 'puvyq p4 ynfg', subcount[15]) + regexs[14].sub(r'', 'pbclevtug', subcount[14]) + regexs[15].sub(r'', 'pbclevtug', subcount[15]) + regexs[14].sub(r'', 'qZFAZR_1', subcount[14]) + regexs[15].sub(r'', 'qZFAZR_1', subcount[15]) + regexs[14].sub(r'', 'qbhoyr2 ps', subcount[14]) + regexs[15].sub(r'', 'qbhoyr2 ps', subcount[15]) + regexs[14].sub(r'', 'qbhoyr2', subcount[14]) + regexs[15].sub(r'', 'qbhoyr2', subcount[15]) + regexs[14].sub(r'', 'uqy_arj', subcount[14]) + regexs[15].sub(r'', 'uqy_arj', subcount[15]) + regexs[30].sub(r'', 'uc_fubccvatobk', subcount[30]) + regexs[29].sub(r'', 'ugzy%2Rvq', subcount[29]) + regexs[30].sub(r'', 'ugzy%2Rvq', subcount[30]) + regexs[33].sub(r'', strings[51], subcount[33]) + regexs[71].sub( + r'', 'uggc://wf.hv-cbegny.qr/tzk/ubzr/wf/20080602/cebgbglcr.wf${4}${5}', subcount[71]) + regexs[72].sub( + r'', 'uggc://wf.hv-cbegny.qr/tzk/ubzr/wf/20080602/cebgbglcr.wf${5}', subcount[72]) + regexs[73].sub(r'', strings[52], subcount[73]) + regexs[69].sub( + r'', 'uggc://zfacbegny.112.2b7.arg/o/ff/zfacbegnyubzr/1/U.7-cqi-2/f55332979829981?[NDO]&{1}&{2}&[NDR]', subcount[69]) + regexs[14].sub(r'', 'vztZFSG', subcount[14]) + regexs[15].sub(r'', 'vztZFSG', subcount[15]) + regexs[14].sub(r'', 'zfasbbg1 ps', subcount[14]) + regexs[15].sub(r'', 'zfasbbg1 ps', subcount[15]) + regexs[14].sub(r'', strings[53], subcount[14]) + regexs[15].sub(r'', strings[53], subcount[15]) + regexs[14].sub( + r'', 'cnerag puebzr6 fvatyr1 gno fryrpgrq ovaq', subcount[14]) + regexs[15].sub( + r'', 'cnerag puebzr6 fvatyr1 gno fryrpgrq ovaq', subcount[15]) + regexs[14].sub(r'', 'cevznel', subcount[14]) + regexs[15].sub(r'', 'cevznel', subcount[15]) + regexs[30].sub(r'', 'erpgnatyr', subcount[30]) + regexs[14].sub(r'', 'frpbaqnel', subcount[14]) + regexs[15].sub(r'', 'frpbaqnel', subcount[15]) + regexs[70].split(r'haybnq') + regexs[63].sub(r'', '{0}{1}1', subcount[63]) + regexs[69].sub(r'', '|{1}1', subcount[69]) + re.search(r'(..-HF)(\|(\d+)|)', 'xb-xe,ra-va,gu-gu', re.IGNORECASE) + regexs[4].search(r'/ZlFcnprNccf/NccPnainf,45000012') + regexs[8].search(r'144631658.0.10.1231367708') + regexs[8].search( + r'144631658.1231367708.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)') + regexs[8].search( + r'144631658.2770915348920628700.1231367708.1231367708.1231367708.1') + regexs[8].search(r'4413235p3660') + regexs[8].search(r'441327q73660') + regexs[8].search(r'9995p6rp12rrnr893334ro7nq70o7p64p69rqn844prs1473') + regexs[8].search(r'SbeprqRkcvengvba=633669350559478880') + regexs[8].search(strings[54]) + regexs[8].search(strings[55]) + regexs[8].search(r'AFP_zp_dfctwzs-aowb_80=441327q73660') + regexs[8].search(r'AFP_zp_kkk-aowb_80=4413235p3660') + regexs[8].search( + r'FrffvbaQQS2=9995p6rp12rrnr893334ro7nq70o7p64p69rqn844prs1473') + regexs[8].search( + r'__hgzn=144631658.2770915348920628700.1231367708.1231367708.1231367708.1') + regexs[8].search(r'__hgzo=144631658.0.10.1231367708') + regexs[8].search( + r'__hgzm=144631658.1231367708.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)') + regexs[34].search(strings[49]) + regexs[34].search(strings[50]) + re.search(r'ZFVR\s+5[.]01', strings[0]) + re.search(r'HF(?=;)', strings[56], re.IGNORECASE) + regexs[74].search(strings[47]) + regexs[28].search(r'svefg npgvir svefgNpgvir') + regexs[28].search(r'ynfg') + re.search( + r'\bp:(..)', 'm:94043|yn:37.4154|yb:-122.0585|p:HF', re.IGNORECASE) + regexs[75].search(strings[57]) + regexs[75].search(strings[58]) + regexs[76].search(strings[57]) + regexs[76].search(strings[58]) + regexs[77].search(strings[57]) + regexs[77].search(strings[58]) + re.search(r'\bhfucce\s*=\s*([^;]*)', strings[59], re.IGNORECASE) + regexs[78].search(strings[57]) + regexs[78].search(strings[58]) + re.search(r'\bjci\s*=\s*([^;]*)', strings[59], re.IGNORECASE) + regexs[79].search(strings[58]) + regexs[79].search(strings[60]) + regexs[79].search(strings[59]) + re.search( + r'\|p:([a-z]{2})', 'm:94043|yn:37.4154|yb:-122.0585|p:HF|ue:1', re.IGNORECASE) + regexs[80].search(strings[47]) + regexs[61].search(r'cebgbglcr.wf') + regexs[68].search(strings[47]) + regexs[81].search(strings[47]) + regexs[82].search(strings[47]) + re.search(r'^Fubpxjnir Synfu (\d)', strings[1]) + re.search(r'^Fubpxjnir Synfu (\d+)', strings[1]) + regexs[83].search(r'[bowrpg tybony]') + regexs[62].search(strings[47]) + regexs[84].search(strings[61]) + regexs[84].search(strings[62]) + re.search(r'jroxvg', strings[63]) + + +def block10(): + for i in range(3): + regexs[39].sub(r'', '%3Szxg=ra-HF', subcount[39]) + regexs[40].sub(r'', '-8', subcount[40]) + regexs[10].sub(r'', '-8', subcount[10]) + regexs[51].sub(r'', '-8', subcount[51]) + regexs[52].sub(r'', '-8', subcount[52]) + regexs[53].sub(r'', '-8', subcount[53]) + regexs[39].sub(r'', '-8', subcount[39]) + regexs[54].sub(r'', '-8', subcount[54]) + regexs[40].sub(r'', '1.5', subcount[40]) + regexs[10].sub(r'', '1.5', subcount[10]) + regexs[51].sub(r'', '1.5', subcount[51]) + regexs[52].sub(r'', '1.5', subcount[52]) + regexs[53].sub(r'', '1.5', subcount[53]) + regexs[39].sub(r'', '1.5', subcount[39]) + regexs[54].sub(r'', '1.5', subcount[54]) + regexs[40].sub(r'', '1024k768', subcount[40]) + regexs[10].sub(r'', '1024k768', subcount[10]) + regexs[51].sub(r'', '1024k768', subcount[51]) + regexs[52].sub(r'', '1024k768', subcount[52]) + regexs[53].sub(r'', '1024k768', subcount[53]) + regexs[39].sub(r'', '1024k768', subcount[39]) + regexs[54].sub(r'', '1024k768', subcount[54]) + regexs[40].sub(r'', strings[64], subcount[40]) + regexs[10].sub(r'', strings[64], subcount[10]) + regexs[51].sub(r'', strings[64], subcount[51]) + regexs[52].sub(r'', strings[64], subcount[52]) + regexs[53].sub(r'', strings[64], subcount[53]) + regexs[39].sub(r'', strings[64], subcount[39]) + regexs[54].sub(r'', strings[64], subcount[54]) + regexs[40].sub(r'', '14', subcount[40]) + regexs[10].sub(r'', '14', subcount[10]) + regexs[51].sub(r'', '14', subcount[51]) + regexs[52].sub(r'', '14', subcount[52]) + regexs[53].sub(r'', '14', subcount[53]) + regexs[39].sub(r'', '14', subcount[39]) + regexs[54].sub(r'', '14', subcount[54]) + regexs[40].sub(r'', '24', subcount[40]) + regexs[10].sub(r'', '24', subcount[10]) + regexs[51].sub(r'', '24', subcount[51]) + regexs[52].sub(r'', '24', subcount[52]) + regexs[53].sub(r'', '24', subcount[53]) + regexs[39].sub(r'', '24', subcount[39]) + regexs[54].sub(r'', '24', subcount[54]) + regexs[40].sub(r'', strings[65], subcount[40]) + regexs[10].sub(r'', strings[65], subcount[10]) + regexs[51].sub(r'', strings[65], subcount[51]) + regexs[52].sub(r'', strings[65], subcount[52]) + regexs[53].sub(r'', strings[65], subcount[53]) + regexs[39].sub(r'', strings[65], subcount[39]) + regexs[54].sub(r'', strings[65], subcount[54]) + regexs[40].sub(r'', strings[66], subcount[40]) + regexs[10].sub(r'', strings[66], subcount[10]) + regexs[51].sub(r'', strings[66], subcount[51]) + regexs[52].sub(r'', strings[66], subcount[52]) + regexs[53].sub(r'', strings[66], subcount[53]) + regexs[39].sub(r'', strings[66], subcount[39]) + regexs[54].sub(r'', strings[66], subcount[54]) + regexs[40].sub(r'', '9.0', subcount[40]) + regexs[10].sub(r'', '9.0', subcount[10]) + regexs[51].sub(r'', '9.0', subcount[51]) + regexs[52].sub(r'', '9.0', subcount[52]) + regexs[53].sub(r'', '9.0', subcount[53]) + regexs[39].sub(r'', '9.0', subcount[39]) + regexs[54].sub(r'', '9.0', subcount[54]) + regexs[40].sub(r'', '994k634', subcount[40]) + regexs[10].sub(r'', '994k634', subcount[10]) + regexs[51].sub(r'', '994k634', subcount[51]) + regexs[52].sub(r'', '994k634', subcount[52]) + regexs[53].sub(r'', '994k634', subcount[53]) + regexs[39].sub(r'', '994k634', subcount[39]) + regexs[54].sub(r'', '994k634', subcount[54]) + regexs[40].sub(r'', '?zxg=ra-HF', subcount[40]) + regexs[10].sub(r'', '?zxg=ra-HF', subcount[10]) + regexs[51].sub(r'', '?zxg=ra-HF', subcount[51]) + regexs[52].sub(r'', '?zxg=ra-HF', subcount[52]) + regexs[53].sub(r'', '?zxg=ra-HF', subcount[53]) + regexs[54].sub(r'', '?zxg=ra-HF', subcount[54]) + regexs[25].sub(r'', 'PAA.pbz', subcount[25]) + regexs[12].sub(r'', 'PAA.pbz', subcount[12]) + regexs[39].sub(r'', 'PAA.pbz', subcount[39]) + regexs[25].sub(r'', 'Qngr & Gvzr', subcount[25]) + regexs[12].sub(r'', 'Qngr & Gvzr', subcount[12]) + regexs[39].sub(r'', 'Qngr & Gvzr', subcount[39]) + regexs[40].sub(r'', 'Frnepu Zvpebfbsg.pbz', subcount[40]) + regexs[54].sub(r'', 'Frnepu Zvpebfbsg.pbz', subcount[54]) + regexs[10].sub(r'', strings[67], subcount[10]) + regexs[51].sub(r'', strings[67], subcount[51]) + regexs[52].sub(r'', strings[67], subcount[52]) + regexs[53].sub(r'', strings[67], subcount[53]) + regexs[39].sub(r'', strings[67], subcount[39]) + regexs[32].split(strings[68]) + regexs[32].split(strings[69]) + regexs[52].sub(r'', strings[70], subcount[52]) + regexs[53].sub(r'', strings[70], subcount[53]) + regexs[39].sub(r'', strings[70], subcount[39]) + regexs[40].sub(r'', strings[71], subcount[40]) + regexs[10].sub(r'', strings[71], subcount[10]) + regexs[51].sub(r'', strings[71], subcount[51]) + regexs[54].sub(r'', strings[71], subcount[54]) + regexs[25].sub(r'', 'Jrngure', subcount[25]) + regexs[12].sub(r'', 'Jrngure', subcount[12]) + regexs[39].sub(r'', 'Jrngure', subcount[39]) + regexs[25].sub(r'', 'LbhGhor', subcount[25]) + regexs[12].sub(r'', 'LbhGhor', subcount[12]) + regexs[39].sub(r'', 'LbhGhor', subcount[39]) + regexs[33].sub(r'', strings[72], subcount[33]) + re.sub(r'^erzbgr_vsenzr_', '', 'erzbgr_vsenzr_1', 1) + regexs[40].sub(r'', strings[73], subcount[40]) + regexs[10].sub(r'', strings[73], subcount[10]) + regexs[51].sub(r'', strings[73], subcount[51]) + regexs[52].sub(r'', strings[73], subcount[52]) + regexs[53].sub(r'', strings[73], subcount[53]) + regexs[39].sub(r'', strings[73], subcount[39]) + regexs[54].sub(r'', strings[73], subcount[54]) + regexs[40].sub(r'', strings[74], subcount[40]) + regexs[10].sub(r'', strings[74], subcount[10]) + regexs[51].sub(r'', strings[74], subcount[51]) + regexs[52].sub(r'', strings[74], subcount[52]) + regexs[53].sub(r'', strings[74], subcount[53]) + regexs[39].sub(r'', strings[74], subcount[39]) + regexs[54].sub(r'', strings[74], subcount[54]) + re.sub(r'\-', '', 'lhv-h', 0) + regexs[9].search(r'p') + regexs[9].search(r'qz p') + regexs[9].search(r'zbqynory') + regexs[9].search(r'lhv-h svefg') + regexs[8].search(r'144631658.0.10.1231365779') + regexs[8].search( + r'144631658.1231365779.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)') + regexs[8].search( + r'144631658.1877536177953918500.1231365779.1231365779.1231365779.1') + regexs[8].search(strings[75]) + regexs[8].search(strings[76]) + regexs[8].search( + r'__hgzn=144631658.1877536177953918500.1231365779.1231365779.1231365779.1') + regexs[8].search(r'__hgzo=144631658.0.10.1231365779') + regexs[8].search( + r'__hgzm=144631658.1231365779.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)') + regexs[34].search(strings[68]) + regexs[34].search(strings[69]) + re.search(r'^$', '') + regexs[31].search(r'qr') + re.search(r'^znk\d+$', '') + re.search(r'^zva\d+$', '') + re.search(r'^erfgber$', '') + regexs[85].search(r'zbqobkva zbqobk_abcnqqvat ') + regexs[85].search(r'zbqgvgyr') + regexs[85].search(r'eaq_zbqobkva ') + regexs[85].search(r'eaq_zbqgvgyr ') + re.search(r'frpgvba\d+_pbagragf', 'obggbz_ani') + + +def block11(): + for i in range(2): + regexs[18].sub(r'', ' .pybfr', subcount[18]) + regexs[18].sub(r'', ' n.svryqOgaPnapry', subcount[18]) + regexs[18].sub(r'', ' qg', subcount[18]) + regexs[68].sub(r'', strings[77], subcount[68]) + regexs[18].sub(r'', strings[77], subcount[18]) + regexs[39].sub(r'', '', subcount[39]) + re.sub(r'^', '', '', 1) + regexs[86].split(r'') + regexs[39].sub(r'', '*', subcount[39]) + regexs[68].sub(r'', '*', subcount[68]) + regexs[18].sub(r'', '*', subcount[18]) + regexs[68].sub(r'', '.pybfr', subcount[68]) + regexs[18].sub(r'', '.pybfr', subcount[18]) + regexs[87].sub( + r'', '//vzt.jro.qr/vij/FC/tzk_uc/fperra/${inyhr}?gf=${abj}', subcount[87]) + regexs[88].sub( + r'', '//vzt.jro.qr/vij/FC/tzk_uc/fperra/1024?gf=${abj}', subcount[88]) + regexs[87].sub( + r'', '//vzt.jro.qr/vij/FC/tzk_uc/jvafvmr/${inyhr}?gf=${abj}', subcount[87]) + regexs[88].sub( + r'', '//vzt.jro.qr/vij/FC/tzk_uc/jvafvmr/992/608?gf=${abj}', subcount[88]) + regexs[30].sub(r'', '300k120', subcount[30]) + regexs[30].sub(r'', '300k250', subcount[30]) + regexs[30].sub(r'', '310k120', subcount[30]) + regexs[30].sub(r'', '310k170', subcount[30]) + regexs[30].sub(r'', '310k250', subcount[30]) + re.sub(r'^.*\.(.*)\s.*$', '', '9.0 e115', 1) + regexs[2].sub(r'', 'Nppbeqvba', subcount[2]) + regexs[89].sub(r'', 'Nxghryy\x0a', subcount[89]) + regexs[90].sub(r'', 'Nxghryy\x0a', subcount[90]) + regexs[2].sub(r'', 'Nccyvpngvba', subcount[2]) + regexs[89].sub(r'', 'Oyvpxchaxg\x0a', subcount[89]) + regexs[90].sub(r'', 'Oyvpxchaxg\x0a', subcount[90]) + regexs[89].sub(r'', 'Svanamra\x0a', subcount[89]) + regexs[90].sub(r'', 'Svanamra\x0a', subcount[90]) + regexs[89].sub(r'', 'Tnzrf\x0a', subcount[89]) + regexs[90].sub(r'', 'Tnzrf\x0a', subcount[90]) + regexs[89].sub(r'', 'Ubebfxbc\x0a', subcount[89]) + regexs[90].sub(r'', 'Ubebfxbc\x0a', subcount[90]) + regexs[89].sub(r'', 'Xvab\x0a', subcount[89]) + regexs[90].sub(r'', 'Xvab\x0a', subcount[90]) + regexs[2].sub(r'', 'Zbqhyrf', subcount[2]) + regexs[89].sub(r'', 'Zhfvx\x0a', subcount[89]) + regexs[90].sub(r'', 'Zhfvx\x0a', subcount[90]) + regexs[89].sub(r'', 'Anpuevpugra\x0a', subcount[89]) + regexs[90].sub(r'', 'Anpuevpugra\x0a', subcount[90]) + regexs[2].sub(r'', 'Cuk', subcount[2]) + regexs[70].split(r'ErdhrfgSvavfu') + regexs[70].split(r'ErdhrfgSvavfu.NWNK.Cuk') + regexs[89].sub(r'', 'Ebhgr\x0a', subcount[89]) + regexs[90].sub(r'', 'Ebhgr\x0a', subcount[90]) + regexs[32].split(strings[78]) + regexs[32].split(strings[79]) + regexs[32].split(strings[80]) + regexs[32].split(strings[81]) + regexs[89].sub(r'', 'Fcbeg\x0a', subcount[89]) + regexs[90].sub(r'', 'Fcbeg\x0a', subcount[90]) + regexs[89].sub(r'', 'GI-Fcbg\x0a', subcount[89]) + regexs[90].sub(r'', 'GI-Fcbg\x0a', subcount[90]) + regexs[89].sub(r'', 'Gbhe\x0a', subcount[89]) + regexs[90].sub(r'', 'Gbhe\x0a', subcount[90]) + regexs[89].sub(r'', 'Hagreunyghat\x0a', subcount[89]) + regexs[90].sub(r'', 'Hagreunyghat\x0a', subcount[90]) + regexs[89].sub(r'', 'Ivqrb\x0a', subcount[89]) + regexs[90].sub(r'', 'Ivqrb\x0a', subcount[90]) + regexs[89].sub(r'', 'Jrggre\x0a', subcount[89]) + regexs[90].sub(r'', 'Jrggre\x0a', subcount[90]) + regexs[68].sub(r'', strings[82], subcount[68]) + regexs[18].sub(r'', strings[82], subcount[18]) + regexs[68].sub(r'', strings[83], subcount[68]) + regexs[18].sub(r'', strings[83], subcount[18]) + regexs[68].sub(r'', strings[84], subcount[68]) + regexs[18].sub(r'', strings[84], subcount[18]) + regexs[30].sub(r'', 'nqiFreivprObk', subcount[30]) + regexs[30].sub(r'', 'nqiFubccvatObk', subcount[30]) + regexs[39].sub(r'', 'nwnk', subcount[39]) + regexs[40].sub(r'', 'nxghryy', subcount[40]) + regexs[41].sub(r'', 'nxghryy', subcount[41]) + regexs[42].sub(r'', 'nxghryy', subcount[42]) + regexs[43].sub(r'', 'nxghryy', subcount[43]) + regexs[44].sub(r'', 'nxghryy', subcount[44]) + regexs[45].sub(r'', 'nxghryy', subcount[45]) + regexs[46].sub(r'', 'nxghryy', subcount[46]) + regexs[47].sub(r'', 'nxghryy', subcount[47]) + regexs[48].sub(r'', 'nxghryy', subcount[48]) + regexs[40].sub(r'', strings[85], subcount[40]) + regexs[41].sub(r'', strings[85], subcount[41]) + regexs[42].sub(r'', strings[85], subcount[42]) + regexs[43].sub(r'', strings[85], subcount[43]) + regexs[44].sub(r'', strings[85], subcount[44]) + regexs[45].sub(r'', strings[85], subcount[45]) + regexs[46].sub(r'', strings[85], subcount[46]) + regexs[47].sub(r'', strings[85], subcount[47]) + regexs[48].sub(r'', strings[85], subcount[48]) + regexs[29].sub(r'', 'pngrtbel', subcount[29]) + regexs[30].sub(r'', 'pngrtbel', subcount[30]) + regexs[39].sub(r'', 'pybfr', subcount[39]) + regexs[39].sub(r'', 'qvi', subcount[39]) + regexs[68].sub(r'', strings[86], subcount[68]) + regexs[18].sub(r'', strings[86], subcount[18]) + regexs[39].sub(r'', 'qg', subcount[39]) + regexs[68].sub(r'', 'qg', subcount[68]) + regexs[18].sub(r'', 'qg', subcount[18]) + regexs[39].sub(r'', 'rzorq', subcount[39]) + regexs[68].sub(r'', 'rzorq', subcount[68]) + regexs[18].sub(r'', 'rzorq', subcount[18]) + regexs[39].sub(r'', 'svryqOga', subcount[39]) + regexs[39].sub(r'', 'svryqOgaPnapry', subcount[39]) + regexs[20].split(r'svz_zlfcnpr_nccf-pnainf,svz_zlfcnpr_havgrq-fgngrf') + regexs[40].sub(r'', 'svanamra', subcount[40]) + regexs[41].sub(r'', 'svanamra', subcount[41]) + regexs[42].sub(r'', 'svanamra', subcount[42]) + regexs[43].sub(r'', 'svanamra', subcount[43]) + regexs[44].sub(r'', 'svanamra', subcount[44]) + regexs[45].sub(r'', 'svanamra', subcount[45]) + regexs[46].sub(r'', 'svanamra', subcount[46]) + regexs[47].sub(r'', 'svanamra', subcount[47]) + regexs[48].sub(r'', 'svanamra', subcount[48]) + regexs[70].split(r'sbphf') + regexs[70].split(r'sbphf.gno sbphfva.gno') + regexs[70].split(r'sbphfva') + regexs[39].sub(r'', 'sbez', subcount[39]) + regexs[68].sub(r'', 'sbez.nwnk', subcount[68]) + regexs[18].sub(r'', 'sbez.nwnk', subcount[18]) + regexs[40].sub(r'', 'tnzrf', subcount[40]) + regexs[41].sub(r'', 'tnzrf', subcount[41]) + regexs[42].sub(r'', 'tnzrf', subcount[42]) + regexs[43].sub(r'', 'tnzrf', subcount[43]) + regexs[44].sub(r'', 'tnzrf', subcount[44]) + regexs[45].sub(r'', 'tnzrf', subcount[45]) + regexs[46].sub(r'', 'tnzrf', subcount[46]) + regexs[47].sub(r'', 'tnzrf', subcount[47]) + regexs[48].sub(r'', 'tnzrf', subcount[48]) + regexs[30].sub(r'', 'ubzrcntr', subcount[30]) + regexs[40].sub(r'', 'ubebfxbc', subcount[40]) + regexs[41].sub(r'', 'ubebfxbc', subcount[41]) + regexs[42].sub(r'', 'ubebfxbc', subcount[42]) + regexs[43].sub(r'', 'ubebfxbc', subcount[43]) + regexs[44].sub(r'', 'ubebfxbc', subcount[44]) + regexs[45].sub(r'', 'ubebfxbc', subcount[45]) + regexs[46].sub(r'', 'ubebfxbc', subcount[46]) + regexs[47].sub(r'', 'ubebfxbc', subcount[47]) + regexs[48].sub(r'', 'ubebfxbc', subcount[48]) + regexs[30].sub(r'', 'uc_cebzbobk_ugzy%2Puc_cebzbobk_vzt', subcount[30]) + regexs[30].sub(r'', 'uc_erpgnatyr', subcount[30]) + regexs[33].sub(r'', strings[87], subcount[33]) + regexs[33].sub(r'', strings[88], subcount[33]) + regexs[71].sub( + r'', 'uggc://wf.hv-cbegny.qr/tzk/ubzr/wf/20080602/onfr.wf${4}${5}', subcount[71]) + regexs[72].sub( + r'', 'uggc://wf.hv-cbegny.qr/tzk/ubzr/wf/20080602/onfr.wf${5}', subcount[72]) + regexs[71].sub( + r'', 'uggc://wf.hv-cbegny.qr/tzk/ubzr/wf/20080602/qlaYvo.wf${4}${5}', subcount[71]) + regexs[72].sub( + r'', 'uggc://wf.hv-cbegny.qr/tzk/ubzr/wf/20080602/qlaYvo.wf${5}', subcount[72]) + regexs[71].sub( + r'', 'uggc://wf.hv-cbegny.qr/tzk/ubzr/wf/20080602/rssrpgYvo.wf${4}${5}', subcount[71]) + regexs[72].sub( + r'', 'uggc://wf.hv-cbegny.qr/tzk/ubzr/wf/20080602/rssrpgYvo.wf${5}', subcount[72]) + regexs[73].sub(r'', strings[89], subcount[73]) + regexs[69].sub( + r'', 'uggc://zfacbegny.112.2b7.arg/o/ff/zfacbegnyubzr/1/U.7-cqi-2/f55023338617756?[NDO]&{1}&{2}&[NDR]', subcount[69]) + regexs[23].sub(r'', strings[6], subcount[23]) + regexs[40].sub(r'', 'xvab', subcount[40]) + regexs[41].sub(r'', 'xvab', subcount[41]) + regexs[42].sub(r'', 'xvab', subcount[42]) + regexs[43].sub(r'', 'xvab', subcount[43]) + regexs[44].sub(r'', 'xvab', subcount[44]) + regexs[45].sub(r'', 'xvab', subcount[45]) + regexs[46].sub(r'', 'xvab', subcount[46]) + regexs[47].sub(r'', 'xvab', subcount[47]) + regexs[48].sub(r'', 'xvab', subcount[48]) + regexs[70].split(r'ybnq') + regexs[18].sub( + r'', 'zrqvnzbqgno lhv-anifrg lhv-anifrg-gbc', subcount[18]) + regexs[39].sub(r'', 'zrgn', subcount[39]) + regexs[68].sub(r'', strings[90], subcount[68]) + regexs[18].sub(r'', strings[90], subcount[18]) + regexs[70].split(r'zbhfrzbir') + regexs[70].split(r'zbhfrzbir.gno') + re.sub(r'^.*jroxvg\/(\d+(\.\d+)?).*$', '', strings[63], 1) + regexs[40].sub(r'', 'zhfvx', subcount[40]) + regexs[41].sub(r'', 'zhfvx', subcount[41]) + regexs[42].sub(r'', 'zhfvx', subcount[42]) + regexs[43].sub(r'', 'zhfvx', subcount[43]) + regexs[44].sub(r'', 'zhfvx', subcount[44]) + regexs[45].sub(r'', 'zhfvx', subcount[45]) + regexs[46].sub(r'', 'zhfvx', subcount[46]) + regexs[47].sub(r'', 'zhfvx', subcount[47]) + regexs[48].sub(r'', 'zhfvx', subcount[48]) + regexs[52].sub(r'', 'zlfcnpr_nccf_pnainf', subcount[52]) + regexs[40].sub(r'', strings[91], subcount[40]) + regexs[41].sub(r'', strings[91], subcount[41]) + regexs[42].sub(r'', strings[91], subcount[42]) + regexs[43].sub(r'', strings[91], subcount[43]) + regexs[44].sub(r'', strings[91], subcount[44]) + regexs[45].sub(r'', strings[91], subcount[45]) + regexs[46].sub(r'', strings[91], subcount[46]) + regexs[47].sub(r'', strings[91], subcount[47]) + regexs[48].sub(r'', strings[91], subcount[48]) + regexs[39].sub(r'', 'anzr', subcount[39]) + + # This prints something different to the V8 version + # The V8 version is escaping different things in the string that + # has the substitutions performed on it. + # + # V8 treats /\S/ like / + escaped S + / + # Python treats it like / + \ + S + / + re.sub(r'\b\w+\b', '', strings[92], 0) + + regexs[39].sub(r'', 'bow-nppbeqvba', subcount[39]) + regexs[39].sub(r'', 'bowrpg', subcount[39]) + regexs[68].sub(r'', 'bowrpg', subcount[68]) + regexs[18].sub(r'', 'bowrpg', subcount[18]) + regexs[29].sub(r'', 'cnenzf%2Rfglyrf', subcount[29]) + regexs[30].sub(r'', 'cnenzf%2Rfglyrf', subcount[30]) + regexs[30].sub(r'', 'cbchc', subcount[30]) + regexs[40].sub(r'', 'ebhgr', subcount[40]) + regexs[41].sub(r'', 'ebhgr', subcount[41]) + regexs[42].sub(r'', 'ebhgr', subcount[42]) + regexs[43].sub(r'', 'ebhgr', subcount[43]) + regexs[44].sub(r'', 'ebhgr', subcount[44]) + regexs[45].sub(r'', 'ebhgr', subcount[45]) + regexs[46].sub(r'', 'ebhgr', subcount[46]) + regexs[47].sub(r'', 'ebhgr', subcount[47]) + regexs[48].sub(r'', 'ebhgr', subcount[48]) + regexs[30].sub(r'', 'freivprobk_uc', subcount[30]) + regexs[30].sub(r'', 'fubccvatobk_uc', subcount[30]) + regexs[39].sub(r'', 'fubhgobk', subcount[39]) + regexs[40].sub(r'', 'fcbeg', subcount[40]) + regexs[41].sub(r'', 'fcbeg', subcount[41]) + regexs[42].sub(r'', 'fcbeg', subcount[42]) + regexs[43].sub(r'', 'fcbeg', subcount[43]) + regexs[44].sub(r'', 'fcbeg', subcount[44]) + regexs[45].sub(r'', 'fcbeg', subcount[45]) + regexs[46].sub(r'', 'fcbeg', subcount[46]) + regexs[47].sub(r'', 'fcbeg', subcount[47]) + regexs[48].sub(r'', 'fcbeg', subcount[48]) + regexs[40].sub(r'', 'gbhe', subcount[40]) + regexs[41].sub(r'', 'gbhe', subcount[41]) + regexs[42].sub(r'', 'gbhe', subcount[42]) + regexs[43].sub(r'', 'gbhe', subcount[43]) + regexs[44].sub(r'', 'gbhe', subcount[44]) + regexs[45].sub(r'', 'gbhe', subcount[45]) + regexs[46].sub(r'', 'gbhe', subcount[46]) + regexs[47].sub(r'', 'gbhe', subcount[47]) + regexs[48].sub(r'', 'gbhe', subcount[48]) + regexs[40].sub(r'', 'gi-fcbg', subcount[40]) + regexs[41].sub(r'', 'gi-fcbg', subcount[41]) + regexs[42].sub(r'', 'gi-fcbg', subcount[42]) + regexs[43].sub(r'', 'gi-fcbg', subcount[43]) + regexs[44].sub(r'', 'gi-fcbg', subcount[44]) + regexs[45].sub(r'', 'gi-fcbg', subcount[45]) + regexs[46].sub(r'', 'gi-fcbg', subcount[46]) + regexs[47].sub(r'', 'gi-fcbg', subcount[47]) + regexs[48].sub(r'', 'gi-fcbg', subcount[48]) + regexs[39].sub(r'', 'glcr', subcount[39]) + re.sub(r'\/', '', 'haqrsvarq', 0) + regexs[40].sub(r'', strings[93], subcount[40]) + regexs[41].sub(r'', strings[93], subcount[41]) + regexs[42].sub(r'', strings[93], subcount[42]) + regexs[43].sub(r'', strings[93], subcount[43]) + regexs[44].sub(r'', strings[93], subcount[44]) + regexs[45].sub(r'', strings[93], subcount[45]) + regexs[46].sub(r'', strings[93], subcount[46]) + regexs[47].sub(r'', strings[93], subcount[47]) + regexs[48].sub(r'', strings[93], subcount[48]) + regexs[40].sub(r'', 'ivqrb', subcount[40]) + regexs[41].sub(r'', 'ivqrb', subcount[41]) + regexs[42].sub(r'', 'ivqrb', subcount[42]) + regexs[43].sub(r'', 'ivqrb', subcount[43]) + regexs[44].sub(r'', 'ivqrb', subcount[44]) + regexs[45].sub(r'', 'ivqrb', subcount[45]) + regexs[46].sub(r'', 'ivqrb', subcount[46]) + regexs[47].sub(r'', 'ivqrb', subcount[47]) + regexs[48].sub(r'', 'ivqrb', subcount[48]) + regexs[86].split(r'ivfvgf=1') + regexs[40].sub(r'', 'jrggre', subcount[40]) + regexs[41].sub(r'', 'jrggre', subcount[41]) + regexs[42].sub(r'', 'jrggre', subcount[42]) + regexs[43].sub(r'', 'jrggre', subcount[43]) + regexs[44].sub(r'', 'jrggre', subcount[44]) + regexs[45].sub(r'', 'jrggre', subcount[45]) + regexs[46].sub(r'', 'jrggre', subcount[46]) + regexs[47].sub(r'', 'jrggre', subcount[47]) + regexs[48].sub(r'', 'jrggre', subcount[48]) + re.search(r'#[a-z0-9]+$', + 'uggc://jjj.fpuhryreim.arg/Qrsnhyg', re.IGNORECASE) + regexs[66].search(r'fryrpgrq') + re.search(r'(?:^|\s+)lhv-ani(?:\s+|$)', 'sff lhv-ani') + re.search(r'(?:^|\s+)lhv-anifrg(?:\s+|$)', 'zrqvnzbqgno lhv-anifrg') + re.search(r'(?:^|\s+)lhv-anifrg-gbc(?:\s+|$)', + 'zrqvnzbqgno lhv-anifrg') + regexs[91].search(r'GnoThvq') + regexs[91].search(r'thvq') + re.search(r'(pbzcngvoyr|jroxvg)', strings[63]) + re.search(r'.+(?:ei|vg|en|vr)[\/: ]([\d.]+)', strings[63]) + regexs[8].search(r'144631658.0.10.1231365869') + regexs[8].search(r'144631658.0.10.1231367054') + regexs[8].search( + r'144631658.1231365869.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)') + regexs[8].search( + r'144631658.1231367054.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)') + regexs[8].search( + r'144631658.1670816052019209000.1231365869.1231365869.1231365869.1') + regexs[8].search( + r'144631658.1796080716621419500.1231367054.1231367054.1231367054.1') + regexs[8].search(strings[94]) + regexs[8].search(strings[95]) + regexs[8].search(strings[96]) + regexs[8].search(strings[97]) + regexs[8].search( + r'__hgzn=144631658.1670816052019209000.1231365869.1231365869.1231365869.1') + regexs[8].search( + r'__hgzn=144631658.1796080716621419500.1231367054.1231367054.1231367054.1') + regexs[8].search(r'__hgzo=144631658.0.10.1231365869') + regexs[8].search(r'__hgzo=144631658.0.10.1231367054') + regexs[8].search( + r'__hgzm=144631658.1231365869.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)') + regexs[8].search( + r'__hgzm=144631658.1231367054.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)') + regexs[34].search(strings[78]) + regexs[34].search(strings[79]) + regexs[34].search(strings[81]) + regexs[74].search(strings[77]) + regexs[74].search(r'*') + regexs[74].search(strings[82]) + regexs[74].search(strings[83]) + regexs[74].search(strings[86]) + regexs[74].search(r'rzorq') + regexs[74].search(r'sbez.nwnk') + regexs[74].search(strings[90]) + regexs[74].search(r'bowrpg') + re.search(r'\/onfr.wf(\?.+)?$', + '/uggc://wf.hv-cbegny.qr/tzk/ubzr/wf/20080602/onfr.wf') + regexs[28].search(r'uvag ynfgUvag ynfg') + regexs[75].search(r'') + regexs[76].search(r'') + regexs[77].search(r'') + regexs[78].search(r'') + regexs[80].search(strings[77]) + regexs[80].search(r'*') + regexs[80].search(r'.pybfr') + regexs[80].search(strings[82]) + regexs[80].search(strings[83]) + regexs[80].search(strings[84]) + regexs[80].search(strings[86]) + regexs[80].search(r'qg') + regexs[80].search(r'rzorq') + regexs[80].search(r'sbez.nwnk') + regexs[80].search(strings[90]) + regexs[80].search(r'bowrpg') + regexs[61].search(r'qlaYvo.wf') + regexs[61].search(r'rssrpgYvo.wf') + regexs[61].search(r'uggc://jjj.tzk.arg/qr/?fgnghf=uvajrvf') + regexs[92].search(r' .pybfr') + regexs[92].search(r' n.svryqOgaPnapry') + regexs[92].search(r' qg') + regexs[92].search(strings[48]) + regexs[92].search(r'.nwnk') + regexs[92].search(r'.svryqOga,n.svryqOgaPnapry') + regexs[92].search(r'.svryqOgaPnapry') + regexs[92].search(r'.bow-nppbeqvba qg') + regexs[68].search(strings[77]) + regexs[68].search(r'*') + regexs[68].search(r'.pybfr') + regexs[68].search(strings[82]) + regexs[68].search(strings[83]) + regexs[68].search(strings[84]) + regexs[68].search(strings[86]) + regexs[68].search(r'qg') + regexs[68].search(r'rzorq') + regexs[68].search(r'sbez.nwnk') + regexs[68].search(strings[90]) + regexs[68].search(r'bowrpg') + regexs[93].search(r' .pybfr') + regexs[93].search(r' n.svryqOgaPnapry') + regexs[93].search(r' qg') + regexs[93].search(strings[48]) + regexs[93].search(r'.nwnk') + regexs[93].search(r'.svryqOga,n.svryqOgaPnapry') + regexs[93].search(r'.svryqOgaPnapry') + regexs[93].search(r'.bow-nppbeqvba qg') + regexs[81].search(strings[77]) + regexs[81].search(r'*') + regexs[81].search(strings[48]) + regexs[81].search(r'.pybfr') + regexs[81].search(strings[82]) + regexs[81].search(strings[83]) + regexs[81].search(strings[84]) + regexs[81].search(strings[86]) + regexs[81].search(r'qg') + regexs[81].search(r'rzorq') + regexs[81].search(r'sbez.nwnk') + regexs[81].search(strings[90]) + regexs[81].search(r'bowrpg') + regexs[94].search(r' .pybfr') + regexs[94].search(r' n.svryqOgaPnapry') + regexs[94].search(r' qg') + regexs[94].search(strings[48]) + regexs[94].search(r'.nwnk') + regexs[94].search(r'.svryqOga,n.svryqOgaPnapry') + regexs[94].search(r'.svryqOgaPnapry') + regexs[94].search(r'.bow-nppbeqvba qg') + regexs[94].search(r'[anzr=nwnkHey]') + regexs[94].search(strings[82]) + regexs[31].search(r'rf') + regexs[31].search(r'wn') + regexs[82].search(strings[77]) + regexs[82].search(r'*') + regexs[82].search(strings[48]) + regexs[82].search(r'.pybfr') + regexs[82].search(strings[82]) + regexs[82].search(strings[83]) + regexs[82].search(strings[84]) + regexs[82].search(strings[86]) + regexs[82].search(r'qg') + regexs[82].search(r'rzorq') + regexs[82].search(r'sbez.nwnk') + regexs[82].search(strings[90]) + regexs[82].search(r'bowrpg') + regexs[83].search(strings[98]) + regexs[83].search(r'shapgvba sbphf() { [angvir pbqr] }') + regexs[62].search(r'#Ybtva') + regexs[62].search(r'#Ybtva_cnffjbeq') + regexs[62].search(strings[77]) + regexs[62].search(r'#fubhgobkWf') + regexs[62].search(r'#fubhgobkWfReebe') + regexs[62].search(r'#fubhgobkWfFhpprff') + regexs[62].search(r'*') + regexs[62].search(strings[82]) + regexs[62].search(strings[83]) + regexs[62].search(strings[86]) + regexs[62].search(r'rzorq') + regexs[62].search(r'sbez.nwnk') + regexs[62].search(strings[90]) + regexs[62].search(r'bowrpg') + regexs[49].search(r'pbagrag') + regexs[24].search(strings[6]) + re.search(r'xbadhrebe', strings[63]) + re.search(r'znp', 'jva32') + re.search(r'zbmvyyn', strings[63]) + re.search(r'zfvr', strings[63]) + re.search(r'ag\s5\.1', strings[63]) + re.search(r'bcren', strings[63]) + re.search(r'fnsnev', strings[63]) + re.search(r'jva', 'jva32') + re.search(r'jvaqbjf', strings[63]) + + +def bench_regex_v8(loops): + for loops in range(loops): + block0() + block1() + block2() + block3() + block4() + block5() + block6() + block7() + block8() + block9() + block10() + block11() + + +def run(): + bench_regex_v8(8) + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/scimark.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/scimark.py new file mode 100644 index 0000000000..44a129d1fd --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/scimark.py @@ -0,0 +1,414 @@ +from array import array +import math +import argparse + + +class Array2D(object): + + def __init__(self, w, h, data=None): + self.width = w + self.height = h + self.data = array('d', [0]) * (w * h) + if data is not None: + self.setup(data) + + def _idx(self, x, y): + if 0 <= x < self.width and 0 <= y < self.height: + return y * self.width + x + raise IndexError + + def __getitem__(self, x_y): + (x, y) = x_y + return self.data[self._idx(x, y)] + + def __setitem__(self, x_y, val): + (x, y) = x_y + self.data[self._idx(x, y)] = val + + def setup(self, data): + for y in range(self.height): + for x in range(self.width): + self[x, y] = data[y][x] + return self + + def indexes(self): + for y in range(self.height): + for x in range(self.width): + yield x, y + + def copy_data_from(self, other): + self.data[:] = other.data[:] + + +class Random(object): + MDIG = 32 + ONE = 1 + m1 = (ONE << (MDIG - 2)) + ((ONE << (MDIG - 2)) - ONE) + m2 = ONE << MDIG // 2 + dm1 = 1.0 / float(m1) + + def __init__(self, seed): + self.initialize(seed) + self.left = 0.0 + self.right = 1.0 + self.width = 1.0 + self.haveRange = False + + def initialize(self, seed): + + self.seed = seed + seed = abs(seed) + jseed = min(seed, self.m1) + if (jseed % 2 == 0): + jseed -= 1 + k0 = 9069 % self.m2 + k1 = 9069 / self.m2 + j0 = jseed % self.m2 + j1 = jseed / self.m2 + self.m = array('d', [0]) * 17 + for iloop in range(17): + jseed = j0 * k0 + j1 = (jseed / self.m2 + j0 * k1 + j1 * k0) % (self.m2 / 2) + j0 = jseed % self.m2 + self.m[iloop] = j0 + self.m2 * j1 + self.i = 4 + self.j = 16 + + def nextDouble(self): + I, J, m = self.i, self.j, self.m + k = m[I] - m[J] + if (k < 0): + k += self.m1 + self.m[J] = k + + if (I == 0): + I = 16 + else: + I -= 1 + self.i = I + + if (J == 0): + J = 16 + else: + J -= 1 + self.j = J + + if (self.haveRange): + return self.left + self.dm1 * float(k) * self.width + else: + return self.dm1 * float(k) + + def RandomMatrix(self, a): + for x, y in a.indexes(): + a[x, y] = self.nextDouble() + return a + + def RandomVector(self, n): + return array('d', [self.nextDouble() for i in range(n)]) + + +def copy_vector(vec): + # Copy a vector created by Random.RandomVector() + vec2 = array('d') + vec2[:] = vec[:] + return vec2 + + +class ArrayList(Array2D): + + def __init__(self, w, h, data=None): + self.width = w + self.height = h + self.data = [array('d', [0]) * w for y in range(h)] + if data is not None: + self.setup(data) + + def __getitem__(self, idx): + if isinstance(idx, tuple): + return self.data[idx[1]][idx[0]] + else: + return self.data[idx] + + def __setitem__(self, idx, val): + if isinstance(idx, tuple): + self.data[idx[1]][idx[0]] = val + else: + self.data[idx] = val + + def copy_data_from(self, other): + for l1, l2 in zip(self.data, other.data): + l1[:] = l2 + + +def SOR_execute(omega, G, cycles, Array): + for p in range(cycles): + for y in range(1, G.height - 1): + for x in range(1, G.width - 1): + G[x, y] = (omega * 0.25 * (G[x, y - 1] + G[x, y + 1] + G[x - 1, y] + + G[x + 1, y]) + + (1.0 - omega) * G[x, y]) + + +def bench_SOR(loops, n, cycles, Array): + range_it = range(loops) + + for _ in range_it: + G = Array(n, n) + SOR_execute(1.25, G, cycles, Array) + + +def SparseCompRow_matmult(M, y, val, row, col, x, num_iterations): + range_it = range(num_iterations) + + for _ in range_it: + for r in range(M): + sa = 0.0 + for i in range(row[r], row[r + 1]): + sa += x[col[i]] * val[i] + y[r] = sa + + +def bench_SparseMatMult(cycles, N, nz): + x = array('d', [0]) * N + y = array('d', [0]) * N + + nr = nz // N + anz = nr * N + val = array('d', [0]) * anz + col = array('i', [0]) * nz + row = array('i', [0]) * (N + 1) + + row[0] = 0 + for r in range(N): + rowr = row[r] + step = r // nr + row[r + 1] = rowr + nr + if step < 1: + step = 1 + for i in range(nr): + col[rowr + i] = i * step + + return SparseCompRow_matmult(N, y, val, row, col, x, cycles) + + +def MonteCarlo(Num_samples): + rnd = Random(113) + under_curve = 0 + for count in range(Num_samples): + x = rnd.nextDouble() + y = rnd.nextDouble() + if x * x + y * y <= 1.0: + under_curve += 1 + return float(under_curve) / Num_samples * 4.0 + + +def bench_MonteCarlo(loops, Num_samples): + range_it = range(loops) + + for _ in range_it: + MonteCarlo(Num_samples) + + +def LU_factor(A, pivot): + M, N = A.height, A.width + minMN = min(M, N) + for j in range(minMN): + jp = j + t = abs(A[j][j]) + for i in range(j + 1, M): + ab = abs(A[i][j]) + if ab > t: + jp = i + t = ab + pivot[j] = jp + + if A[jp][j] == 0: + raise Exception("factorization failed because of zero pivot") + + if jp != j: + A[j], A[jp] = A[jp], A[j] + + if j < M - 1: + recp = 1.0 / A[j][j] + for k in range(j + 1, M): + A[k][j] *= recp + + if j < minMN - 1: + for ii in range(j + 1, M): + for jj in range(j + 1, N): + A[ii][jj] -= A[ii][j] * A[j][jj] + + +def LU(lu, A, pivot): + lu.copy_data_from(A) + LU_factor(lu, pivot) + + +def bench_LU(cycles, N): + rnd = Random(7) + A = rnd.RandomMatrix(ArrayList(N, N)) + lu = ArrayList(N, N) + pivot = array('i', [0]) * N + range_it = range(cycles) + + for _ in range_it: + LU(lu, A, pivot) + + +def int_log2(n): + k = 1 + log = 0 + while k < n: + k *= 2 + log += 1 + if n != 1 << log: + raise Exception("FFT: Data length is not a power of 2: %s" % n) + return log + + +def FFT_num_flops(N): + return (5.0 * N - 2) * int_log2(N) + 2 * (N + 1) + + +def FFT_transform_internal(N, data, direction): + n = N // 2 + bit = 0 + dual = 1 + if n == 1: + return + + logn = int_log2(n) + if N == 0: + return + FFT_bitreverse(N, data) + + # apply fft recursion + # this loop executed int_log2(N) times + bit = 0 + while bit < logn: + w_real = 1.0 + w_imag = 0.0 + theta = 2.0 * direction * math.pi / (2.0 * float(dual)) + s = math.sin(theta) + t = math.sin(theta / 2.0) + s2 = 2.0 * t * t + for b in range(0, n, 2 * dual): + i = 2 * b + j = 2 * (b + dual) + wd_real = data[j] + wd_imag = data[j + 1] + data[j] = data[i] - wd_real + data[j + 1] = data[i + 1] - wd_imag + data[i] += wd_real + data[i + 1] += wd_imag + for a in range(1, dual): + tmp_real = w_real - s * w_imag - s2 * w_real + tmp_imag = w_imag + s * w_real - s2 * w_imag + w_real = tmp_real + w_imag = tmp_imag + for b in range(0, n, 2 * dual): + i = 2 * (b + a) + j = 2 * (b + a + dual) + z1_real = data[j] + z1_imag = data[j + 1] + wd_real = w_real * z1_real - w_imag * z1_imag + wd_imag = w_real * z1_imag + w_imag * z1_real + data[j] = data[i] - wd_real + data[j + 1] = data[i + 1] - wd_imag + data[i] += wd_real + data[i + 1] += wd_imag + bit += 1 + dual *= 2 + + +def FFT_bitreverse(N, data): + n = N // 2 + nm1 = n - 1 + j = 0 + for i in range(nm1): + ii = i << 1 + jj = j << 1 + k = n >> 1 + if i < j: + tmp_real = data[ii] + tmp_imag = data[ii + 1] + data[ii] = data[jj] + data[ii + 1] = data[jj + 1] + data[jj] = tmp_real + data[jj + 1] = tmp_imag + while k <= j: + j -= k + k >>= 1 + j += k + + +def FFT_transform(N, data): + FFT_transform_internal(N, data, -1) + + +def FFT_inverse(N, data): + n = N / 2 + norm = 0.0 + FFT_transform_internal(N, data, +1) + norm = 1 / float(n) + for i in range(N): + data[i] *= norm + + +def bench_FFT(loops, N, cycles): + twoN = 2 * N + init_vec = Random(7).RandomVector(twoN) + range_it = range(loops) + + for _ in range_it: + x = copy_vector(init_vec) + for i in range(cycles): + FFT_transform(twoN, x) + FFT_inverse(twoN, x) + + +def add_cmdline_args(cmd, args): + if args.benchmark: + cmd.append(args.benchmark) + + +BENCHMARKS = { + # function name => arguments + 'sor': (bench_SOR, 1, 100, 1, Array2D), + 'sparse_mat_mult': (bench_SparseMatMult, 4, 1000, 50 * 1000), + 'monte_carlo': (bench_MonteCarlo, 2, 10 * 1000,), + 'lu': (bench_LU, 1, 50,), + 'fft': (bench_FFT, 1, 1024, 5), +} + + +def run(): + parser = argparse.ArgumentParser(prog="python") + parser.add_argument("benchmark", nargs='?', + choices=sorted(BENCHMARKS)) + + args = parser.parse_args() + if args.benchmark: + benchmarks = (args.benchmark,) + else: + benchmarks = sorted(BENCHMARKS) + + for bench in benchmarks: + func, *func_args = BENCHMARKS[bench] + func(*func_args) + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/spectral_norm.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/spectral_norm.py new file mode 100644 index 0000000000..63cad9f280 --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/spectral_norm.py @@ -0,0 +1,81 @@ +""" +MathWorld: "Hundred-Dollar, Hundred-Digit Challenge Problems", Challenge #3. +http://mathworld.wolfram.com/Hundred-DollarHundred-DigitChallengeProblems.html + +The Computer Language Benchmarks Game +http://benchmarksgame.alioth.debian.org/u64q/spectralnorm-description.html#spectralnorm + +Contributed by Sebastien Loisel +Fixed by Isaac Gouy +Sped up by Josh Goldfoot +Dirtily sped up by Simon Descarpentries +Concurrency by Jason Stitt +""" + + +DEFAULT_N = 130 + + +def eval_A(i, j): + return 1.0 / ((i + j) * (i + j + 1) // 2 + i + 1) + + +def eval_times_u(func, u): + return [func((i, u)) for i in range(len(list(u)))] + + +def eval_AtA_times_u(u): + return eval_times_u(part_At_times_u, eval_times_u(part_A_times_u, u)) + + +def part_A_times_u(i_u): + i, u = i_u + partial_sum = 0 + for j, u_j in enumerate(u): + partial_sum += eval_A(i, j) * u_j + return partial_sum + + +def part_At_times_u(i_u): + i, u = i_u + partial_sum = 0 + for j, u_j in enumerate(u): + partial_sum += eval_A(j, i) * u_j + return partial_sum + + +def bench_spectral_norm(loops): + range_it = range(loops) + + for _ in range_it: + u = [1] * DEFAULT_N + + for dummy in range(10): + v = eval_AtA_times_u(u) + u = eval_AtA_times_u(v) + + vBv = vv = 0 + + for ue, ve in zip(u, v): + vBv += ue * ve + vv += ve * ve + + +def run(): + bench_spectral_norm(1) + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/telco.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/telco.py new file mode 100644 index 0000000000..fefc0a81ae --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/telco.py @@ -0,0 +1,101 @@ +# coding: UTF-8 +""" Telco Benchmark for measuring the performance of decimal calculations + +- http://speleotrove.com/decimal/telco.html +- http://speleotrove.com/decimal/telcoSpec.html + +A call type indicator, c, is set from the bottom (least significant) bit of the duration (hence c is 0 or 1). +A rate, r, is determined from the call type. Those calls with c=0 have a low r: 0.0013; the remainder (‘distance calls’) have a ‘premium’ r: 0.00894. (The rates are, very roughly, in Euros or dollarates per second.) +A price, p, for the call is then calculated (p=r*n). This is rounded to exactly 2 fractional digits using round-half-even (Banker’s round to nearest). +A basic tax, b, is calculated: b=p*0.0675 (6.75%). This is truncated to exactly 2 fractional digits (round-down), and the total basic tax variable is then incremented (sumB=sumB+b). +For distance calls: a distance tax, d, is calculated: d=p*0.0341 (3.41%). This is truncated to exactly 2 fractional digits (round-down), and then the total distance tax variable is incremented (sumD=sumD+d). +The total price, t, is calculated (t=p+b, and, if a distance call, t=t+d). +The total prices variable is incremented (sumT=sumT+t). +The total price, t, is converted to a string, s. + +""" + +from decimal import ROUND_HALF_EVEN, ROUND_DOWN, Decimal, getcontext, Context +import io +import os +from struct import unpack + + +def rel_path(*path): + return os.path.join(os.path.dirname(__file__), *path) + + +def bench_telco(loops, filename): + getcontext().rounding = ROUND_DOWN + rates = list(map(Decimal, ('0.0013', '0.00894'))) + twodig = Decimal('0.01') + Banker = Context(rounding=ROUND_HALF_EVEN) + basictax = Decimal("0.0675") + disttax = Decimal("0.0341") + + with open(filename, "rb") as infil: + data = infil.read() + + infil = io.BytesIO(data) + outfil = io.StringIO() + + for _ in range(loops): + infil.seek(0) + + sumT = Decimal("0") # sum of total prices + sumB = Decimal("0") # sum of basic tax + sumD = Decimal("0") # sum of 'distance' tax + + for i in range(5000): + datum = infil.read(8) + if datum == '': + break + n, = unpack('>Q', datum) + + calltype = n & 1 + r = rates[calltype] + + p = Banker.quantize(r * n, twodig) + + b = p * basictax + b = b.quantize(twodig) + sumB += b + + t = p + b + + if calltype: + d = p * disttax + d = d.quantize(twodig) + sumD += d + t += d + + sumT += t + print(t, file=outfil) + + outfil.seek(0) + outfil.truncate() + + +def run(): + filename = rel_path("data", "telco-bench.b") + bench_telco(1, filename) + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + return ["data/telco-bench.b"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/unpack_sequence.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/unpack_sequence.py new file mode 100644 index 0000000000..eae9d95223 --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/unpack_sequence.py @@ -0,0 +1,466 @@ +"""Microbenchmark for Python's sequence unpacking.""" + +import argparse + + +def do_unpacking(loops, to_unpack): + range_it = range(loops) + + for _ in range_it: + # 400 unpackings + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + a, b, c, d, e, f, g, h, i, j = to_unpack + + +def bench_tuple_unpacking(loops): + x = tuple(range(10)) + do_unpacking(loops, x) + + +def bench_list_unpacking(loops): + x = list(range(10)) + + do_unpacking(loops, x) + + +def bench_all(loops): + bench_tuple_unpacking(loops) + bench_list_unpacking(loops) + + +def add_cmdline_args(cmd, args): + if args.benchmark: + cmd.append(args.benchmark) + + +def run(): + benchmarks = {"tuple": bench_tuple_unpacking, + "list": bench_list_unpacking} + + parser = argparse.ArgumentParser(prog="python") + parser.add_argument("benchmark", nargs="?", + choices=sorted(benchmarks)) + + options = parser.parse_args() + name = 'unpack_sequence' + if options.benchmark: + func = benchmarks[options.benchmark] + name += "_%s" % options.benchmark + else: + func = bench_all + + func(8192) + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/unpickle.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/unpickle.py new file mode 100644 index 0000000000..18bc21a969 --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/unpickle.py @@ -0,0 +1,28 @@ +import sys +import os +# Add benchmark directory to path to allow import of bm_pickle.py +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +import bm_pickle + +def run(): + bm_pickle.__benchmark__(["unpickle"]) + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + return ["bm_pickle.py"] diff --git a/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/unpickle_list.py b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/unpickle_list.py new file mode 100644 index 0000000000..c155a5282c --- /dev/null +++ b/graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/unpickle_list.py @@ -0,0 +1,28 @@ +import sys +import os +# Add benchmark directory to path to allow import of bm_pickle.py +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +import bm_pickle + +def run(): + bm_pickle.__benchmark__(["unpickle_list"]) + + +def warmupIterations(): + return 0 + + +def iterations(): + return 10 + + +def summary(): + return { + "name": "OutlierRemovalAverageSummary", + "lower-threshold": 0.0, + "upper-threshold": 1.0, + } + + +def dependencies(): + return ["bm_pickle.py"] diff --git a/mx.graalpython/mx_graalpython.py b/mx.graalpython/mx_graalpython.py index 95df723378..77e9a184f2 100644 --- a/mx.graalpython/mx_graalpython.py +++ b/mx.graalpython/mx_graalpython.py @@ -2087,6 +2087,9 @@ def python_checkcopyrights(args): "/hpy/", "com.oracle.graal.python.test.integration/src/org.graalvm.python.vfs/", "com.oracle.graal.python.test.integration/src/GRAALPY-VFS/", + "com.oracle.graal.python.benchmarks/python/micro/pyperformance/", + "com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.py", + "com.oracle.graal.python.benchmarks/python/micro/numpy/common.py", ]): pass elif os.path.splitext(line)[1] in [".py", ".java", ".c", ".h", ".sh"]: diff --git a/mx.graalpython/mx_graalpython_benchmark.py b/mx.graalpython/mx_graalpython_benchmark.py index f0e8089e91..9c1b412c8f 100644 --- a/mx.graalpython/mx_graalpython_benchmark.py +++ b/mx.graalpython/mx_graalpython_benchmark.py @@ -1,4 +1,4 @@ -# Copyright (c) 2018, 2025, Oracle and/or its affiliates. +# Copyright (c) 2018, 2026, Oracle and/or its affiliates. # Copyright (c) 2013, Regents of the University of California # # All rights reserved. @@ -1145,10 +1145,10 @@ def graalpython_polybench_runner(polybench_run: mx_polybench.PolybenchRunFunctio mx_polybench.register_polybench_benchmark_suite(mx_suite=SUITE, name="python", languages=["python"], benchmark_distribution="GRAALPYTHON_POLYBENCH_BENCHMARKS", - # Match all python files, except for: - # * harness.py - # * tests/__init__.py - # These two are necessary for running the C-extension-module benchmarks, - # but are not benchmarks themselves. - benchmark_file_filter=r"^(?!.*(harness\.py|tests/__init__\.py)$).*\.py$", + # There are python files that are necessary for running some benchmarks, + # but are not benchmarks themselves. For this reason, we exclude them: + # * harness.py (C-extension-module) + # * tests/__init__.py (C-extension-module) + # * interpreter/bench_core.py (numpy) + benchmark_file_filter=r"^(?!.*(harness\.py|tests/__init__\.py|interpreter/bench_core\.py)$).*\.py$", runner=graalpython_polybench_runner, tags={"gate", "benchmark", "instructions"}) diff --git a/mx.graalpython/polybench-stable-run-config.json b/mx.graalpython/polybench-stable-run-config.json index 4b8f5e856b..3341e29995 100644 --- a/mx.graalpython/polybench-stable-run-config.json +++ b/mx.graalpython/polybench-stable-run-config.json @@ -301,5 +301,430 @@ "policy": "outlier-elimination-all-builds", "forks": "3x3", "focus": "0.0-0.3" + }, + "interpreter/bm_pathlib.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "interpreter/bm_pickle.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "interpreter/bm_richards.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "interpreter/chaos.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "interpreter/fannkuch.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "interpreter/float.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "interpreter/go.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "interpreter/hexiom.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "interpreter/json_dumps.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "interpreter/json_loads.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "interpreter/meteor_contest.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "interpreter/nbody.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "interpreter/nqueens.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "interpreter/pickle_dict.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "interpreter/pickle_list.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "interpreter/pickle_pure_python.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "interpreter/pidigits.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "interpreter/pyflate.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "interpreter/regex_compile.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "interpreter/regex_dna.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "interpreter/regex_effbot.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "interpreter/regex_v8.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "interpreter/scimark.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "interpreter/spectral_norm.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "interpreter/telco.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "interpreter/unpack_sequence.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "interpreter/unpickle_list.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "interpreter/unpickle.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.Core.time_array_1.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.Core.time_array_empty.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.Core.time_arange_100.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.Core.time_array_float64_l1000.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.Core.time_array_float_l1000.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.Core.time_array_float_l1000_dtype.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.Core.time_array_int_l1000.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.Core.time_array_l.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.Core.time_array_l1.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.Core.time_array_l100.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.Core.time_array_l_view.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.Core.time_can_cast.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.Core.time_can_cast_same_kind.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.Core.time_diag_l100.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.Core.time_diagflat_l100.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.Core.time_diagflat_l50_l50.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.Core.time_dstack_l.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.Core.time_empty_100.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.Core.time_empty_like.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.Core.time_eye_100.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.Core.time_eye_3000.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.Core.time_hstack_l.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.Core.time_identity_100.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.Core.time_identity_3000.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.Core.time_ones_100.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.Core.time_tril_indices_500.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.Core.time_tril_l10x10.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.Core.time_triu_indices_500.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.Core.time_triu_l10x10.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.Core.time_vstack_l.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.Core.time_zeros_100.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.CorrConv.time_convolve.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.CorrConv.time_correlate.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.CountNonzero.time_count_nonzero.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.CountNonzero.time_count_nonzero_axis.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.CountNonzero.time_count_nonzero_multi_axis.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.Indices.time_indices.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.PackBits.time_packbits.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.PackBits.time_packbits_axis0.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.PackBits.time_packbits_axis1.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.PackBits.time_packbits_little.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.StatsMethods.time_max.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.StatsMethods.time_mean.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.StatsMethods.time_min.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.StatsMethods.time_prod.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.StatsMethods.time_std.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.StatsMethods.time_sum.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.StatsMethods.time_var.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.Temporaries.time_large.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.Temporaries.time_large2.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.Temporaries.time_mid.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.Temporaries.time_mid2.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.UnpackBits.time_unpackbits.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.UnpackBits.time_unpackbits_axis0.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.UnpackBits.time_unpackbits_axis1.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.UnpackBits.time_unpackbits_axis1_little.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" + }, + "numpy/bench_core.UnpackBits.time_unpackbits_little.py": { + "policy": "outlier-elimination-all-builds", + "forks": "1x1", + "focus": "0.0-1.0" } } diff --git a/mx.graalpython/suite.py b/mx.graalpython/suite.py index 4969452b67..69af31b25b 100644 --- a/mx.graalpython/suite.py +++ b/mx.graalpython/suite.py @@ -1538,6 +1538,94 @@ "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/c-magic-bool.py", "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/c-magic-iter.py", "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/c-member-access.py", + # Batch 4 (pyperformance) + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/bm_pathlib.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/bm_pickle.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/bm_richards.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/chaos.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/fannkuch.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/float.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/go.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/hexiom.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/json_dumps.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/json_loads.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/meteor_contest.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/nbody.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/nqueens.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/pickle_dict.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/pickle_list.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/pidigits.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/pyflate.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/regex_compile.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/regex_dna.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/regex_effbot.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/regex_v8.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/scimark.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/spectral_norm.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/telco.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/unpack_sequence.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/unpickle_list.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/unpickle.py", + ], + "./numpy/": [ + # Batch 5 (numpy) + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_array_1.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_array_empty.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_arange_100.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_array_float64_l1000.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_array_float_l1000.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_array_float_l1000_dtype.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_array_int_l1000.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_array_l.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_array_l1.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_array_l100.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_array_l_view.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_can_cast.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_can_cast_same_kind.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_diag_l100.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_diagflat_l100.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_diagflat_l50_l50.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_dstack_l.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_empty_100.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_empty_like.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_eye_100.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_eye_3000.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_hstack_l.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_identity_100.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_identity_3000.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_ones_100.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_tril_indices_500.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_tril_l10x10.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_triu_indices_500.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_triu_l10x10.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_vstack_l.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Core.time_zeros_100.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.CorrConv.time_convolve.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.CorrConv.time_correlate.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.CountNonzero.time_count_nonzero.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.CountNonzero.time_count_nonzero_axis.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.CountNonzero.time_count_nonzero_multi_axis.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Indices.time_indices.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.PackBits.time_packbits.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.PackBits.time_packbits_axis0.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.PackBits.time_packbits_axis1.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.PackBits.time_packbits_little.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.StatsMethods.time_max.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.StatsMethods.time_mean.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.StatsMethods.time_min.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.StatsMethods.time_prod.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.StatsMethods.time_std.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.StatsMethods.time_sum.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.StatsMethods.time_var.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Temporaries.time_large.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Temporaries.time_large2.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Temporaries.time_mid.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.Temporaries.time_mid2.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.UnpackBits.time_unpackbits.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.UnpackBits.time_unpackbits_axis0.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.UnpackBits.time_unpackbits_axis1.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.UnpackBits.time_unpackbits_axis1_little.py", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.UnpackBits.time_unpackbits_little.py", ], # Interpreter supporting infra "./interpreter/harness.py": [ @@ -1546,6 +1634,16 @@ "./interpreter/tests/": [ "file:graalpython/com.oracle.graal.python.test/src/tests/__init__.py", ], + "./interpreter/data/": [ + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/data/interpreter.tar.bz2", + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/pyperformance/data/telco-bench.b", + ], + "./numpy/bench_core.py": [ + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/bench_core.py", + ], + "./numpy/common.py": [ + "file:graalpython/com.oracle.graal.python.benchmarks/python/micro/numpy/common.py", + ], # Warmup benchmarks "./warmup/": [ "file:benchmarks/warmup/*.py",