mirror of
https://github.com/msgpack/msgpack-python.git
synced 2025-11-11 06:51:04 +00:00
Add no-GIL interpreter support
Add `pytest-run-parallel` as dependency, test no-GIL interpreters in CI, and mark Cython module as safe for freethreaded interpreters.
This commit is contained in:
parent
42f056f3cf
commit
6ced817616
7 changed files with 59 additions and 7 deletions
6
.github/workflows/test.yml
vendored
6
.github/workflows/test.yml
vendored
|
|
@ -10,7 +10,7 @@ jobs:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: ["ubuntu-latest", "windows-latest", "macos-latest"]
|
os: ["ubuntu-latest", "windows-latest", "macos-latest"]
|
||||||
py: ["3.14-dev", "3.13", "3.12", "3.11", "3.10", "3.9", "3.8"]
|
py: ["3.14", "3.14t", "3.13", "3.13t", "3.12", "3.11", "3.10", "3.9", "3.8"]
|
||||||
|
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
name: Run test with Python ${{ matrix.py }} on ${{ matrix.os }}
|
name: Run test with Python ${{ matrix.py }} on ${{ matrix.os }}
|
||||||
|
|
@ -41,12 +41,12 @@ jobs:
|
||||||
- name: Test (C extension)
|
- name: Test (C extension)
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
pytest -v test
|
PYTHON_GIL=0 pytest -v test
|
||||||
|
|
||||||
- name: Test (pure Python fallback)
|
- name: Test (pure Python fallback)
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
MSGPACK_PUREPYTHON=1 pytest -v test
|
PYTHON_GIL=0 MSGPACK_PUREPYTHON=1 pytest -v test
|
||||||
|
|
||||||
- name: build packages
|
- name: build packages
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
|
||||||
3
.github/workflows/wheel.yml
vendored
3
.github/workflows/wheel.yml
vendored
|
|
@ -32,8 +32,9 @@ jobs:
|
||||||
uses: pypa/cibuildwheel@v2.23.3
|
uses: pypa/cibuildwheel@v2.23.3
|
||||||
env:
|
env:
|
||||||
CIBW_TEST_REQUIRES: "pytest"
|
CIBW_TEST_REQUIRES: "pytest"
|
||||||
CIBW_TEST_COMMAND: "pytest {package}/test"
|
CIBW_TEST_COMMAND: "PYTHON_GIL=0 pytest {package}/test"
|
||||||
CIBW_SKIP: "pp* cp38-macosx_*"
|
CIBW_SKIP: "pp* cp38-macosx_*"
|
||||||
|
CIBW_ENABLE: cpython-freerelease
|
||||||
|
|
||||||
- name: Build sdist
|
- name: Build sdist
|
||||||
if: runner.os == 'Linux' && runner.arch == 'X64'
|
if: runner.os == 'Linux' && runner.arch == 'X64'
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
# coding: utf-8
|
# coding: utf-8
|
||||||
#cython: embedsignature=True, c_string_encoding=ascii, language_level=3
|
#cython: embedsignature=True, c_string_encoding=ascii, language_level=3, freethreading_compatible=True
|
||||||
from cpython.datetime cimport import_datetime, datetime_new
|
from cpython.datetime cimport import_datetime, datetime_new
|
||||||
import_datetime()
|
import_datetime()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
# coding: utf-8
|
# coding: utf-8
|
||||||
|
# cython: freethreading_compatible = True
|
||||||
from cpython cimport *
|
from cpython cimport *
|
||||||
from cpython.bytearray cimport PyByteArray_Check, PyByteArray_CheckExact
|
from cpython.bytearray cimport PyByteArray_Check, PyByteArray_CheckExact
|
||||||
from cpython.datetime cimport (
|
from cpython.datetime cimport (
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
# coding: utf-8
|
# coding: utf-8
|
||||||
|
# cython: freethreading_compatible = True
|
||||||
from cpython cimport *
|
from cpython cimport *
|
||||||
cdef extern from "Python.h":
|
cdef extern from "Python.h":
|
||||||
ctypedef struct PyObject
|
ctypedef struct PyObject
|
||||||
|
|
|
||||||
|
|
@ -1 +1,2 @@
|
||||||
Cython~=3.1.1
|
Cython~=3.1.1
|
||||||
|
pytest-run-parallel[psutil]
|
||||||
|
|
|
||||||
50
test/test_multithreading.py
Normal file
50
test/test_multithreading.py
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
from concurrent.futures import ThreadPoolExecutor
|
||||||
|
from msgpack import Packer
|
||||||
|
import threading
|
||||||
|
|
||||||
|
|
||||||
|
def run_threaded(
|
||||||
|
func,
|
||||||
|
num_threads=8,
|
||||||
|
pass_count=False,
|
||||||
|
pass_barrier=False,
|
||||||
|
outer_iterations=1,
|
||||||
|
prepare_args=None,
|
||||||
|
):
|
||||||
|
"""Runs a function many times in parallel"""
|
||||||
|
for _ in range(outer_iterations):
|
||||||
|
with ThreadPoolExecutor(max_workers=num_threads) as tpe:
|
||||||
|
if prepare_args is None:
|
||||||
|
args = []
|
||||||
|
else:
|
||||||
|
args = prepare_args()
|
||||||
|
if pass_barrier:
|
||||||
|
barrier = threading.Barrier(num_threads)
|
||||||
|
args.append(barrier)
|
||||||
|
if pass_count:
|
||||||
|
all_args = [(func, i, *args) for i in range(num_threads)]
|
||||||
|
else:
|
||||||
|
all_args = [(func, *args) for i in range(num_threads)]
|
||||||
|
try:
|
||||||
|
futures = []
|
||||||
|
for arg in all_args:
|
||||||
|
futures.append(tpe.submit(*arg))
|
||||||
|
finally:
|
||||||
|
if len(futures) < num_threads and pass_barrier:
|
||||||
|
barrier.abort()
|
||||||
|
for f in futures:
|
||||||
|
f.result()
|
||||||
|
|
||||||
|
|
||||||
|
def test_multithread_packing():
|
||||||
|
output = []
|
||||||
|
test_data = "abcd" * 10_000_000
|
||||||
|
packer = Packer()
|
||||||
|
|
||||||
|
def closure(b):
|
||||||
|
data = packer.pack(test_data)
|
||||||
|
output.append(data)
|
||||||
|
b.wait()
|
||||||
|
|
||||||
|
run_threaded(closure, num_threads=10, pass_barrier=True, pass_count=False)
|
||||||
Loading…
Add table
Add a link
Reference in a new issue