Skip to content

Fix optimize dropping only-last-event sub queries - #919

Merged
DavidBadura merged 2 commits into
4.0.xfrom
DavidBadura/dcb-implementation-review-vs
Oct 3, 2026
Merged

DavidBadura merged 2 commits into
4.0.xfrom
DavidBadura/dcb-implementation-review-vs

Conversation

@DavidBadura

Copy link
Copy Markdown
Member

Query::optimize() removed an onlyLastEvent sub query when another onlyLastEvent sub query had broader filters, e.g. ['a'] vs. ['a', 'b']. But the last event tagged a is not necessarily the last event tagged a and b. Since CompositeProjection::query() always optimizes, a decision model with two lastEventIsEnough() projections like that silently built the narrower one from its initial state.

SubQuery::includes() now only lets an onlyLastEvent sub query include another one if both match exactly the same events. A regular sub query can still absorb a narrower onlyLastEvent one, since it loads all events anyway.

SubQuery::includes() treated an onlyLastEvent sub query with broader filters
as covering a narrower onlyLastEvent one. The last event tagged `a` is not
necessarily the last event tagged `a` and `b`, so Query::optimize() removed
the narrower sub query and the projection behind it never got its event.

An onlyLastEvent sub query now only includes another one if both match
exactly the same events.
@github-actions

github-actions Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

Hello 👋

here is the most recent benchmark result:

SplitStreamBench
================

+-------------------------+--------------------+--------------------+-----------+-----------------+------------+-------------+
|                         | time (kde mode)                                     | memory                                     |
+-------------------------+--------------------+--------------------+-----------+-----------------+------------+-------------+
| subject                 | Tag: <current>     | Tag: base          | time-diff | Tag: <current>  | Tag: base  | memory-diff |
+-------------------------+--------------------+--------------------+-----------+-----------------+------------+-------------+
| benchLoad10000Events () | 2.413ms (±0.00%)   | 1.955ms (±0.00%)   | +23.39%   | 35.774mb        | 36.295mb   | -1.43%      |
| benchSave10000Events () | 330.573ms (±0.00%) | 384.734ms (±0.00%) | -14.08%   | 35.909mb        | 35.909mb   | 0.00%       |
+-------------------------+--------------------+--------------------+-----------+-----------------+------------+-------------+

SimpleSetupTaggableStoreBench
=============================

+----------------------------------------+--------------------+--------------------+-----------+-----------------+------------+-------------+
|                                        | time (kde mode)                                     | memory                                     |
+----------------------------------------+--------------------+--------------------+-----------+-----------------+------------+-------------+
| subject                                | Tag: <current>     | Tag: base          | time-diff | Tag: <current>  | Tag: base  | memory-diff |
+----------------------------------------+--------------------+--------------------+-----------+-----------------+------------+-------------+
| benchLoad1Event ()                     | 809.300μs (±0.00%) | 808.400μs (±0.00%) | +0.11%    | 36.312mb        | 36.312mb   | 0.00%       |
| benchLoad10000Events ()                | 44.432ms (±0.00%)  | 44.344ms (±0.00%)  | +0.20%    | 36.312mb        | 36.312mb   | 0.00%       |
| benchSave1Event ()                     | 1.052ms (±0.00%)   | 1.083ms (±0.00%)   | -2.86%    | 36.312mb        | 36.312mb   | 0.00%       |
| benchSave10000Events ()                | 211.622ms (±0.00%) | 211.499ms (±0.00%) | +0.06%    | 36.312mb        | 36.312mb   | 0.00%       |
| benchSave10000Aggregates ()            | 5.735s (±0.00%)    | 5.691s (±0.00%)    | +0.78%    | 36.312mb        | 36.312mb   | 0.00%       |
| benchSave10000AggregatesTransaction () | 3.425s (±0.00%)    | 3.507s (±0.00%)    | -2.34%    | 36.312mb        | 36.312mb   | 0.00%       |
| benchAppend1Event ()                   | 1.085ms (±0.00%)   | 1.214ms (±0.00%)   | -10.64%   | 36.312mb        | 36.312mb   | 0.00%       |
| benchAppend100Events ()                | 5.400ms (±0.00%)   | 5.152ms (±0.00%)   | +4.82%    | 36.312mb        | 36.312mb   | 0.00%       |
+----------------------------------------+--------------------+--------------------+-----------+-----------------+------------+-------------+

