Skip to content

feat: Message data classes - #284

Open
chrisk314 wants to merge 13 commits into
mainfrom
feat/message-data-classes
Open

chrisk314 wants to merge 13 commits into
mainfrom
feat/message-data-classes

Conversation

@chrisk314

@chrisk314 chrisk314 commented Sep 4, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Implements #102: feat: Base component for external communication (#102).

Adds MessageDataReader / MessageDataWriter for reading and writing records through a pub/sub broker - the broker equivalent of FileReader/FileWriter, where each message carries one record and field_names become the component's outputs (reader) or inputs (writer). Both extend the existing DataReader/DataWriter bases, adding what a broker needs and a finite source does not: a long-lived connection, reconnection with backoff, and acknowledgment.

Three implementations: Google Cloud PubSub, AWS SQS/SNS, Apache Kafka.

Integration tests against real infrastructure are deliberately deferred - no AWS/GCP accounts or broker resources exist yet. Terraform for the required PubSub topic/subscription and SNS topic/SQS queue lives in plugboard-infra (terraform/ci-data-message-testing), and docs/running-message-data-tests.md there describes wiring its outputs into this suite. All 128 tests here are mock-based, so no credentials are needed.

Changes

Base classes

  • MessageDataReader / MessageDataWriter extend DataReader / DataWriter (buffer, input binding and batching are inherited, not copied), adding _connect, _disconnect, _receive/_send, _convert, and _ack (reader).
  • Retry, exponential backoff and reconnect live in one shared place: plugboard/utils/retry.py, with a frozen RetryPolicy value object used by both bases.
  • Broker exceptions (MessageBrokerConnectionError / TransientError / PermanentError) are raised and honoured: each implementation maps its SDK's failures onto them, and permanent errors skip retries that cannot help.
  • Settings for GCP/AWS/Kafka are read as constructor fallbacks (GCP_PUBSUB_PROJECT_ID, AWS_REGION, KAFKA_BOOTSTRAP_SERVERS); explicit arguments win.
  • All six concrete classes are exported from plugboard.library.

Implementations

  • GCPPubSubDataReader / GCPPubSubDataWriter (google-cloud-pubsub) - every synchronous PubSub call is dispatched to a worker thread, so a pull or publish never stalls the shared event loop.
  • AWSSQSDataReader / AWSSNSDataWriter (aiobotocore) - long polling, delete_message_batch for acks, and the 10-message SQS cap is logged rather than applied silently.
  • KafkaDataReader / KafkaDataWriter (aiokafka) - commits the offsets of processed records per partition; sends a batch then flushes once, so producer batching is used.

Packaging: optional extras gcp-pubsub, aws-messaging, kafka; the broker SDKs are also declared in the test dependency group.

Docs: new Message Data usage page (extras, worked example, delivery semantics), broker settings in the configuration page, new extras in the README.

Behaviour worth knowing

  • An empty poll is not the end of the stream. A reader started before its producer keeps waiting and polls again, like WebsocketReader. A subclass signals a genuinely exhausted source by raising NoMoreDataException, which closes the IO as other data readers do.
  • Messages are acknowledged after they are processed. A fetched batch is acked only once all of its records have been published downstream, so a crash mid-batch leaves the unread messages for redelivery (at-least-once). Unconsumed pre-fetched messages are deliberately left unacked.
  • Sends are not cancelled at teardown: an in-flight batch is awaited (and any failure logged) rather than dropped.

Testing

  • 128 unit tests (was 72), all against teardown-aware monkeypatch fixtures rather than global sys.modules mocks, asserting broker calls and arguments rather than private attribute identity.
  • New coverage for the previously-untested paths the review flagged: retry exhaustion and the delay cap, empty-batch handling, SDK error mapping, offset commits, reconnect/disconnect failures, and ack timing.
  • Branch coverage of the new modules: utils/retry.py 100%, message_reader.py 95%, message_writer.py 94%, gcp_pubsub_io.py 94%, aws_messaging_io.py 95%, kafka_io.py 96% - the remaining misses are abstract-method bodies.
  • ruff check, ruff format --check, ty over plugboard/, plugboard-schemas/ and tests/ all pass; mkdocs build is clean.
  • Full unit suite: 409 passed, 6 skipped. Integration suite against the compose services: 141 passed, 1 pre-existing ZMQ flake (test_process_stop_event[LocalProcess-ZMQConnector-...]), which passes on repeat runs in isolation and is addressed in fix: avoid ZMQ slow-joiner loss on pipeline connect #297.

