Skip to content

Commit

Permalink
C++: Fix join-order problem in UserType::getADeclarationEntry
Browse files Browse the repository at this point in the history
Before on `LRMPUT/PUTSLAM`:
```
Evaluated recursive predicate UserType::UserType.getADeclarationEntry/0#cea44e2f@7ce3a4hu in 22069ms on iteration 2 (delta size: 379076853).
Evaluated relational algebra for predicate UserType::UserType.getADeclarationEntry/0#cea44e2f@7ce3a4hu on iteration 2 running pipeline standard with tuple counts:
           126825  ~32%    {2} r1 = JOIN `UserType::UserType.getADeclarationEntry/0#cea44e2f#prev_delta` WITH Class::Class#9afdbffd ON FIRST 1 OUTPUT Lhs.0, Lhs.1
        379076853  ~97%    {2}    | JOIN WITH `Class::Class.isConstructedFrom/1#dispred#390e01c8_10#join_rhs` ON FIRST 1 OUTPUT Rhs.1, Lhs.1
        379076853  ~97%    {2}    | JOIN WITH UserType::UserType#21e9e463 ON FIRST 1 OUTPUT Lhs.0, Lhs.1
                           {2}    | AND NOT `UserType::UserType.getADeclarationEntry/0#cea44e2f#prev`(FIRST 2)
        379076853  ~96%    {2}    | SCAN OUTPUT In.1, In.0
                           {2}    | AND NOT `_Class::Class#9afdbffd_Class::Class.isConstructedFrom/1#dispred#390e01c8_10#join_rhs_ResolveClass::r__#antijoin_rhs`(FIRST 2)
        379076853  ~97%    {2}    | SCAN OUTPUT In.1, In.0
                           return r1

Evaluated named local _Class::Class#9afdbffd_Class::Class.isConstructedFrom/1#dispred#390e01c8_10#join_rhs_ResolveClass::r__#antijoin_rhs@L0#7ce3a in 7459ms on iteration 2 (size: 0).
Evaluated relational algebra for predicate _Class::Class#9afdbffd_Class::Class.isConstructedFrom/1#dispred#390e01c8_10#join_rhs_ResolveClass::r__#antijoin_rhs@L0#7ce3a on iteration 2 running pipeline main with tuple counts:
           126825  ~32%    {2} r1 = JOIN `UserType::UserType.getADeclarationEntry/0#cea44e2f#prev_delta` WITH Class::Class#9afdbffd ON FIRST 1 OUTPUT Lhs.0, Lhs.1
        379076853  ~97%    {2}    | JOIN WITH `Class::Class.isConstructedFrom/1#dispred#390e01c8_10#join_rhs` ON FIRST 1 OUTPUT Rhs.1, Lhs.1
        379076853  ~97%    {2}    | JOIN WITH UserType::UserType#21e9e463 ON FIRST 1 OUTPUT Lhs.0, Lhs.1
        379076853  ~97%    {2}    | AND NOT `UserType::UserType.getADeclarationEntry/0#cea44e2f#prev`(FIRST 2)

                0   ~0%    {2} r2 = r1 AND NOT usertypes_0#antijoin_rhs(FIRST 1)
                0   ~0%    {2}    | JOIN WITH type_decls_1#join_rhs ON FIRST 1 OUTPUT Lhs.1, Lhs.0

        379077929  ~95%    {3} r3 = JOIN r1 WITH `ResolveClass::resolveClass/1#ea47deee_10#join_rhs` ON FIRST 1 OUTPUT Rhs.1, Lhs.1, Lhs.0
                0   ~0%    {2}    | JOIN WITH type_decls_1#join_rhs ON FIRST 1 OUTPUT Lhs.1, Lhs.2

                0   ~0%    {2} r4 = r2 UNION r3
                           return r4

