[SERVER-69149] Make debug print of SBE expressions more readable Created: 25/Aug/22  Updated: 29/Oct/23  Resolved: 23/Sep/22

Status: Closed
Project: Core Server
Component/s: None
Affects Version/s: None
Fix Version/s: 6.2.0-rc0

Type: Improvement Priority: Major - P3
Reporter: David Storch Assignee: David Storch
Resolution: Fixed Votes: 0
Labels: auto-reverted
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Depends
Problem/Incident
Backwards Compatibility: Fully Compatible
Sprint: QE 2022-09-19, QE 2022-10-03
Participants:
Linked BF Score: 146

 Description   

As part of our efforts to improve the performance of the SBE engine, we are trying to change our plan generation logic so that instead of generating large subtrees of PlanStages, we instead generate large EExpression trees. This comes with a performance benefit, since we've found that it's cheaper to interpret the bytecode generated from EExpression trees than interpreting PlanStage trees (which involves a long chain of getNext() virtual function calls).

Although such changes improve the performance of the engine, it reduces debuggability. The debug print for PlanStage uses newlines and spacing to show the tree structure. In contrast, EExpression debug print produces a long wall of text like this:

        [2] filter {let [l4.0 = let [l2.0 = [2, 12], l2.1 = let [l1.0 = s7] if (! exists (l1.0) || typeMatch (l1.0, 1088), null, if (! isArray (l1.0), fail ( 5126900 ,All operands of $setIntersection must be arrays.), setIntersection (l1.0)))] fillEmpty (l2.0 <=> l2.1 >= 0, exists (l2.0) && typeMatch (l2.0, -65) >= exists (l2.1) && typeMatch (l2.1, -65))] exists (l4.0) && ! typeMatch (l4.0, 1088) && l4.0 <=> false != 0 && l4.0 <=> 0 != 0}

We could improve this by rendering the EExpression tree with newlines and potentially some delimiters to indicate the beginning and end of expressions.



 Comments   
Comment by Githook User [ 23/Sep/22 ]

Author:

{'name': 'David Storch', 'email': 'david.storch@mongodb.com', 'username': 'dstorch'}

Message: SERVER-69149 Make debug print of SBE expressions more readable

Reapplies the original change with a corrected out-of-bounds
check.
Branch: master
https://github.com/mongodb/mongo/commit/cdafd3e4b159ed66d61da9fc6d15c8707a3e5b3e

Comment by xgen-buildbaron-user [ 23/Sep/22 ]

Ticket re-opened due to revert. write_concern_majority_passthrough began a consistent failure of jstests\core\distinct_with_hashed_index.js

Comment by Githook User [ 23/Sep/22 ]

Author:

{'name': 'auto-revert-processor', 'email': 'dev-prod-dag@mongodb.com'}

Message: Revert "SERVER-69149 Make debug print of SBE expressions more readable"

This reverts commit fd15b0d0ef92e32bc3ce60742ffe6a5337269bff.
Branch: master
https://github.com/mongodb/mongo/commit/7645dbbe88354f09ee8d84dc393a899cd067bc71

Comment by Githook User [ 22/Sep/22 ]

Author:

{'name': 'David Storch', 'email': 'david.storch@mongodb.com', 'username': 'dstorch'}

Message: SERVER-69149 Make debug print of SBE expressions more readable

Also improves debug print of the SBE union stage.
Branch: master
https://github.com/mongodb/mongo/commit/fd15b0d0ef92e32bc3ce60742ffe6a5337269bff

Comment by David Storch [ 16/Sep/22 ]

I typed up a quick and rather arbitrary example I can use to test out what a nice rendering of SBE expressions could look like:

(function() {
"use strict";
 
db.c.drop();
assert.commandWorked(db.c.insert({}));
 
let explain = db.c.find({
                      $expr: {
                          $or: [
                              {$eq: ["$a", "$b"]},
                              {$lt: [{$abs: "$c.d"}, "$e.f"]},
                          ]
                      }
                  })
                  .explain();
let sbePlan = explain.queryPlanner.winningPlan.slotBasedPlan.stages;
print(sbePlan);
}());

The output from the master branch looks like this:

[1] filter {let [l8.0 = s8] exists (l8.0) && ! typeMatch (l8.0, 1088) && l8.0 <=> false != 0 && l8.0 <=> 0 != 0}
[1] nlj [s4, s5] [s4, s5]
    left
        [1] scan s4 s5 none none none none [] @"7b354343-3715-4463-bbb0-ea3024f46d1f" true false
    right
        [1] limit 1
        [1] union [s8] [
            [s6] [1] project [s6 = true]
            [1] filter {let [l7.0 = let [l1.0 = getField (s4, "a"), l1.1 = getField (s4, "b")] fillEmpty (l1.0 <=> l1.1 == 0, exists (l1.0) && typeMatch (l1.0, -65) == exists (l1.1) && typeMatch (l1.1, -65))] exists (l7.0) && ! typeMatch (l7.0, 1088) && l7.0 <=> false != 0 && l7.0 <=> 0 != 0}
            [1] limit 1
            [1] coscan ,
            [s7] [1] project [s7 = let [l6.0 = let [l5.0 = let [l3.0 = traverseP (getField (s4, "c"), \ l2.0 . getField (l2.0, "d"), 1)] if (! exists (l3.0) || typeMatch (l3.0, 1088), null, if (! isNumber (l3.0), fail ( 4903700 ,$abs only supports numeric types), if (typeMatch (l3.0, 262144) && l3.0 == -9223372036854775808, fail ( 4903701 ,can't take $abs of long long min), abs (l3.0)))), l5.1 = traverseP (getField (s4, "e"), \ l4.0 . getField (l4.0, "f"), 1)] fillEmpty (l5.0 <=> l5.1 < 0, exists (l5.0) && typeMatch (l5.0, -65) < exists (l5.1) && typeMatch (l5.1, -65))] exists (l6.0) && ! typeMatch (l6.0, 1088) && l6.0 <=> false != 0 && l6.0 <=> 0 != 0]
            [1] limit 1
            [1] coscan
       ]

Generated at Thu Feb 08 06:12:42 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.