SubscriptionEngineBench
=======================

+---------------------------+-----------------+-----------------+-----------+-----------------+------------+-------------+
|                           | time (kde mode)                               | memory                                     |
+---------------------------+-----------------+-----------------+-----------+-----------------+------------+-------------+
| subject                   | Tag: <current>  | Tag: base       | time-diff | Tag: <current>  | Tag: base  | memory-diff |
+---------------------------+-----------------+-----------------+-----------+-----------------+------------+-------------+
| benchHandle10000Events () | 1.652s (±0.00%) | 1.669s (±0.00%) | -1.01%    | 48.301mb        | 48.301mb   | 0.00%       |
+---------------------------+-----------------+-----------------+-----------+-----------------+------------+-------------+

NoopSubscriptionEngineBench
===========================

+---------------------------+-------------------+-------------------+-----------+-----------------+------------+-------------+
|                           | time (kde mode)                                   | memory                                     |
+---------------------------+-------------------+-------------------+-----------+-----------------+------------+-------------+
| subject                   | Tag: <current>    | Tag: base         | time-diff | Tag: <current>  | Tag: base  | memory-diff |
+---------------------------+-------------------+-------------------+-----------+-----------------+------------+-------------+
| benchHandle10000Events () | 61.485ms (±0.00%) | 63.169ms (±0.00%) | -2.67%    | 48.301mb        | 48.301mb   | 0.00%       |
+---------------------------+-------------------+-------------------+-----------+-----------------+------------+-------------+

SimpleSetupStreamStoreBench
===========================

+----------------------------------------+--------------------+--------------------+-----------+-----------------+------------+-------------+
|                                        | time (kde mode)                                     | memory                                     |
+----------------------------------------+--------------------+--------------------+-----------+-----------------+------------+-------------+
| subject                                | Tag: <current>     | Tag: base          | time-diff | Tag: <current>  | Tag: base  | memory-diff |
+----------------------------------------+--------------------+--------------------+-----------+-----------------+------------+-------------+
| benchLoad1Event ()                     | 928.700μs (±0.00%) | 956.000μs (±0.00%) | -2.86%    | 35.146mb        | 35.146mb   | 0.00%       |
| benchLoad10000Events ()                | 43.126ms (±0.00%)  | 44.483ms (±0.00%)  | -3.05%    | 35.146mb        | 35.146mb   | 0.00%       |
| benchSave1Event ()                     | 1.026ms (±0.00%)   | 1.082ms (±0.00%)   | -5.20%    | 35.146mb        | 35.146mb   | 0.00%       |
| benchSave10000Events ()                | 188.607ms (±0.00%) | 206.549ms (±0.00%) | -8.69%    | 35.146mb        | 35.146mb   | 0.00%       |
| benchSave10000Aggregates ()            | 5.517s (±0.00%)    | 5.564s (±0.00%)    | -0.84%    | 35.147mb        | 35.147mb   | 0.00%       |
| benchSave10000AggregatesTransaction () | 3.369s (±0.00%)    | 3.440s (±0.00%)    | -2.06%    | 35.147mb        | 35.147mb   | 0.00%       |
+----------------------------------------+--------------------+--------------------+-----------+-----------------+------------+-------------+

SubscriptionEngineBatchBench
============================

+---------------------------+-------------------+-------------------+-----------+-----------------+------------+-------------+
|                           | time (kde mode)                                   | memory                                     |
+---------------------------+-------------------+-------------------+-----------+-----------------+------------+-------------+
| subject                   | Tag: <current>    | Tag: base         | time-diff | Tag: <current>  | Tag: base  | memory-diff |
+---------------------------+-------------------+-------------------+-----------+-----------------+------------+-------------+
| benchHandle10000Events () | 65.993ms (±0.00%) | 66.289ms (±0.00%) | -0.45%    | 35.726mb        | 35.726mb   | 0.00%       |
+---------------------------+-------------------+-------------------+-----------+-----------------+------------+-------------+

PersonalDataBench
=================

