Ryan Malloy a9e1f17bae Phase 31: Head-to-head benchmark vs IfxPy (the C-bound PyPI driver)
Adds a paired benchmark of informix-db (pure Python) against IfxPy
3.0.5 (IBM's C-bound driver via OneDB ODBC) on identical workloads
against the same Informix dev container.

Headline result: pure Python is competitive — and faster on 2/5
benchmarks where wire round-trip dominates over codec/marshaling.

| Benchmark | IfxPy | informix-db | Result |
|---|---:|---:|---:|
| select_one_row (single-row latency) | 128 us | 116 us | us 9% faster |
| select_systables_first_10 | 126 us | 184 us | IfxPy 32% faster |
| select_bench_table_all (1k rows) | 969 us | 855 us | us 12% faster |
| executemany(1000) in txn | 21.5 ms | 30.8 ms | IfxPy 30% slower |
| cold_connect_disconnect | 11.0 ms | 10.9 ms | comparable |

Why the surprising wins: IfxPy's path is Python -> OneDB ODBC ->
libifdmr -> wire. Ours is Python -> wire. When wire round-trip
dominates (single-row, bulk fetch), the missing abstraction layer
makes us faster. When per-row marshaling dominates (executemany),
IfxPy's C-level execute(stmt, tuple) beats Python BIND-PDU build.

Files added under tests/benchmarks/compare/:
* Dockerfile.ifxpy — Ubuntu 20.04 base with IfxPy + OneDB drivers
* ifxpy_bench.py — IfxPy benchmark workloads matching test_*_perf.py
* README.md — methodology, results, install gauntlet, reproduction

The IfxPy install gauntlet itself is part of the comparison story:
modern Python 3.11 (not 3.13), setuptools <58, permissive CFLAGS,
manual download of 92MB OneDB ODBC tarball, four LD_LIBRARY_PATH
directories, libcrypt.so.1 (deprecated 2018, missing on Arch /
Fedora 35+ / RHEL 9). Versus our `pip install informix-db`.

README.md (project root): added "Compared to IfxPy" section under
Performance with the headline numbers and a pointer to the full
methodology.

.gitignore: keep Dockerfile/script/README under tests/benchmarks/
compare/, exclude the 92MB OneDB tarball and the local venv.
2026-05-05 11:41:47 -06:00

43 lines
1.6 KiB
Docker

# IfxPy benchmark container — Ubuntu 20.04 base for libcrypt.so.1 compat.
#
# Runs side-by-side with the host's `informix-db` benchmarks against the
# same Informix dev container at host.docker.internal:9088. Both drivers
# hit the same server over loopback equivalent (Docker's host-gateway
# DNS), making the comparison apples-to-apples on the wire layer.
#
# Build:
# docker build -f tests/benchmarks/compare/Dockerfile.ifxpy \
# -t ifxpy-bench tests/benchmarks/compare/
#
# Run:
# docker run --rm --network=host ifxpy-bench
FROM ubuntu:20.04
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y --no-install-recommends \
python3.9 python3-pip python3.9-dev \
build-essential \
libcrypt1 libcrypt-dev \
curl ca-certificates tar \
&& rm -rf /var/lib/apt/lists/*
# IfxPy needs setuptools <58 because its setup.py uses use_2to3
RUN python3.9 -m pip install --upgrade "pip<24" "setuptools<58" wheel
# Permissive CFLAGS bypass GCC's modern strict-pointer-types check.
ENV CFLAGS="-Wno-incompatible-pointer-types -Wno-error"
RUN python3.9 -m pip install IfxPy
# Pull OneDB ODBC drivers (92MB) — IfxPy's setup.py downloaded headers
# but not the runtime libs.
RUN mkdir -p /opt/onedb && cd /opt/onedb && \
curl -sSL https://hcl-onedb.github.io/odbc/OneDB-Linux64-ODBC-Driver.tar | tar xf -
ENV INFORMIXDIR=/opt/onedb/onedb-odbc-driver
ENV LD_LIBRARY_PATH=$INFORMIXDIR/lib:$INFORMIXDIR/lib/cli:$INFORMIXDIR/lib/esql:$INFORMIXDIR/lib/client:$INFORMIXDIR/gls/dll
# Sanity check: import + smoke connect.
COPY ifxpy_bench.py /opt/ifxpy_bench.py
WORKDIR /opt
CMD ["python3.9", "/opt/ifxpy_bench.py"]