Related

fsspec license metadata is not detectable by licensecheck, causing
CI failures. Add to ignore list since it's BSD-3-Clause licensed.
Implements issue #102: Base component for external communication via
pub/sub message broker infrastructure.

New base classes:
- MessageDataReader: Abstract base for reading data from message brokers
  with connection management, reconnection with exponential backoff,
  retry logic, message acknowledgment, and chunked/buffered reading.
- MessageDataWriter: Abstract base for writing data to message brokers
  with connection management, reconnection, retry logic, and
  chunked/buffered writing.

Concrete implementations:
- GCPPubSubDataReader/Writer: Google Cloud PubSub
- AWSSQSDataReader/AWSSNSDataWriter: AWS SQS/SNS
- KafkaDataReader/Writer: Apache Kafka

Also includes:
- Message broker exceptions (ConnectionError, TransientError, PermanentError)
- Settings for GCP PubSub, AWS, and Kafka
- Optional dependencies in pyproject.toml
- Proposal document with design rationale
- Comprehensive unit tests (72 new tests)
@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown

Benchmark comparison for fa9a1b92 (base) vs e14a0fae (PR)


------------------------------------------------------------------------------------------------------------------ benchmark: 2 tests -----------------------------------------------------------------------------------------------------------------
Name (time in ms)                                                                         Min                 Max                Mean            StdDev              Median               IQR            Outliers     OPS            Rounds  Iterations
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
test_benchmark_process_run (main/.benchmarks/Linux-CPython-3.14-64bit/0001_base)     538.2940 (1.0)      550.3755 (1.00)     543.8897 (1.0)      5.3367 (2.22)     545.2340 (1.0)      9.4054 (2.37)          3;0  1.8386 (1.0)           5           1
test_benchmark_process_run (pr/.benchmarks/Linux-CPython-3.14-64bit/0001_pr)         543.6806 (1.01)     549.3609 (1.0)      546.7065 (1.01)     2.4078 (1.0)      545.9489 (1.00)     3.9692 (1.0)           2;0  1.8291 (0.99)          5           1
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Legend:
  Outliers: 1 Standard Deviation from Mean; 1.5 IQR (InterQuartile Range) from 1st Quartile and 3rd Quartile.
  OPS: Operations Per Second, computed as 1 / Mean

- Fix ruff lint errors: import sorting, unused imports, S110 noqa comments
- Fix ruff format errors in gcp_pubsub_io.py
- Fix mypy overlap errors: remove duplicate fields from ArgsDict TypedDicts
- Fix mypy multiple values error: use kwargs.setdefault instead of pop
- Remove untracked test data files causing lint failures
@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown

Benchmark comparison for fa9a1b92 (base) vs e538c242 (PR)


------------------------------------------------------------------------------------------------------------------ benchmark: 2 tests -----------------------------------------------------------------------------------------------------------------
Name (time in ms)                                                                         Min                 Max                Mean            StdDev              Median               IQR            Outliers     OPS            Rounds  Iterations
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
test_benchmark_process_run (pr/.benchmarks/Linux-CPython-3.14-64bit/0001_pr)         378.6095 (1.0)      381.9872 (1.0)      380.3807 (1.0)      1.4510 (1.0)      380.8602 (1.0)      2.4960 (1.0)           2;0  2.6289 (1.0)           5           1
test_benchmark_process_run (main/.benchmarks/Linux-CPython-3.14-64bit/0001_base)     380.9969 (1.01)     387.2179 (1.01)     383.3493 (1.01)     2.6439 (1.82)     381.8112 (1.00)     3.9492 (1.58)          1;0  2.6086 (0.99)          5           1
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Legend:
  Outliers: 1 Standard Deviation from Mean; 1.5 IQR (InterQuartile Range) from 1st Quartile and 3rd Quartile.
  OPS: Operations Per Second, computed as 1 / Mean

