From 5a98d8f7935e66f3f98802e6e99c6a97ae17065d Mon Sep 17 00:00:00 2001 From: Alexander Volkovsky Date: Sun, 4 Feb 2024 23:11:49 +0100 Subject: [PATCH 1/3] wasm wheels (pyodide) (#52) * build pyodide wheel * build for multiple pyodide versions * update readme --- .github/workflows/ci.yaml | 114 +++++++++++++++++++++++++------------- .gitignore | 6 +- Cargo.toml | 1 + README.md | 4 ++ pyproject.toml | 1 + 5 files changed, 85 insertions(+), 41 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index ea4bed2..09bd3b0 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -6,11 +6,9 @@ on: branches: [main] tags: ['v*'] workflow_dispatch: - inputs: - build: - description: 'Build' - required: true - default: true + +env: + MATURIN_VERSION: 1.4.0 jobs: test: @@ -33,11 +31,9 @@ jobs: pip uninstall numpy -y cargo test --release --features nonumpy - build: + if: ${{ startsWith(github.ref, 'refs/tags/') || github.event_name == 'workflow_dispatch' }} needs: test - runs-on: ${{ matrix.os.platform }} - if: ${{ startsWith(github.ref, 'refs/tags/') || github.event.inputs.build }} strategy: matrix: python: @@ -47,12 +43,13 @@ jobs: - version: '3.10' - version: '3.11' - version: '3.12' - os: - - platform: ubuntu-latest - - platform: macos-latest - - platform: macos-latest + platform: + - os: ubuntu-latest + - os: macos-latest + - os: macos-latest arch: aarch64 - - platform: windows-latest + - os: windows-latest + runs-on: ${{ matrix.platform.os }} steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 @@ -65,49 +62,50 @@ jobs: ~/.cargo/registry ~/.cargo/git target - key: ${{ runner.os.platform }}-cargo-${{ hashFiles('**/Cargo.lock') }} - - - run: rustup target list + key: ${{ runner.platform.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} - name: Build Wheels - Linux - if: matrix.os.platform == 'ubuntu-latest' + if: matrix.platform.os == 'ubuntu-latest' uses: PyO3/maturin-action@v1 with: - maturin-version: v1.3.0 + maturin-version: ${{ env.MATURIN_VERSION }} manylinux: auto args: -i python${{ matrix.python.version }} --release --strip --sdist + - name: Check that the source distribution installed correctly + if: matrix.platform.os == 'ubuntu-latest' + run: pip install target/wheels/pyxirr-*.tar.gz + - name: Build Wheels - MacOS [aarch64] - if: ${{ matrix.os.platform == 'macos-latest' && matrix.os.arch == 'aarch64' }} + if: ${{ matrix.platform.os == 'macos-latest' && matrix.platform.arch == 'aarch64' }} uses: PyO3/maturin-action@v1 with: - maturin-version: v1.3.0 + maturin-version: ${{ env.MATURIN_VERSION }} args: -i python --release --target aarch64-apple-darwin --strip - name: Build Wheels - MacOS [x86_64] - if: ${{ matrix.os.platform == 'macos-latest' && matrix.os.arch != 'aarch64' }} + if: ${{ matrix.platform.os == 'macos-latest' && matrix.platform.arch != 'aarch64' }} uses: PyO3/maturin-action@v1 with: - maturin-version: v1.3.0 + maturin-version: ${{ env.MATURIN_VERSION }} args: -i python --release --target universal2-apple-darwin --strip - name: Build Wheels - Windows - if: matrix.os.platform == 'windows-latest' + if: matrix.platform.os == 'windows-latest' uses: PyO3/maturin-action@v1 with: - maturin-version: v1.3.0 + maturin-version: ${{ env.MATURIN_VERSION }} args: -i python --release --strip - name: Upload wheels - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: - name: wheels + name: wheels-${{ matrix.platform.os }}-${{ matrix.platform.arch || 'x86_64' }}-${{ matrix.python.version }} path: target/wheels linux-cross: + if: ${{ startsWith(github.ref, 'refs/tags/') || github.event_name == 'workflow_dispatch' }} needs: test - runs-on: ubuntu-latest - if: ${{ startsWith(github.ref, 'refs/tags/') || github.event.inputs.build }} strategy: matrix: python: @@ -124,6 +122,7 @@ jobs: - version: '3.12' abi: 'cp312-cp312' target: [aarch64, armv7, s390x, ppc64le, ppc64] + runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Build Wheels @@ -131,20 +130,50 @@ jobs: env: PYO3_CROSS_LIB_DIR: /opt/python/${{ matrix.python.abi }}/lib with: - maturin-version: v1.3.0 + maturin-version: ${{ env.MATURIN_VERSION }} target: ${{ matrix.target }} manylinux: auto - args: -i python3.9 --release --strip + args: --release --strip -i python${{ matrix.python.version }} - name: Upload wheels uses: actions/upload-artifact@v4 with: - name: wheels + name: wheels-${{ matrix.target }}-${{ matrix.python.version }} path: target/wheels - linux-musl: + wasm-emscripten: + if: ${{ startsWith(github.ref, 'refs/tags/') || github.event_name == 'workflow_dispatch' }} needs: test + strategy: + matrix: + # https://pyodide.org/en/stable/project/changelog.html + version: + - python: '3.11' + emscripten: 3.1.46 # pyodide 0.25.* + - python: '3.11' + emscripten: 3.1.45 # pyodide 0.24.* + - python: '3.11' + emscripten: 3.1.32 # pyodide 0.23.* runs-on: ubuntu-latest - if: ${{ startsWith(github.ref, 'refs/tags/') || github.event.inputs.build }} + steps: + - uses: actions/checkout@v4 + - uses: mymindstorm/setup-emsdk@v14 + with: + version: ${{ matrix.version.emscripten }} + - uses: PyO3/maturin-action@v1 + with: + maturin-version: ${{ env.MATURIN_VERSION }} + target: wasm32-unknown-emscripten + rust-toolchain: nightly + args: --release --strip -i python${{ matrix.version.python }} + - name: Upload wheels + uses: actions/upload-artifact@v4 + with: + name: wheels-wasm-emscripten-${{ matrix.version.emscripten }} + path: target/wheels + + linux-musl: + if: ${{ startsWith(github.ref, 'refs/tags/') || github.event_name == 'workflow_dispatch' }} + needs: test strategy: matrix: target: @@ -152,29 +181,35 @@ jobs: - i686-unknown-linux-musl - aarch64-unknown-linux-musl - armv7-unknown-linux-musleabihf + runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Build Wheels - musl uses: PyO3/maturin-action@v1 with: - maturin-version: v1.3.0 + maturin-version: ${{ env.MATURIN_VERSION }} target: ${{ matrix.target }} manylinux: musllinux_1_2 args: --release --strip -i 3.7 3.8 3.9 3.10 3.11 3.12 - name: Upload wheels uses: actions/upload-artifact@v4 with: - name: wheels + name: wheels-musl-${{ matrix.target }} path: target/wheels publish: - needs: [build, linux-cross, linux-musl] - runs-on: ubuntu-latest if: startsWith(github.ref, 'refs/tags/') + needs: + - build + - linux-cross + - linux-musl + - wasm-emscripten + runs-on: ubuntu-latest steps: - uses: actions/download-artifact@v4 with: - name: wheels + name: wheels-* + merge-multiple: true - run: pip install maturin @@ -188,4 +223,5 @@ jobs: - name: PyPI publish env: MATURIN_PASSWORD: ${{ secrets.PYPI_PASSWORD }} - run: find . -name 'pyxirr*' | xargs -l maturin upload --skip-existing --username __token__ + # wasm excluded because pypi doesn't support wasm wheels yet + run: find . -name 'pyxirr*' -not -name 'wasm' | xargs -l maturin upload --skip-existing --username __token__ diff --git a/.gitignore b/.gitignore index c3aab21..383cc0e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ -/target -.mypy_cache/ +target +.mypy_cache __pycache__ *.so +.gdb_history +.pyodide-xbuildenv diff --git a/Cargo.toml b/Cargo.toml index 8abfa82..8fea2c7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,7 @@ keywords = [ ] include = [ "src/**", + "docs/_inline/**", "Cargo.toml", "pyproject.toml", "LICENSE", diff --git a/README.md b/README.md index 9e14617..95c20f4 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,10 @@ Features: pip install pyxirr ``` +> WASM wheels for [pyodide](https://github.com/pyodide/pyodide) are also available, +> but unfortunately are [not supported by PyPI](https://github.com/pypi/warehouse/issues/10416). +> You can find them on the [GitHub Releases](https://github.com/Anexen/pyxirr/releases) page. + # Benchmarks Rust implementation has been tested against existing [xirr](https://pypi.org/project/xirr/) package diff --git a/pyproject.toml b/pyproject.toml index 4d3ae4a..6765de9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -30,6 +30,7 @@ include = [ { path = "Cargo.toml", format = "sdist" }, { path = "Cargo.lock", format = "sdist" }, { path = ".cargo/*", format = "sdist" }, + { path = "docs", format = "sdist" }, ] [tool.black] From 931e311b06ec0f05acdabbde1e8c6ec8e7f7867d Mon Sep 17 00:00:00 2001 From: Anexen Date: Sun, 4 Feb 2024 23:24:06 +0100 Subject: [PATCH 2/3] bump version to 0.10.3 --- CHANGELOG.md | 4 +++- Cargo.lock | 2 +- Cargo.toml | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6566de0..aa3d819 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,10 @@ # Changelog -## not released +## [0.10.3] - 2024-02-04 - XIRR Performance improvements +- Fixed building from source distribution +- Build wheels for Pyodide (WASM wheels) ## [0.10.2] - 2024-01-27 diff --git a/Cargo.lock b/Cargo.lock index e848a18..b273f44 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -366,7 +366,7 @@ dependencies = [ [[package]] name = "pyxirr" -version = "0.10.2" +version = "0.10.3" dependencies = [ "assert_approx_eq", "ndarray", diff --git a/Cargo.toml b/Cargo.toml index 8fea2c7..49c4832 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pyxirr" -version = "0.10.2" +version = "0.10.3" authors = ["Anexen"] edition = "2021" description = "Rust-powered collection of financial functions for Python." From 9b65a6c6829de0e10b4d85112ba216289b89e0b7 Mon Sep 17 00:00:00 2001 From: github-action-benchmark Date: Sun, 4 Feb 2024 22:25:48 +0000 Subject: [PATCH 3/3] add Rust Benchmark (cargo) benchmark result for 931e311b06ec0f05acdabbde1e8c6ec8e7f7867d --- docs/bench/data.js | 98 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 97 insertions(+), 1 deletion(-) diff --git a/docs/bench/data.js b/docs/bench/data.js index d9e7d80..845f800 100644 --- a/docs/bench/data.js +++ b/docs/bench/data.js @@ -1,5 +1,5 @@ window.BENCHMARK_DATA = { - "lastUpdate": 1706562288951, + "lastUpdate": 1707085548952, "repoUrl": "https://github.com/Anexen/pyxirr", "entries": { "Rust Benchmark": [ @@ -3778,6 +3778,102 @@ window.BENCHMARK_DATA = { "unit": "ns/iter" } ] + }, + { + "commit": { + "author": { + "email": "avolk93@gmail.com", + "name": "Anexen", + "username": "Anexen" + }, + "committer": { + "email": "avolk93@gmail.com", + "name": "Anexen", + "username": "Anexen" + }, + "distinct": true, + "id": "931e311b06ec0f05acdabbde1e8c6ec8e7f7867d", + "message": "bump version to 0.10.3", + "timestamp": "2024-02-04T23:24:06+01:00", + "tree_id": "ecfcf99a3c16af134957115973485f4677d00b5f", + "url": "https://github.com/Anexen/pyxirr/commit/931e311b06ec0f05acdabbde1e8c6ec8e7f7867d" + }, + "date": 1707085548699, + "tool": "cargo", + "benches": [ + { + "name": "bench_python_100", + "value": 991372, + "range": "± 6338", + "unit": "ns/iter" + }, + { + "name": "bench_python_1000", + "value": 10264432, + "range": "± 75164", + "unit": "ns/iter" + }, + { + "name": "bench_python_50", + "value": 438349, + "range": "± 3840", + "unit": "ns/iter" + }, + { + "name": "bench_python_500", + "value": 4867056, + "range": "± 30278", + "unit": "ns/iter" + }, + { + "name": "bench_rust_100", + "value": 7308, + "range": "± 75", + "unit": "ns/iter" + }, + { + "name": "bench_rust_1000", + "value": 71640, + "range": "± 793", + "unit": "ns/iter" + }, + { + "name": "bench_rust_50", + "value": 3713, + "range": "± 278", + "unit": "ns/iter" + }, + { + "name": "bench_rust_500", + "value": 39287, + "range": "± 219", + "unit": "ns/iter" + }, + { + "name": "bench_scipy_100", + "value": 393335, + "range": "± 5347", + "unit": "ns/iter" + }, + { + "name": "bench_scipy_1000", + "value": 2595898, + "range": "± 22480", + "unit": "ns/iter" + }, + { + "name": "bench_scipy_50", + "value": 266311, + "range": "± 4229", + "unit": "ns/iter" + }, + { + "name": "bench_scipy_500", + "value": 1379722, + "range": "± 17071", + "unit": "ns/iter" + } + ] } ] }