Evaluated named local _Class::Class#9afdbffd_Class::Class.isConstructedFrom/1#dispred#390e01c8_10#join_rhs_ResolveClass::r__#antijoin_rhs@L0#7ce3a in 1031ms on iteration 3 (size: 0).
Evaluated relational algebra for predicate _Class::Class#9afdbffd_Class::Class.isConstructedFrom/1#dispred#390e01c8_10#join_rhs_ResolveClass::r__#antijoin_rhs@L0#7ce3a on iteration 3 running pipeline main with tuple counts:
        190114100   ~0%    {2} r1 = JOIN `UserType::UserType.getADeclarationEntry/0#cea44e2f#prev_delta` WITH Class::Class#9afdbffd ON FIRST 1 OUTPUT Lhs.0, Lhs.1
                0   ~0%    {2}    | JOIN WITH `Class::Class.isConstructedFrom/1#dispred#390e01c8_10#join_rhs` ON FIRST 1 OUTPUT Rhs.1, Lhs.1
                0   ~0%    {2}    | JOIN WITH UserType::UserType#21e9e463 ON FIRST 1 OUTPUT Lhs.0, Lhs.1
                0   ~0%    {2}    | AND NOT `UserType::UserType.getADeclarationEntry/0#cea44e2f#prev`(FIRST 2)

                0   ~0%    {2} r2 = r1 AND NOT usertypes_0#antijoin_rhs(FIRST 1)
                0   ~0%    {2}    | JOIN WITH type_decls_1#join_rhs ON FIRST 1 OUTPUT Lhs.1, Lhs.0

                0   ~0%    {3} r3 = JOIN r1 WITH `ResolveClass::resolveClass/1#ea47deee_10#join_rhs` ON FIRST 1 OUTPUT Rhs.1, Lhs.1, Lhs.0
                0   ~0%    {2}    | JOIN WITH type_decls_1#join_rhs ON FIRST 1 OUTPUT Lhs.1, Lhs.2

                0   ~0%    {2} r4 = r2 UNION r3
                           return r4

Pipeline base for UserType::UserType.getADeclarationEntry/0#cea44e2f@7ce3a4hu was evaluated in 1 iterations totaling 149ms (delta sizes total: 224004).
         149171    ~17%    {1} r1 = JOIN type_decls_1#join_rhs WITH `ResolveClass::resolveClass/1#ea47deee` ON FIRST 1 OUTPUT Rhs.1
         125649     ~0%    {1}    | JOIN WITH UserType::UserType#21e9e463 ON FIRST 1 OUTPUT Lhs.0
        1811817  ~1075%    {2}    | JOIN WITH `ResolveClass::resolveClass/1#ea47deee_10#join_rhs` ON FIRST 1 OUTPUT Rhs.1, Lhs.0
        1812281  ~1172%    {2}    | JOIN WITH type_decls_10#join_rhs ON FIRST 1 OUTPUT Lhs.1, Rhs.1
                           return r1

Pipeline standard for UserType::UserType.getADeclarationEntry/0#cea44e2f@7ce3a4hu was evaluated in 1 iterations totaling 22069ms (delta sizes total: 379076853).
           126825  ~32%    {2} r1 = JOIN `UserType::UserType.getADeclarationEntry/0#cea44e2f#prev_delta` WITH Class::Class#9afdbffd ON FIRST 1 OUTPUT Lhs.0, Lhs.1
        379076853  ~97%    {2}    | JOIN WITH `Class::Class.isConstructedFrom/1#dispred#390e01c8_10#join_rhs` ON FIRST 1 OUTPUT Rhs.1, Lhs.1
        379076853  ~97%    {2}    | JOIN WITH UserType::UserType#21e9e463 ON FIRST 1 OUTPUT Lhs.0, Lhs.1
                           {2}    | AND NOT `UserType::UserType.getADeclarationEntry/0#cea44e2f#prev`(FIRST 2)
        379076853  ~96%    {2}    | SCAN OUTPUT In.1, In.0
                           {2}    | AND NOT `_Class::Class#9afdbffd_Class::Class.isConstructedFrom/1#dispred#390e01c8_10#join_rhs_ResolveClass::r__#antijoin_rhs`(FIRST 2)
        379076853  ~97%    {2}    | SCAN OUTPUT In.1, In.0
                           return r1

Pipeline main for _Class::Class#9afdbffd_Class::Class.isConstructedFrom/1#dispred#390e01c8_10#join_rhs_ResolveClass::r__#antijoin_rhs@L0#7ce3a was evaluated in 2 iterations totaling 8490ms (sizes total: 0).
        190240925   ~0%    {2} r1 = JOIN `UserType::UserType.getADeclarationEntry/0#cea44e2f#prev_delta` WITH Class::Class#9afdbffd ON FIRST 1 OUTPUT Lhs.0, Lhs.1
        379076853  ~97%    {2}    | JOIN WITH `Class::Class.isConstructedFrom/1#dispred#390e01c8_10#join_rhs` ON FIRST 1 OUTPUT Rhs.1, Lhs.1
        379076853  ~97%    {2}    | JOIN WITH UserType::UserType#21e9e463 ON FIRST 1 OUTPUT Lhs.0, Lhs.1
        379076853  ~97%    {2}    | AND NOT `UserType::UserType.getADeclarationEntry/0#cea44e2f#prev`(FIRST 2)

                0   ~0%    {2} r2 = r1 AND NOT usertypes_0#antijoin_rhs(FIRST 1)
                0   ~0%    {2}    | JOIN WITH type_decls_1#join_rhs ON FIRST 1 OUTPUT Lhs.1, Lhs.0

        379077929  ~95%    {3} r3 = JOIN r1 WITH `ResolveClass::resolveClass/1#ea47deee_10#join_rhs` ON FIRST 1 OUTPUT Rhs.1, Lhs.1, Lhs.0
                0   ~0%    {2}    | JOIN WITH type_decls_1#join_rhs ON FIRST 1 OUTPUT Lhs.1, Lhs.2

                0   ~0%    {2} r4 = r2 UNION r3
                           return r4
```

After:
```
[2025-01-24 15:22:19] Evaluated non-recursive predicate UserType::UserType.getADeclarationEntryBase/0#dispred#d07c0e9a@82645fgi in 8ms (size: 149661).
Evaluated relational algebra for predicate UserType::UserType.getADeclarationEntryBase/0#dispred#d07c0e9a@82645fgi with tuple counts:
        149661  ~5%    {2} r1 = JOIN `_ResolveClass::resolveClass/1#ea47deee_type_decls#shared` WITH UserType::UserType#21e9e463 ON FIRST 1 OUTPUT Lhs.0, Lhs.1
                       return r1

[2025-01-24 15:22:19] Evaluated non-recursive predicate project#UserType::UserType.getADeclarationEntryBase/0#dispred#d07c0e9a@22da38r1 in 10ms (size: 124540).
Evaluated relational algebra for predicate project#UserType::UserType.getADeclarationEntryBase/0#dispred#d07c0e9a@22da38r1 with tuple counts:
        149661  ~17%    {1} r1 = SCAN `UserType::UserType.getADeclarationEntryBase/0#dispred#d07c0e9a` OUTPUT In.0
        124540   ~0%    {1}    | STREAM DEDUP
                        return r1

[2025-01-24 15:22:20] Evaluated non-recursive predicate Class::Class.isConstructedFrom/1#dispred#390e01c8_10#join_rhs@9c5150lt in 91ms (size: 764244).
Evaluated relational algebra for predicate Class::Class.isConstructedFrom/1#dispred#390e01c8_10#join_rhs@9c5150lt with tuple counts:
        764244  ~2%    {2} r1 = SCAN `Class::Class.isConstructedFrom/1#dispred#390e01c8` OUTPUT In.1, In.0
                       return r1

Evaluated recursive predicate UserType::UserType.getADeclarationEntry/0#cea44e2f#fb@d5a154u4 in 8ms on iteration 1 (delta size: 25561).
Evaluated relational algebra for predicate UserType::UserType.getADeclarationEntry/0#cea44e2f#fb@d5a154u4 on iteration 1 running pipeline base with tuple counts:
        149661  ~2%    {2} r1 = SCAN `UserType::UserType.getADeclarationEntryBase/0#dispred#d07c0e9a` OUTPUT In.1, In.0
         25561  ~6%    {2}    | JOIN WITH type_def ON FIRST 1 OUTPUT Lhs.1, Lhs.0
                       return r1

Evaluated recursive predicate UserType::UserType.getADeclarationEntry/0#cea44e2f#fb@d5a154u4 in 108ms on iteration 2 (delta size: 763236).
Evaluated relational algebra for predicate UserType::UserType.getADeclarationEntry/0#cea44e2f#fb@d5a154u4 on iteration 2 running pipeline standard with tuple counts:
          3655  ~0%    {2} r1 = JOIN `UserType::UserType.getADeclarationEntry/0#cea44e2f#fb#prev_delta` WITH Class::Class#9afdbffd ON FIRST 1 OUTPUT Lhs.0, Lhs.1
        763236  ~1%    {2}    | JOIN WITH `Class::Class.isConstructedFrom/1#dispred#390e01c8_10#join_rhs` ON FIRST 1 OUTPUT Rhs.1, Lhs.1
        763236  ~1%    {2}    | AND NOT `UserType::UserType.getADeclarationEntry/0#cea44e2f#fb#prev`(FIRST 2)
        763236  ~1%    {2}    | AND NOT `project#UserType::UserType.getADeclarationEntryBase/0#dispred#d07c0e9a`(FIRST 1)
                       return r1

Pipeline base for UserType::UserType.getADeclarationEntry/0#cea44e2f#fb@d5a154u4 was evaluated in 1 iterations totaling 8ms (delta sizes total: 25561).
        149661  ~2%    {2} r1 = SCAN `UserType::UserType.getADeclarationEntryBase/0#dispred#d07c0e9a` OUTPUT In.1, In.0
         25561  ~6%    {2}    | JOIN WITH type_def ON FIRST 1 OUTPUT Lhs.1, Lhs.0
                       return r1

Pipeline standard for UserType::UserType.getADeclarationEntry/0#cea44e2f#fb@d5a154u4 was evaluated in 1 iterations totaling 108ms (delta sizes total: 763236).
          3655  ~0%    {2} r1 = JOIN `UserType::UserType.getADeclarationEntry/0#cea44e2f#fb#prev_delta` WITH Class::Class#9afdbffd ON FIRST 1 OUTPUT Lhs.0, Lhs.1
        763236  ~1%    {2}    | JOIN WITH `Class::Class.isConstructedFrom/1#dispred#390e01c8_10#join_rhs` ON FIRST 1 OUTPUT Rhs.1, Lhs.1
        763236  ~1%    {2}    | AND NOT `UserType::UserType.getADeclarationEntry/0#cea44e2f#fb#prev`(FIRST 2)
        763236  ~1%    {2}    | AND NOT `project#UserType::UserType.getADeclarationEntryBase/0#dispred#d07c0e9a`(FIRST 1)
                       return r1
```
  • Loading branch information
jketema committed Jan 24, 2025
1 parent a6cd53e commit 4c256d1
Showing 1 changed file with 8 additions and 3 deletions.
11 changes: 8 additions & 3 deletions cpp/ql/lib/semmle/code/cpp/UserType.qll
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,15 @@ class UserType extends Type, Declaration, NameQualifyingElement, AccessHolder, @
else result = this.getADeclarationLocation()
}

private TypeDeclarationEntry getADeclarationEntryBase() {
type_decls(underlyingElement(result), unresolveElement(this), _)
}

override TypeDeclarationEntry getADeclarationEntry() {
if type_decls(_, unresolveElement(this), _)
then type_decls(underlyingElement(result), unresolveElement(this), _)
else exists(Class t | this.(Class).isConstructedFrom(t) and result = t.getADeclarationEntry())
pragma[only_bind_into](result) = pragma[only_bind_into](this).getADeclarationEntryBase()
or
not exists(this.getADeclarationEntryBase()) and
exists(Class t | this.(Class).isConstructedFrom(t) and result = t.getADeclarationEntry())
}

override Location getADeclarationLocation() { result = this.getADeclarationEntry().getLocation() }
Expand Down

0 comments on commit 4c256d1

Please sign in to comment.