Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 109 additions & 0 deletions .github/workflows/codspeed.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
name: codspeed

# Continuous performance benchmarks via CodSpeed (https://codspeed.io).
# Runs the framework's micro scenarios (M1-M7) and four representative
# macro scenarios (X1-1, X2-10k, X4, X6) on CodSpeed's bare-metal Macro
# Runners. The Macro Runners give <1 % variance walltime measurements —
# substantially more stable than shared GitHub Actions runners, which is
# what makes per-PR perf-regression gating meaningful here.
#
# Free for OSS up to 600 macro-runner minutes/month; one run of the
# benchmark set takes roughly 5-6 minutes.
#
# Triggers:
# - push to master: track per-commit perf trend on the dashboard
# - pull_request with the `perf-check` label: opt-in per-PR
# CodSpeed comments. Maintainers apply the label on PRs whose perf
# impact is uncertain; routine PRs don't burn macro-runner budget.
# - workflow_dispatch: manual trigger, available always
#
# Path filter limits triggers to commits that could plausibly affect
# performance (py4j Python sources, py4j-java sources, the test
# requirements file, and this workflow itself). Doc-only commits
# don't burn macro-runner budget.
#
# Prerequisite (not in this PR): install the CodSpeed GitHub App on the
# py4j organization:
# https://github.com/apps/codspeed
# Until installed, this workflow runs the benchmarks but cannot post
# results to the dashboard (and ``codspeed-macro`` won't resolve to a
# runner). Maintainer action; one-time setup.

on:
push:
branches:
- master
paths:
- 'py4j-python/src/py4j/**/*.py'
- 'py4j-java/src/main/**'
- 'py4j-python/requirements-test.txt'
- '.github/workflows/codspeed.yml'
pull_request:
types: [labeled, synchronize]
branches:
- master
paths:
- 'py4j-python/src/py4j/**/*.py'
- 'py4j-java/src/main/**'
- 'py4j-python/requirements-test.txt'
- '.github/workflows/codspeed.yml'
workflow_dispatch:

jobs:
codspeed:
name: CodSpeed walltime benchmarks
# Opt-in per-PR runs gated on the ``perf-check`` label:
# - ``labeled`` events fire only for the perf-check label
# - ``synchronize`` events (new commits on a PR) only fire if the
# PR already carries the label
# ``push`` and ``workflow_dispatch`` always run.
if: >
github.event_name != 'pull_request' ||
(github.event.action == 'labeled' && github.event.label.name == 'perf-check') ||
(github.event.action == 'synchronize' && contains(github.event.pull_request.labels.*.name, 'perf-check'))
runs-on: codspeed-macro
timeout-minutes: 30
steps:
- uses: actions/checkout@v6

- name: Setup Java 8 JDK for py4j-java build
# py4j-java targets source/target 1.6 so it has to compile with
# Java 8 specifically — newer JDKs reject Source option 6.
uses: actions/setup-java@v5
with:
java-version: '8'
distribution: 'zulu'
cache: 'gradle'

- name: Setup Python 3.13
uses: actions/setup-python@v6
with:
python-version: '3.13'

- name: Install py4j + perf deps
run: |
cd py4j-python
pip install -e .
pip install -r requirements-test.txt

- name: Build py4j-java classes
run: |
cd py4j-java
./gradlew classes testClasses

- name: Setup Java 17 JDK for the perf-framework runtime
uses: actions/setup-java@v5
with:
java-version: '17'
distribution: 'zulu'

- name: Run CodSpeed benchmarks (micro + macro)
uses: CodSpeedHQ/action@v3
with:
token: ${{ secrets.CODSPEED_TOKEN }}
run: |
cd py4j-python
pytest \
src/py4j/tests/perf/scenarios/micro.py \
src/py4j/tests/perf/scenarios/codspeed_macros.py \
--codspeed
11 changes: 6 additions & 5 deletions .github/workflows/perf-framework.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,24 @@ on:
branches:
- master
paths:
# Include perf-framework code, excluding doc-only changes within it
# (GitHub Actions rejects `paths` + `paths-ignore` together in the
# same trigger; the `!` negation prefix inside a single `paths:` list
# is the supported way to combine include + exclude).
- 'py4j-python/src/py4j/tests/perf/**'
- '!py4j-python/src/py4j/tests/perf/**/*.md'
- 'py4j-python/src/py4j/tests/test_perf_framework.py'
- 'py4j-python/requirements-test.txt'
- '.github/workflows/perf-framework.yml'
paths-ignore:
# Doc-only changes never affect framework behavior; skip the run.
- '**/*.md'
pull_request:
branches:
- master
paths:
- 'py4j-python/src/py4j/tests/perf/**'
- '!py4j-python/src/py4j/tests/perf/**/*.md'
- 'py4j-python/src/py4j/tests/test_perf_framework.py'
- 'py4j-python/requirements-test.txt'
- '.github/workflows/perf-framework.yml'
paths-ignore:
- '**/*.md'
# Manual trigger from the Actions UI — useful when you want to
# re-run perf coverage after merging upstream master or to test the
# workflow itself.
Expand Down
2 changes: 1 addition & 1 deletion py4j-python/.pydevproject
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
<path>/py4j-python/src</path>
</pydev_pathproperty>
<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.6</pydev_property>
<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 3.9</pydev_property>
<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
</pydev_project>
2 changes: 0 additions & 2 deletions py4j-python/nose.cfg

This file was deleted.

1 change: 1 addition & 0 deletions py4j-python/requirements-test.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ flake8>=4.0.1
tox>=2.1.1
pytest>=7.1.1
pytest-benchmark>=4.0.0
pytest-codspeed>=3.0.0
psutil>=5.9.0
5 changes: 0 additions & 5 deletions py4j-python/setup.cfg

This file was deleted.

12 changes: 5 additions & 7 deletions py4j-python/setup.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
try:
from setuptools import setup
except ImportError:
from distutils.core import setup
from setuptools import setup
import os

DOC_DIR = "doc"
DIST_DIR = "dist"
VERSION_PATH = os.path.join("src", "py4j", "version.py")
# For Python 3 compatibility, we can't use execfile; this is 2to3's conversion:
exec(compile(open(VERSION_PATH).read(),
VERSION_PATH, "exec"))
VERSION = __version__ # noqa
Expand Down Expand Up @@ -37,18 +33,20 @@
author="Barthelemy Dagenais",
author_email="barthelemy@infobart.com",
license="BSD License",
python_requires=">=3.9",
classifiers=[
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"License :: OSI Approved :: BSD License",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 2",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Java",
"Topic :: Software Development :: Libraries",
"Topic :: Software Development :: Object Brokering",
Expand Down
1 change: 0 additions & 1 deletion py4j-python/src/py4j/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
# Py4J Package
from __future__ import absolute_import
from . import version

__version__ = version.__version__
4 changes: 0 additions & 4 deletions py4j-python/src/py4j/clientserver.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
# -*- coding: UTF-8 -*-
"""Module that implements a different threading model between
a Java Virtual Machine a Python interpreter.

In this model, Java and Python can exchange resquests and responses in the same
thread. For example, if a request is started in a Java UI thread and the Python
code calls some Java code, the Java code will be executed in the UI thread.
"""

from __future__ import unicode_literals, absolute_import

from collections import deque
import logging
import socket
Expand Down
Loading