Skip to content

Commit d4fc096

Browse files
authored
Python: Use local flow in Pythagorean.ql
The hand-rolled notion of flow was causing some severe performance issues (on a few databases): ``` Tuple counts for Pythagorean::square#168e234a#f#loop_invariant_prefix/2@c86989kr after 6m35s: 175000 ~5% {2} r1 = JOIN SSA::SsaVariable::getDefinition#dispred#f0820431#ff_10#join_rhs WITH Flow::ControlFlowNode::getNode#dispred#f0820431#bf ON FIRST 1 OUTPUT Lhs.1, Rhs.1 'arg0' 174500 ~6% {2} r2 = JOIN r1 WITH SSA::SsaVariable::getVariable#dispred#f0820431#ff ON FIRST 1 OUTPUT Rhs.1, Lhs.1 'arg0' 1467782500 ~5% {3} r3 = JOIN r2 WITH AstGenerated::Name_::getVariable#dispred#f0820431#ff_10#join_rhs ON FIRST 1 OUTPUT 3, Rhs.1 'arg1', Lhs.1 'arg0' 1467553000 ~0% {2} r4 = JOIN r3 WITH py_expr_contexts_12#join_rhs ON FIRST 2 OUTPUT Lhs.2 'arg0', Lhs.1 'arg1' return r4 ``` Rewriting it to use the data flow library made all of this go away. 🎉
1 parent b2cc913 commit d4fc096

File tree

1 file changed

+17
-23
lines changed

1 file changed

+17
-23
lines changed

python/ql/src/Numerics/Pythagorean.ql

Lines changed: 17 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,36 +10,30 @@
1010
*/
1111

1212
import python
13+
import semmle.python.dataflow.new.DataFlow
14+
import semmle.python.ApiGraphs
1315

14-
predicate squareOp(BinaryExpr e) {
15-
e.getOp() instanceof Pow and e.getRight().(IntegerLiteral).getN() = "2"
16-
}
17-
18-
predicate squareMul(BinaryExpr e) {
19-
e.getOp() instanceof Mult and e.getRight().(Name).getId() = e.getLeft().(Name).getId()
16+
DataFlow::ExprNode squareOp() {
17+
exists(BinaryExpr e | e = result.asExpr() |
18+
e.getOp() instanceof Pow and e.getRight().(IntegerLiteral).getN() = "2"
19+
)
2020
}
2121

22-
predicate squareRef(Name e) {
23-
e.isUse() and
24-
exists(SsaVariable v, Expr s | v.getVariable() = e.getVariable() |
25-
s = v.getDefinition().getNode().getParentNode().(AssignStmt).getValue() and
26-
square(s)
22+
DataFlow::ExprNode squareMul() {
23+
exists(BinaryExpr e | e = result.asExpr() |
24+
e.getOp() instanceof Mult and e.getRight().(Name).getId() = e.getLeft().(Name).getId()
2725
)
2826
}
2927

30-
predicate square(Expr e) {
31-
squareOp(e)
32-
or
33-
squareMul(e)
34-
or
35-
squareRef(e)
36-
}
28+
DataFlow::ExprNode square() { result in [squareOp(), squareMul()] }
3729

38-
from Call c, BinaryExpr s
30+
from DataFlow::CallCfgNode c, BinaryExpr s, DataFlow::ExprNode left, DataFlow::ExprNode right
3931
where
40-
c.getFunc().toString() = "sqrt" and
41-
c.getArg(0) = s and
32+
c = API::moduleImport("math").getMember("sqrt").getACall() and
33+
c.getArg(0).asExpr() = s and
4234
s.getOp() instanceof Add and
43-
square(s.getLeft()) and
44-
square(s.getRight())
35+
left.asExpr() = s.getLeft() and
36+
right.asExpr() = s.getRight() and
37+
left.getALocalSource() = square() and
38+
right.getALocalSource() = square()
4539
select c, "Pythagorean calculation with sub-optimal numerics"

0 commit comments

Comments
 (0)