+----------------------------------------+--------------------+--------------------+-----------+-----------------+------------+-------------+
|                                        | time (kde mode)                                     | memory                                     |
+----------------------------------------+--------------------+--------------------+-----------+-----------------+------------+-------------+
| subject                                | Tag: <current>     | Tag: base          | time-diff | Tag: <current>  | Tag: base  | memory-diff |
+----------------------------------------+--------------------+--------------------+-----------+-----------------+------------+-------------+
| benchLoad1Event ()                     | 604.800μs (±0.00%) | 597.000μs (±0.00%) | +1.31%    | 37.008mb        | 37.008mb   | 0.00%       |
| benchLoad10000Events ()                | 104.726ms (±0.00%) | 103.451ms (±0.00%) | +1.23%    | 37.008mb        | 37.008mb   | 0.00%       |
| benchSave1Event ()                     | 1.702ms (±0.00%)   | 2.326ms (±0.00%)   | -26.83%   | 37.008mb        | 37.008mb   | +0.00%      |
| benchSave10000Events ()                | 254.420ms (±0.00%) | 270.452ms (±0.00%) | -5.93%    | 37.063mb        | 37.063mb   | +0.00%      |
| benchSave10000Aggregates ()            | 8.599s (±0.00%)    | 8.704s (±0.00%)    | -1.20%    | 37.008mb        | 37.008mb   | 0.00%       |
| benchSave10000AggregatesTransaction () | 6.402s (±0.00%)    | 6.509s (±0.00%)    | -1.65%    | 37.009mb        | 37.008mb   | +0.00%      |
+----------------------------------------+--------------------+--------------------+-----------+-----------------+------------+-------------+

SnapshotsBench
==============

+----------------------------------------+--------------------+--------------------+-----------+-----------------+------------+-------------+
|                                        | time (kde mode)                                     | memory                                     |
+----------------------------------------+--------------------+--------------------+-----------+-----------------+------------+-------------+
| subject                                | Tag: <current>     | Tag: base          | time-diff | Tag: <current>  | Tag: base  | memory-diff |
+----------------------------------------+--------------------+--------------------+-----------+-----------------+------------+-------------+
| benchLoad10000EventsMissingSnapshot () | 43.681ms (±0.00%)  | 42.548ms (±0.00%)  | +2.66%    | 35.151mb        | 35.151mb   | 0.00%       |
| benchLoad10000Events ()                | 777.300μs (±0.00%) | 741.100μs (±0.00%) | +4.88%    | 35.151mb        | 35.151mb   | 0.00%       |
+----------------------------------------+--------------------+--------------------+-----------+-----------------+------------+-------------+

CommandToQueryBench
===================

+----------------+------------------+------------------+-----------+-----------------+------------+-------------+
|                | time (kde mode)                                 | memory                                     |
+----------------+------------------+------------------+-----------+-----------------+------------+-------------+
| subject        | Tag: <current>   | Tag: base        | time-diff | Tag: <current>  | Tag: base  | memory-diff |
+----------------+------------------+------------------+-----------+-----------------+------------+-------------+
| benchCreate () | 2.574ms (±0.00%) | 2.706ms (±0.00%) | -4.86%    | 5.057mb         | 5.057mb    | 0.00%       |
| benchUpdate () | 3.599ms (±0.00%) | 3.509ms (±0.00%) | +2.56%    | 5.067mb         | 5.067mb    | 0.00%       |
| benchBoth ()   | 5.923ms (±0.00%) | 6.007ms (±0.00%) | -1.40%    | 5.389mb         | 5.389mb    | 0.00%       |
+----------------+------------------+------------------+-----------+-----------------+------------+-------------+

This comment gets update everytime a new commit comes in!

Comment thread src/Store/SubQuery.php Outdated
@DavidBadura
DavidBadura merged commit 57e2762 into 4.0.x Oct 3, 2026
38 of 39 checks passed
@DavidBadura
DavidBadura deleted the DavidBadura/dcb-implementation-review-vs branch October 3, 2026 17:01
@DavidBadura DavidBadura added the bug Something isn't working label Oct 3, 2026
@DavidBadura DavidBadura added this to the 4.0.0 milestone Oct 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants