Skip to content

Commit 877ddd8

Browse files
static rule optimization by batching
1 parent 0a72191 commit 877ddd8

2 files changed

Lines changed: 58 additions & 6 deletions

File tree

.vscode/launch.json

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,37 @@
5050
"<node_internals>/**"
5151
]
5252
},
53+
{
54+
"type": "java",
55+
"request": "attach",
56+
"name": "Attach to SFGE Java (port 5005)",
57+
"hostName": "localhost",
58+
"port": 5005
59+
},
60+
{
61+
"type": "node",
62+
"request": "launch",
63+
"name": "Debug SFGE Full Flow (single test)",
64+
"cwd": "${workspaceFolder}",
65+
"program": "${workspaceFolder}/node_modules/.bin/jest",
66+
"args": [
67+
"packages/code-analyzer-sfge-engine/test/engine.test.ts",
68+
"-t",
69+
"When only one of several selected rules is violated",
70+
"--runInBand",
71+
"--coverage=false",
72+
"--testTimeout=600000000"
73+
],
74+
"env": {
75+
"NODE_OPTIONS": "--experimental-vm-modules"
76+
},
77+
"console": "integratedTerminal",
78+
"internalConsoleOptions": "neverOpen",
79+
"skipFiles": [
80+
"<node_internals>/**"
81+
],
82+
"timeout": 300000
83+
},
5384
{
5485
"type": "node",
5586
"request": "launch",

packages/code-analyzer-sfge-engine/sfge/src/main/java/com/salesforce/rules/AbstractStaticRule.java

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,41 @@
88
import org.apache.tinkerpop.gremlin.structure.Vertex;
99

1010
public abstract class AbstractStaticRule extends AbstractRule implements StaticRule {
11+
1112
@Override
1213
public final List<Violation> run(GraphTraversalSource g) {
1314
return run(g, new ArrayList<>());
1415
}
1516

17+
/**
18+
* TinkerGraph's .union() operator degrades non-linearly when given thousands of
19+
* sub-traversals. Splitting targets into batches of this size keeps each .union()
20+
* manageable and avoids the performance cliff.
21+
*/
22+
private static final int BATCH_SIZE = 500;
23+
1624
public final List<Violation> run(
1725
GraphTraversalSource g, List<AbstractRuleRunner.RuleRunnerTarget> targets) {
18-
GraphTraversal<Vertex, Vertex> eligibleVertices = buildBaseTraversal(g, targets);
19-
return _run(g, eligibleVertices);
20-
}
26+
if (targets.size() <= BATCH_SIZE) {
27+
GraphTraversal<Vertex, Vertex> eligibleVertices =
28+
TraversalUtil.ruleTargetTraversal(g, targets);
29+
return _run(g, eligibleVertices);
30+
}
2131

22-
private GraphTraversal<Vertex, Vertex> buildBaseTraversal(
23-
GraphTraversalSource g, List<AbstractRuleRunner.RuleRunnerTarget> targets) {
24-
return TraversalUtil.ruleTargetTraversal(g, targets);
32+
int totalBatches = (targets.size() + BATCH_SIZE - 1) / BATCH_SIZE;
33+
List<Violation> allViolations = new ArrayList<>();
34+
35+
for (int batchNum = 0; batchNum < totalBatches; batchNum++) {
36+
int fromIndex = batchNum * BATCH_SIZE;
37+
int toIndex = Math.min(fromIndex + BATCH_SIZE, targets.size());
38+
List<AbstractRuleRunner.RuleRunnerTarget> batch = targets.subList(fromIndex, toIndex);
39+
40+
GraphTraversal<Vertex, Vertex> batchTraversal =
41+
TraversalUtil.ruleTargetTraversal(g, batch);
42+
List<Violation> batchViolations = _run(g, batchTraversal);
43+
allViolations.addAll(batchViolations);
44+
}
45+
return allViolations;
2546
}
2647

2748
/**

0 commit comments

Comments
 (0)