Increase connection establishment sleep in _ZMQPipelineConnectorProxy
from 0.1s to 0.5s to allow the proxy subprocess's SUB socket
subscription to propagate to XPUB before the sender starts publishing
(ZMQ slow joiner problem). Also mark the test as flaky with 3 reruns
following the existing pattern used elsewhere in the repo.

Fixes: test_process_with_components_run[RayProcess-zmq_connector_cls-zmq_pubsub_proxy=True-10-2.0]
@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown

Benchmark comparison for 7b0cbeda (base) vs e49d472e (PR)


------------------------------------------------------------------------------------------------------------------ benchmark: 2 tests -----------------------------------------------------------------------------------------------------------------
Name (time in ms)                                                                         Min                 Max                Mean            StdDev              Median               IQR            Outliers     OPS            Rounds  Iterations
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
test_benchmark_process_run (pr/.benchmarks/Linux-CPython-3.14-64bit/0001_pr)         286.1344 (1.0)      297.6967 (1.0)      292.9123 (1.0)      4.6218 (1.97)     294.8739 (1.0)      6.6802 (2.40)          2;0  3.4140 (1.0)           5           1
test_benchmark_process_run (main/.benchmarks/Linux-CPython-3.14-64bit/0001_base)     295.0680 (1.03)     301.3671 (1.01)     297.8813 (1.02)     2.3407 (1.0)      297.1355 (1.01)     2.7794 (1.0)           2;0  3.3570 (0.98)          5           1
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Legend:
  Outliers: 1 Standard Deviation from Mean; 1.5 IQR (InterQuartile Range) from 1st Quartile and 3rd Quartile.
  OPS: Operations Per Second, computed as 1 / Mean

@codecov

codecov Bot commented Sep 9, 2026 •

Copy link
Copy Markdown

- Fix invalid-raise errors in message_reader.py and message_writer.py
  by initializing last_exception with a non-None default instead of
  Optional[Exception]
- Remove PublisherClient.close() call in gcp_pubsub_io.py (method does
  not exist on the client); just set reference to None for GC
- Update test to match new disconnect behavior
@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown

Benchmark comparison for 7b0cbeda (base) vs d315dd07 (PR)


------------------------------------------------------------------------------------------------------------------ benchmark: 2 tests -----------------------------------------------------------------------------------------------------------------
Name (time in ms)                                                                         Min                 Max                Mean            StdDev              Median               IQR            Outliers     OPS            Rounds  Iterations
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
test_benchmark_process_run (main/.benchmarks/Linux-CPython-3.14-64bit/0001_base)     534.4430 (1.0)      539.0566 (1.0)      536.5269 (1.0)      1.8247 (1.0)      535.9234 (1.0)      2.7265 (1.0)           2;0  1.8638 (1.0)           5           1
test_benchmark_process_run (pr/.benchmarks/Linux-CPython-3.14-64bit/0001_pr)         538.3621 (1.01)     549.1566 (1.02)     544.6404 (1.02)     4.0247 (2.21)     545.0155 (1.02)     4.7870 (1.76)          2;0  1.8361 (0.99)          5           1
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Legend:
  Outliers: 1 Standard Deviation from Mean; 1.5 IQR (InterQuartile Range) from 1st Quartile and 3rd Quartile.
  OPS: Operations Per Second, computed as 1 / Mean

The design proposal is not tracked in the repo. Added to .gitignore
to prevent accidental re-commit.
@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown

Benchmark comparison for 7b0cbeda (base) vs 0fa21c58 (PR)


------------------------------------------------------------------------------------------------------------------ benchmark: 2 tests -----------------------------------------------------------------------------------------------------------------
Name (time in ms)                                                                         Min                 Max                Mean            StdDev              Median               IQR            Outliers     OPS            Rounds  Iterations
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
test_benchmark_process_run (main/.benchmarks/Linux-CPython-3.14-64bit/0001_base)     527.9234 (1.0)      542.6921 (1.0)      537.0849 (1.0)      5.5841 (1.28)     537.6015 (1.0)      5.9359 (1.0)           2;0  1.8619 (1.0)           5           1
test_benchmark_process_run (pr/.benchmarks/Linux-CPython-3.14-64bit/0001_pr)         540.4164 (1.02)     550.3291 (1.01)     546.0575 (1.02)     4.3785 (1.0)      548.3933 (1.02)     7.3029 (1.23)          1;0  1.8313 (0.98)          5           1
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Legend:
  Outliers: 1 Standard Deviation from Mean; 1.5 IQR (InterQuartile Range) from 1st Quartile and 3rd Quartile.
  OPS: Operations Per Second, computed as 1 / Mean

Resolve conflict in tests/integration/test_process_with_components_run.py:
keep main's native pytest parametrization (ConnectorCase + indirect +
ids) replacing pytest-cases, retaining the flaky marker for the
Ray + ZMQ proxy case. Regenerate uv.lock for merged pyproject extras.

Verified: ruff check, ruff format, ty check all pass; new ZMQ backend/
channel/proxy unit tests (21) and message data tests (72) pass; merged
integration file collects cleanly (25 tests).
@github-actions

github-actions Bot commented Oct 4, 2026

Copy link
Copy Markdown

Benchmark comparison for 894671bb (base) vs a7d10b72 (PR)


------------------------------------------------------------------------------------------------------------------- benchmark: 2 tests ------------------------------------------------------------------------------------------------------------------
Name (time in ms)                                                                         Min                 Max                Mean             StdDev              Median                IQR            Outliers     OPS            Rounds  Iterations
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
test_benchmark_process_run (pr/.benchmarks/Linux-CPython-3.14-64bit/0001_pr)         289.2487 (1.0)      316.7170 (1.06)     297.5400 (1.01)     11.2704 (4.16)     292.8931 (1.0)      12.7278 (2.47)          1;0  3.3609 (0.99)          5           1
test_benchmark_process_run (main/.benchmarks/Linux-CPython-3.14-64bit/0001_base)     292.6107 (1.01)     298.1502 (1.0)      295.5250 (1.0)       2.7097 (1.0)      296.5808 (1.01)      5.1463 (1.0)           2;0  3.3838 (1.0)           5           1
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Legend:
  Outliers: 1 Standard Deviation from Mean; 1.5 IQR (InterQuartile Range) from 1st Quartile and 3rd Quartile.
  OPS: Operations Per Second, computed as 1 / Mean

Blocking issues:
- An empty broker poll no longer ends the stream. `_receive` returning [] means
  "nothing yet", so `step()` waits and polls again like `WebsocketReader`; only a
  subclass raising `NoMoreDataException` closes the IO (B1).
- A batch is acknowledged only after its last record is consumed, instead of after
  the first one. Previously a crash mid-batch lost the unread messages (B2).
- `KafkaDataReader._ack` commits the offsets following the processed records, per
  partition, instead of the consumer position, which could mark unprocessed records
  as done (B3).
- GCP reader and writer dispatch every synchronous PubSub call (client construction,
  pull, acknowledge, publish, future.result, stop, close) to a worker thread, so they
  no longer block the shared event loop (B4, B5).

Design and consolidation:
- `MessageDataReader`/`MessageDataWriter` now extend `DataReader`/`DataWriter`,
  reusing the buffer, binding and batching logic instead of copying it (W14).
- Retry, backoff and reconnect live in one place: `plugboard.utils.retry` with a
  frozen `RetryPolicy` value object shared by both bases (W13, L1, L2).
- A failing reconnect no longer escapes the retry loop; it costs an attempt and the
  broker error is raised once attempts run out (W12).
- Row-to-message encoding is shared as `iter_records`/`encode_records`/
  `encode_records_bytes`; the old per-row deque indexing was quadratic in buffer size
  and duplicated across three writers (W16, W19).
- Connection access is serialised with an `asyncio.Lock` across ack and reconnect (W15).
- Kafka writer submits all records then flushes once, instead of one round trip per
  record (W18). SQS deletes ack batches of up to 10 with `delete_message_batch` and
  reports partial failures rather than pretending success (L3).
- The GCP publisher is stopped on disconnect, so a reconnect no longer leaks a channel
  and its threads (W17).
