Skip to content

Commit d123e5b

Browse files
committed
Ruby: add performance diagnostic query
1 parent bb521d7 commit d123e5b

File tree

1 file changed

+116
-0
lines changed

1 file changed

+116
-0
lines changed
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
/**
2+
* @kind table
3+
*/
4+
5+
/*
6+
* This query outputs some numbers that can be used to help narrow down the cause of performance
7+
* issues in a codebase, without leaking any actual code or identifiers from the codebase.
8+
*/
9+
10+
import ruby
11+
import codeql.ruby.ApiGraphs
12+
13+
query int numberOfModuleBases() { result = count(Ast::ModuleBase cls) }
14+
15+
query int numberOfClasses() { result = count(Ast::ClassDeclaration cls) }
16+
17+
query int numberOfMethods() { result = count(Ast::MethodBase method) }
18+
19+
query int numberOfCallables() { result = count(Ast::Callable c) }
20+
21+
query int numberOfMethodCalls() { result = count(Ast::MethodCall call) }
22+
23+
query int numberOfCalls() { result = count(Ast::Call call) }
24+
25+
signature module HistogramSig {
26+
bindingset[this]
27+
class Bucket;
28+
29+
int getCounts(Bucket bucket);
30+
}
31+
32+
module MakeHistogram<HistogramSig H> {
33+
predicate histogram(int bucketSize, int frequency) {
34+
frequency = strictcount(H::Bucket bucket | H::getCounts(bucket) = bucketSize)
35+
}
36+
}
37+
38+
module MethodNames implements HistogramSig {
39+
class Bucket = string;
40+
41+
int getCounts(string name) {
42+
result = strictcount(Ast::MethodBase method | method.getName() = name) and
43+
name != "initialize"
44+
}
45+
}
46+
47+
query predicate numberOfMethodsWithNameHistogram = MakeHistogram<MethodNames>::histogram/2;
48+
49+
module CallTargets implements HistogramSig {
50+
class Bucket = Ast::Call;
51+
52+
int getCounts(Ast::Call call) { result = count(call.getATarget()) }
53+
}
54+
55+
query predicate numberOfCallTargetsHistogram = MakeHistogram<CallTargets>::histogram/2;
56+
57+
module Callers implements HistogramSig {
58+
class Bucket = Ast::Callable;
59+
60+
int getCounts(Ast::Callable callable) {
61+
result = count(Ast::Call call | call.getATarget() = callable)
62+
}
63+
}
64+
65+
query predicate numberOfCallersHistogram = MakeHistogram<Callers>::histogram/2;
66+
67+
private DataFlow::MethodNode getAnOverriddenMethod(DataFlow::MethodNode method) {
68+
exists(DataFlow::ModuleNode cls, string name |
69+
method = cls.getInstanceMethod(name) and
70+
result = cls.getAnAncestor().getInstanceMethod(name) and
71+
result != method
72+
)
73+
}
74+
75+
module MethodOverrides implements HistogramSig {
76+
class Bucket = DataFlow::MethodNode;
77+
78+
int getCounts(DataFlow::MethodNode method) { result = count(getAnOverriddenMethod(method)) }
79+
}
80+
81+
query predicate numberOfOverriddenMethodsHistogram = MakeHistogram<MethodOverrides>::histogram/2;
82+
83+
module MethodOverridenBy implements HistogramSig {
84+
class Bucket = DataFlow::MethodNode;
85+
86+
int getCounts(DataFlow::MethodNode method) {
87+
result = count(DataFlow::MethodNode overrider | method = getAnOverriddenMethod(overrider))
88+
}
89+
}
90+
91+
query predicate numberOfOverridingMethodsHistogram = MakeHistogram<MethodOverridenBy>::histogram/2;
92+
93+
module Ancestors implements HistogramSig {
94+
class Bucket = DataFlow::ModuleNode;
95+
96+
int getCounts(DataFlow::ModuleNode mod) {
97+
result =
98+
count(DataFlow::ModuleNode ancestor | ancestor = mod.getAnAncestor() and ancestor != mod)
99+
}
100+
}
101+
102+
query predicate numberOfAncestorsHistogram = MakeHistogram<Ancestors>::histogram/2;
103+
104+
module Descendents implements HistogramSig {
105+
class Bucket = DataFlow::ModuleNode;
106+
107+
int getCounts(DataFlow::ModuleNode mod) {
108+
not mod.getQualifiedName() = ["Object", "Kernel", "BasicObject", "Class", "Module"] and
109+
result =
110+
count(DataFlow::ModuleNode descendent |
111+
descendent = mod.getADescendent() and descendent != mod
112+
)
113+
}
114+
}
115+
116+
query predicate numberOfDescendentsHistogram = MakeHistogram<Descendents>::histogram/2;

0 commit comments

Comments
 (0)