Skip to content

Commit 3de2c7c

Browse files
#128 Improving load times
- Reverting to base 3D graph features if nodes + edges > 4000 - Only performing cycle analysis on 10 biggest cycles. Will make configurable later.
1 parent 8dc5b38 commit 3de2c7c

File tree

3 files changed

+150
-152
lines changed

3 files changed

+150
-152
lines changed

report/src/main/java/org/hjug/refactorfirst/report/HtmlReport.java

Lines changed: 73 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ public class HtmlReport extends SimpleHtmlReport {
124124
+ "</script>";
125125

126126
public static final String FORCE_3D_GRAPH =
127-
"<script type=\"module\">\n" + " // SpriteText will only work as import\n"
127+
"<script type=\"module\">\n" + "// SpriteText will only work as import\n"
128128
+ " // this script block requires type=module since we are using an import\n"
129129
+ " import SpriteText from \"https://esm.sh/three-spritetext\";\n"
130130
+ "\n"
@@ -159,7 +159,7 @@ public class HtmlReport extends SimpleHtmlReport {
159159
+ " source: edge.v,\n"
160160
+ " target: edge.w,\n"
161161
+ " color: graphlibGraph.edge(edge).color || 'white',\n"
162-
+ " weight: graphlibGraph.edge(edge).weight\n"
162+
+ " weight: graphlibGraph.edge(edge).weight,\n"
163163
+ " });\n"
164164
+ " });\n"
165165
+ "\n"
@@ -183,90 +183,86 @@ public class HtmlReport extends SimpleHtmlReport {
183183
+ " b.links.push(link);\n"
184184
+ " });\n"
185185
+ "\n"
186-
+ " const highlightNodes = new Set();\n"
187-
+ " const highlightLinks = new Set();\n"
188-
+ " let hoverNode = null;\n"
189-
+ "\n"
190-
+ " // ForceGraph3D()(container)\n"
191-
+ " // .graphData({ nodes: nodes, links: links })\n"
192-
+ " // .nodeLabel('id')\n"
193-
+ " // .nodeAutoColorBy('color')\n"
194-
+ " // .linkAutoColorBy('color')\n"
195-
+ " // .linkDirectionalArrowLength(3.5)\n"
196-
+ " // .linkDirectionalArrowRelPos(1)\n"
197-
+ " // .width(container.clientWidth)\n"
198-
+ " // .height(container.clientHeight);\n"
199-
+ "\n"
200186
+ " const Graph = new ForceGraph3D(container)\n"
201187
+ " .graphData(gData)\n"
202188
+ " .nodeLabel('id')\n"
203-
+ " // uncomment when adding highlight control GUI\n"
204-
+ " // .nodeColor(node => highlightNodes.has(node) ? node === hoverNode ? 'rgb(255,0,0,1)' : 'rgba(255,160,0,0.8)' : 'rgba(0,255,255,0.6)')\n"
205-
+ " // .linkWidth(link => highlightLinks.has(link) ? 4 : 1)\n"
206-
+ " // .linkDirectionalParticles(link => highlightLinks.has(link) ? 4 : 0)\n"
207-
+ " .linkDirectionalParticleWidth(4)\n"
208189
+ " .width(container.clientWidth)\n"
209-
+ " .height(container.clientHeight)\n"
210-
+ " .nodeThreeObject(node => {\n"
211-
+ " // use node labels instead of spheres\n"
190+
+ " .height(container.clientHeight);\n"
191+
+ "\n"
192+
+ " if(gData.links.length + gData.nodes.length < 4000) {\n"
193+
+ " console.log(gData.links.length + gData.nodes.length);\n"
194+
+ "\n"
195+
+ "\n"
196+
+ " // use node labels instead of spheres\n"
197+
+ " Graph.nodeThreeObject(node => {\n"
212198
+ " const sprite = new SpriteText(node.id);\n"
213199
+ " sprite.material.depthWrite = false; // make sprite background transparent\n"
214200
+ " sprite.color = node.color;\n"
215201
+ " sprite.textHeight = 4;\n"
216202
+ " return sprite;\n"
217-
+ " })\n"
218-
+ " // code to display weight as link text - may be too much for browsers to handle\n"
219-
+ " .linkThreeObjectExtend(true)\n"
220-
+ " .linkThreeObject(link => {\n"
221-
+ " // extend link with text sprite\n"
222-
+ " const sprite = new SpriteText(`${link.weight}`);\n"
223-
+ " sprite.color = 'lightgrey';\n"
224-
+ " sprite.textHeight = 3;\n"
225-
+ " return sprite;\n"
226-
+ " })\n"
227-
+ " .linkPositionUpdate((sprite, { start, end }) => {\n"
228-
+ " const middlePos = Object.assign(...['x', 'y', 'z'].map(c => ({\n"
229-
+ " [c]: start[c] + (end[c] - start[c]) / 2 // calc middle point\n"
230-
+ " })));\n"
203+
+ " });\n"
204+
+ "\n"
205+
+ " // code to display weight as link text\n"
206+
+ " // may be too much for browsers to handle\n"
207+
+ " // Graph\n"
208+
+ " // .linkThreeObjectExtend(true)\n"
209+
+ " // .linkThreeObject(link => {\n"
210+
+ " // // extend link with text sprite\n"
211+
+ " // const sprite = new SpriteText(`${link.weight}`);\n"
212+
+ " // sprite.color = 'lightgrey';\n"
213+
+ " // sprite.textHeight = 3;\n"
214+
+ " // return sprite;\n"
215+
+ " // })\n"
216+
+ " // .linkPositionUpdate((sprite, {start, end}) => {\n"
217+
+ " // const middlePos = Object.assign(...['x', 'y', 'z'].map(c => ({\n"
218+
+ " // [c]: start[c] + (end[c] - start[c]) / 2 // calc middle point\n"
219+
+ " // })));\n"
220+
+ " //\n"
221+
+ " // // Position sprite\n"
222+
+ " // Object.assign(sprite.position, middlePos);\n"
223+
+ " // });\n"
224+
+ "\n"
231225
+ "\n"
232-
+ " // Position sprite\n"
233-
+ " Object.assign(sprite.position, middlePos);\n"
234-
+ " })\n"
235226
+ " // code to highlight nodes & links\n"
236227
+ " // TODO: enable via control - see Manipulate Link Force Distance for example\n"
237-
+ " // .onNodeHover(node => {\n"
238-
+ " // // no state change\n"
239-
+ " // if ((!node && !highlightNodes.size) || (node && hoverNode === node)) return;\n"
240-
+ " //\n"
241-
+ " // highlightNodes.clear();\n"
242-
+ " // highlightLinks.clear();\n"
243-
+ " // if (node) {\n"
244-
+ " // highlightNodes.add(node);\n"
245-
+ " // node.neighbors.forEach(neighbor => highlightNodes.add(neighbor));\n"
246-
+ " // node.links.forEach(link => highlightLinks.add(link));\n"
247-
+ " // }\n"
248-
+ " //\n"
249-
+ " // hoverNode = node || null;\n"
250-
+ " //\n"
251-
+ " // updateHighlight(Graph);\n"
252-
+ " // })\n"
253-
+ " // .onLinkHover(link => {\n"
254-
+ " // highlightNodes.clear();\n"
255-
+ " // highlightLinks.clear();\n"
256-
+ " //\n"
257-
+ " // if (link) {\n"
258-
+ " // highlightLinks.add(link);\n"
259-
+ " // highlightNodes.add(link.source);\n"
260-
+ " // highlightNodes.add(link.target);\n"
261-
+ " // }\n"
262-
+ " //\n"
263-
+ " // updateHighlight(Graph);\n"
264-
+ " // })\n"
265-
+ " ;\n"
228+
+ " const highlightNodes = new Set();\n"
229+
+ " const highlightLinks = new Set();\n"
230+
+ " let hoverNode = null;\n"
231+
+ " Graph\n"
232+
+ " .nodeColor(node => highlightNodes.has(node) ? node === hoverNode ? 'rgb(255,0,0,1)' : 'rgba(255,160,0,0.8)' : 'rgba(0,255,255,0.6)')\n"
233+
+ " .linkWidth(link => highlightLinks.has(link) ? 4 : 1)\n"
234+
+ " .linkDirectionalParticles(link => highlightLinks.has(link) ? 4 : 0)\n"
235+
+ " .linkDirectionalParticleWidth(4)\n"
236+
+ " .onNodeHover(node => {\n"
237+
+ " // no state change\n"
238+
+ " if ((!node && !highlightNodes.size) || (node && hoverNode === node)) return;\n"
266239
+ "\n"
267-
+ " Graph\n"
268-
+ " .d3Force('link')\n"
269-
+ " .distance(link => (1/link.weight) * 200);\n"
240+
+ " highlightNodes.clear();\n"
241+
+ " highlightLinks.clear();\n"
242+
+ " if (node) {\n"
243+
+ " highlightNodes.add(node);\n"
244+
+ " node.neighbors.forEach(neighbor => highlightNodes.add(neighbor));\n"
245+
+ " node.links.forEach(link => highlightLinks.add(link));\n"
246+
+ " }\n"
247+
+ "\n"
248+
+ " hoverNode = node || null;\n"
249+
+ "\n"
250+
+ " updateHighlight(Graph);\n"
251+
+ " })\n"
252+
+ " .onLinkHover(link => {\n"
253+
+ " highlightNodes.clear();\n"
254+
+ " highlightLinks.clear();\n"
255+
+ "\n"
256+
+ " if (link) {\n"
257+
+ " highlightLinks.add(link);\n"
258+
+ " highlightNodes.add(link.source);\n"
259+
+ " highlightNodes.add(link.target);\n"
260+
+ " }\n"
261+
+ "\n"
262+
+ " updateHighlight(Graph);\n"
263+
+ " });\n"
264+
+ "\n"
265+
+ " }\n"
270266
+ " }\n"
271267
+ "\n"
272268
+ " // used by highlighting functionality\n"
@@ -279,7 +275,7 @@ public class HtmlReport extends SimpleHtmlReport {
279275
+ " }\n"
280276
+ "\n"
281277
+ " // needed to allow the button to open the graph\n"
282-
+ " window.createForceGraph = createForceGraph;\n"
278+
+ " window.createForceGraph = createForceGraph;"
283279
+ " </script>";
284280

285281
// Created by generative AI and modified
@@ -527,7 +523,7 @@ public String renderClassGraphDotImage() {
527523
stringBuilder.append("</script>\n");
528524
} else {
529525
// revisit and add D3 SVG popup button
530-
stringBuilder.append("<div align=\"center\">\nMap is too big to render SVG quickly</div>\n");
526+
stringBuilder.append("<div align=\"center\">\nClass Map SVG is too big to render SVG quickly</div>\n");
531527
}
532528

533529
return stringBuilder.toString();
@@ -614,7 +610,8 @@ public String renderCycleDotImage(RankedCycle cycle) {
614610
stringBuilder.append("</script>\n");
615611
} else {
616612
// revisit and add D3 SVG popup button
617-
stringBuilder.append("<div align=\"center\">\nCycle is too big to render SVG quickly</div>\n");
613+
stringBuilder.append(
614+
"<div align=\"center\">\nCycle " + cycleName + " SVG is too big to render SVG quickly</div>\n");
618615
}
619616

620617
stringBuilder.append("<br/>\n");

report/src/main/java/org/hjug/refactorfirst/report/SimpleHtmlReport.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -322,9 +322,10 @@ private String renderCycles(List<RankedCycle> rankedCycles) {
322322

323323
stringBuilder.append("<br/>\n");
324324

325-
for (RankedCycle rankedCycle : rankedCycles) {
326-
stringBuilder.append(renderSingleCycle(rankedCycle));
327-
}
325+
rankedCycles.stream()
326+
.limit(10)
327+
.map(this::renderSingleCycle)
328+
.forEach(stringBuilder::append);
328329

329330
return stringBuilder.toString();
330331
}
@@ -384,6 +385,10 @@ private String renderClassCycleSummary(List<RankedCycle> rankedCycles) {
384385
StringBuilder stringBuilder = new StringBuilder();
385386

386387
stringBuilder.append("<div style=\"text-align: center;\"><a id=\"CYCLES\"><h1>Class Cycles</h1></a></div>\n");
388+
if (rankedCycles.size() > 10) {
389+
stringBuilder.append(
390+
"<div style=\"text-align: center;\">10 largest cycles are shown in the sections below</div>\n");
391+
}
387392

388393
stringBuilder.append("<h2 align=\"center\">Class Cycles by the numbers:</h2>\n");
389394
// stringBuilder.append("<p align=\"center\"><strong>Bold edges are backward edges causing

0 commit comments

Comments
 (0)