- `MessageBrokerPermanentError`/`TransientError` are now actually raised and honoured:
  each broker maps its SDK's failures onto the hierarchy, and permanent errors skip the
  retries that previously burnt against a guaranteed failure (W1).

Configuration and packaging:
- The GCP/AWS/Kafka settings are read as constructor fallbacks via
  `resolve_argument`, so `GCP_PUBSUB_PROJECT_ID`, `AWS_REGION` and
  `KAFKA_BOOTSTRAP_SERVERS` work (W2).
- `aws-messaging` now uses `aiobotocore` instead of `aioboto3`, which no longer forces
  the shared botocore/boto3 stack backwards (W5).
- Broker SDKs are declared in the `test` dependency group, which also resolves the three
  `ty` unresolved-import findings (W10 root cause).
- The six concrete broker classes are exported from `plugboard.library` (W3).
- Removed the misleading broker-specific ArgsDicts that documented attributes they did
  not declare (W20).

Tests: 126 tests, up from 72, all using teardown-aware monkeypatch fixtures instead of
global `sys.modules` mocks, asserting broker calls rather than private attribute
identity (W10, W11). New coverage for retry exhaustion and the delay cap, empty-batch
handling, error-branch mapping, offset commits, reconnect failure, and the
acknowledgment timing that previously lost records (W7, W8, W9). Record encoding is
parametrised once rather than copied across three modules (L4).

Docs: new Message Data usage page (extras, worked example, delivery semantics), broker
settings in the configuration page, and the new extras in the README (W4).

Test isolation: the S3 file tests pinned their bucket region so they no longer depend
on the developer's ambient AWS profile, which the newer botocore resolves over
`AWS_REGION`.
The connection delay and the flaky marker on the Ray + ZMQ integration test fix an
unrelated ZMQ connector issue; they now move with it to their own change.
@github-actions

github-actions Bot commented Oct 4, 2026

Copy link
Copy Markdown

Benchmark comparison for 894671bb (base) vs 6ac64739 (PR)


------------------------------------------------------------------------------------------------------------------ benchmark: 2 tests ------------------------------------------------------------------------------------------------------------------
Name (time in ms)                                                                         Min                 Max                Mean            StdDev              Median                IQR            Outliers     OPS            Rounds  Iterations
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
test_benchmark_process_run (main/.benchmarks/Linux-CPython-3.14-64bit/0001_base)     541.8068 (1.0)      555.3819 (1.01)     548.8945 (1.00)     5.9871 (3.94)     546.7437 (1.00)     10.3207 (4.72)          3;0  1.8218 (1.00)          5           1
test_benchmark_process_run (pr/.benchmarks/Linux-CPython-3.14-64bit/0001_pr)         544.6977 (1.01)     548.6559 (1.0)      546.6321 (1.0)      1.5215 (1.0)      546.2889 (1.0)       2.1859 (1.0)           2;0  1.8294 (1.0)           5           1
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Legend:
  Outliers: 1 Standard Deviation from Mean; 1.5 IQR (InterQuartile Range) from 1st Quartile and 3rd Quartile.
  OPS: Operations Per Second, computed as 1 / Mean

…ure at teardown

Closes the two remaining uncovered branches from the error-handling paths the review
asked about: a reconnect whose disconnect raises must still connect and let the retry
proceed, and a send still in flight when destroy runs must be reported rather than
swallowed. plugboard/utils/retry.py is now at 100% branch coverage.
@chrisk314

Copy link
Copy Markdown
Contributor Author

Review response

Addressed in b569b78, 6ac6473, 3af63fe:

What changed
B1 Empty poll = "nothing yet": step() waits and re-polls instead of closing the stream; NoMoreDataException is reserved for an exhausted source, and KafkaDataReader._receive now returns [] rather than raising.
B2 A batch is acked only when its last record has been consumed (_ack_pending fires on drain), so records still in the buffer stay redeliverable.
B3 KafkaDataReader._ack commits TopicPartition -> OffsetAndMetadata(offset + 1) for the records passed in, highest per partition, instead of the consumer position.
B4/B5 Every synchronous GCP call (client construction, pull, acknowledge, publish, future.result, close, stop) runs via asyncio.to_thread. Covered by tests that assert the SDK call happens off the event loop thread.
W1 Brokers map SDK failures onto the hierarchy (NotFound/QueueDoesNotExist -> NoMoreDataException, auth/invalid-argument -> permanent, throttling/transport -> transient); with_retry re-raises MessageBrokerPermanentError immediately.
W2 resolve_argument reads GCP_PUBSUB_PROJECT_ID, AWS_REGION, KAFKA_BOOTSTRAP_SERVERS as constructor fallbacks, with an error naming the variable to set.
W3 Six concrete classes exported from plugboard.library; verified the package still imports with all three SDKs blocked.
W4 New docs/usage/message-data.md (in nav), broker-settings section in configuration.md, extras in the README; API entries now render via W3.
W5 aioboto3 dropped for aiobotocore>=3.4,<4: the shared stack moved up (aiobotocore 3.4.0 -> 3.9.2, botocore 1.42.84 -> 1.43.106) instead of down.
W7/W8/W9 Retry exhaustion raises the broker error after exactly max_retries+1 attempts / max_retries reconnects (asserted, with the delay cap); empty-batch path, SDK error branches, disconnect-failure and pending-send-failure arms covered.
W10/W11/L4 sys.modules.setdefault mocks replaced by monkeypatch fixtures over the implementation modules; assertions target broker calls/arguments; record encoding tested once.
W12 A failing reconnect is recorded and the loop continues; the broker error is raised once attempts run out.
W13/L1/L2 One shared with_retry + RetryPolicy (frozen msgspec.Struct) + attempt_reconnect, used by both bases; nesting depth reduced.
W14/W19 MessageDataReader/MessageDataWriter inherit DataReader/DataWriter; row-to-payload encoding shared as iter_records/encode_records/encode_records_bytes.
W15 An asyncio.Lock serialises _ack against _reconnect.
W16 iter_records zips the deques once - the per-row deque[i] indexing was quadratic and, with the default chunk_size, ran over the whole buffered stream.
W17 _disconnect calls publisher.stop(), so a reconnect no longer leaks a channel and its threads.
W18 Kafka writer gathers send() futures then flushes once; send_and_wait is asserted unused.
W20 The six ArgsDict subclasses that documented undeclared attributes were removed (matching the FileReader/DataReaderArgsSpec convention); topic is documented on the base dicts.
L3 SQS acks use delete_message_batch in groups of 10 and raise MessageBrokerTransientError on partial failure instead of reporting success.
L5 ZMQ connect_recv delay + flaky marker reverted here and moved to #297.
L6 Redundant # Use getmany... comment removed.

Deferred (W6): real-infrastructure integration tests, pending the AWS account and GCP project plus the Terraform in plugboard-infra. Until then tests/integration/ has no message-data coverage, so wire-format, credential, long-poll and ack/commit behaviour against live brokers is still unverified - which is also expected to be where the remaining design questions surface.

@github-actions

github-actions Bot commented Oct 4, 2026

Copy link
Copy Markdown

Benchmark comparison for 894671bb (base) vs 3af63fee (PR)


------------------------------------------------------------------------------------------------------------------ benchmark: 2 tests -----------------------------------------------------------------------------------------------------------------
Name (time in ms)                                                                         Min                 Max                Mean            StdDev              Median               IQR            Outliers     OPS            Rounds  Iterations
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
test_benchmark_process_run (pr/.benchmarks/Linux-CPython-3.14-64bit/0001_pr)         399.5175 (1.0)      420.8993 (1.03)     404.9637 (1.0)      9.0346 (5.23)     400.8723 (1.0)      7.8745 (2.94)          1;1  2.4694 (1.0)           5           1
test_benchmark_process_run (main/.benchmarks/Linux-CPython-3.14-64bit/0001_base)     403.7804 (1.01)     407.8922 (1.0)      405.3655 (1.00)     1.7286 (1.0)      404.5846 (1.01)     2.6822 (1.0)           1;0  2.4669 (1.00)          5           1
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Legend:
  Outliers: 1 Standard Deviation from Mean; 1.5 IQR (InterQuartile Range) from 1st Quartile and 3rd Quartile.
  OPS: Operations Per Second, computed as 1 / Mean

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant