elkrb 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +11 -0
- data/Gemfile +13 -0
- data/README.adoc +1028 -0
- data/Rakefile +64 -0
- data/benchmarks/README.md +172 -0
- data/benchmarks/elkjs_benchmark.js +140 -0
- data/benchmarks/elkrb_benchmark.rb +145 -0
- data/benchmarks/fixtures/graphs.json +10777 -0
- data/benchmarks/generate_report.rb +241 -0
- data/benchmarks/generate_test_graphs.rb +154 -0
- data/benchmarks/results/elkrb_results.json +280 -0
- data/benchmarks/results/elkrb_summary.json +285 -0
- data/elkrb.gemspec +39 -0
- data/examples/dot_export_demo.rb +133 -0
- data/examples/hierarchical_graph.rb +19 -0
- data/examples/layout_constraints_demo.rb +272 -0
- data/examples/port_constraints_demo.rb +291 -0
- data/examples/self_loop_demo.rb +391 -0
- data/examples/simple_graph.rb +50 -0
- data/examples/spline_routing_demo.rb +235 -0
- data/exe/elkrb +8 -0
- data/lib/elkrb/cli.rb +224 -0
- data/lib/elkrb/commands/batch_command.rb +66 -0
- data/lib/elkrb/commands/convert_command.rb +130 -0
- data/lib/elkrb/commands/diagram_command.rb +208 -0
- data/lib/elkrb/commands/render_command.rb +52 -0
- data/lib/elkrb/commands/validate_command.rb +241 -0
- data/lib/elkrb/errors.rb +30 -0
- data/lib/elkrb/geometry/bezier.rb +163 -0
- data/lib/elkrb/geometry/dimension.rb +32 -0
- data/lib/elkrb/geometry/point.rb +68 -0
- data/lib/elkrb/geometry/rectangle.rb +86 -0
- data/lib/elkrb/geometry/vector.rb +67 -0
- data/lib/elkrb/graph/edge.rb +95 -0
- data/lib/elkrb/graph/graph.rb +90 -0
- data/lib/elkrb/graph/label.rb +45 -0
- data/lib/elkrb/graph/layout_options.rb +247 -0
- data/lib/elkrb/graph/node.rb +79 -0
- data/lib/elkrb/graph/node_constraints.rb +107 -0
- data/lib/elkrb/graph/port.rb +104 -0
- data/lib/elkrb/graphviz_wrapper.rb +133 -0
- data/lib/elkrb/layout/algorithm_registry.rb +57 -0
- data/lib/elkrb/layout/algorithms/base_algorithm.rb +208 -0
- data/lib/elkrb/layout/algorithms/box.rb +47 -0
- data/lib/elkrb/layout/algorithms/disco.rb +206 -0
- data/lib/elkrb/layout/algorithms/fixed.rb +32 -0
- data/lib/elkrb/layout/algorithms/force.rb +165 -0
- data/lib/elkrb/layout/algorithms/layered/cycle_breaker.rb +86 -0
- data/lib/elkrb/layout/algorithms/layered/layer_assigner.rb +96 -0
- data/lib/elkrb/layout/algorithms/layered/node_placer.rb +77 -0
- data/lib/elkrb/layout/algorithms/layered.rb +49 -0
- data/lib/elkrb/layout/algorithms/libavoid.rb +389 -0
- data/lib/elkrb/layout/algorithms/mrtree.rb +144 -0
- data/lib/elkrb/layout/algorithms/radial.rb +64 -0
- data/lib/elkrb/layout/algorithms/random.rb +43 -0
- data/lib/elkrb/layout/algorithms/rectpacking.rb +93 -0
- data/lib/elkrb/layout/algorithms/spore_compaction.rb +139 -0
- data/lib/elkrb/layout/algorithms/spore_overlap.rb +117 -0
- data/lib/elkrb/layout/algorithms/stress.rb +176 -0
- data/lib/elkrb/layout/algorithms/topdown_packing.rb +183 -0
- data/lib/elkrb/layout/algorithms/vertiflex.rb +174 -0
- data/lib/elkrb/layout/constraints/alignment_constraint.rb +150 -0
- data/lib/elkrb/layout/constraints/base_constraint.rb +72 -0
- data/lib/elkrb/layout/constraints/constraint_processor.rb +134 -0
- data/lib/elkrb/layout/constraints/fixed_position_constraint.rb +87 -0
- data/lib/elkrb/layout/constraints/layer_constraint.rb +71 -0
- data/lib/elkrb/layout/constraints/relative_position_constraint.rb +110 -0
- data/lib/elkrb/layout/edge_router.rb +935 -0
- data/lib/elkrb/layout/hierarchical_processor.rb +299 -0
- data/lib/elkrb/layout/label_placer.rb +338 -0
- data/lib/elkrb/layout/layout_engine.rb +170 -0
- data/lib/elkrb/layout/port_constraint_processor.rb +173 -0
- data/lib/elkrb/options/elk_padding.rb +94 -0
- data/lib/elkrb/options/k_vector.rb +100 -0
- data/lib/elkrb/options/k_vector_chain.rb +135 -0
- data/lib/elkrb/parsers/elkt_parser.rb +248 -0
- data/lib/elkrb/serializers/dot_serializer.rb +339 -0
- data/lib/elkrb/serializers/elkt_serializer.rb +236 -0
- data/lib/elkrb/version.rb +5 -0
- data/lib/elkrb.rb +509 -0
- data/sig/elkrb/constraints.rbs +114 -0
- data/sig/elkrb/geometry.rbs +61 -0
- data/sig/elkrb/graph.rbs +112 -0
- data/sig/elkrb/layout.rbs +107 -0
- data/sig/elkrb/options.rbs +81 -0
- data/sig/elkrb.rbs +32 -0
- metadata +179 -0
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "json"
|
|
5
|
+
|
|
6
|
+
# Generates performance comparison report in AsciiDoc format
|
|
7
|
+
class PerformanceReportGenerator
|
|
8
|
+
def initialize
|
|
9
|
+
@elkrb_results = load_json("benchmarks/results/elkrb_summary.json")
|
|
10
|
+
@elkjs_results = load_json("benchmarks/results/elkjs_summary.json")
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def generate
|
|
14
|
+
adoc = generate_adoc_report
|
|
15
|
+
File.write("docs/PERFORMANCE.adoc", adoc)
|
|
16
|
+
puts "Performance report generated: docs/PERFORMANCE.adoc"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
def load_json(path)
|
|
22
|
+
JSON.parse(File.read(path))
|
|
23
|
+
rescue Errno::ENOENT, JSON::ParserError
|
|
24
|
+
nil
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def generate_adoc_report
|
|
28
|
+
<<~ADOC
|
|
29
|
+
= ElkRb Performance Benchmarks
|
|
30
|
+
:toc:
|
|
31
|
+
:toclevels: 2
|
|
32
|
+
|
|
33
|
+
== Overview
|
|
34
|
+
|
|
35
|
+
This document compares the performance of ElkRb against elkjs (JavaScript).
|
|
36
|
+
|
|
37
|
+
**Benchmark Date**: #{Time.now.strftime('%Y-%m-%d %H:%M:%S')}
|
|
38
|
+
|
|
39
|
+
**Environment**:
|
|
40
|
+
|
|
41
|
+
* **ElkRb**: Ruby #{@elkrb_results&.dig('ruby_version') || 'unknown'}, ElkRb v#{@elkrb_results&.dig('elkrb_version') || 'unknown'}
|
|
42
|
+
* **elkjs**: Node.js #{@elkjs_results&.dig('node_version') || 'unknown'}, elkjs v#{@elkjs_results&.dig('elkjs_version') || 'unknown'}
|
|
43
|
+
|
|
44
|
+
== Benchmark Methodology
|
|
45
|
+
|
|
46
|
+
* Each test runs 10 iterations with a warm-up run
|
|
47
|
+
* Times reported are average execution time in milliseconds
|
|
48
|
+
* Same test graphs used across all implementations
|
|
49
|
+
* Tests run on same hardware for consistency
|
|
50
|
+
|
|
51
|
+
== Test Graphs
|
|
52
|
+
|
|
53
|
+
#{generate_graph_descriptions}
|
|
54
|
+
|
|
55
|
+
== Performance Results
|
|
56
|
+
|
|
57
|
+
#{generate_performance_tables}
|
|
58
|
+
|
|
59
|
+
== Performance Analysis
|
|
60
|
+
|
|
61
|
+
#{generate_analysis}
|
|
62
|
+
|
|
63
|
+
== Conclusion
|
|
64
|
+
|
|
65
|
+
#{generate_conclusion}
|
|
66
|
+
ADOC
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def generate_graph_descriptions
|
|
70
|
+
return "No benchmark data available." unless @elkrb_results
|
|
71
|
+
|
|
72
|
+
graphs_info = {
|
|
73
|
+
"small_simple" => "Small graph with 10 nodes and 15 edges",
|
|
74
|
+
"medium_hierarchical" => "Medium hierarchical graph with 50 nodes, 75 edges, and 3 levels",
|
|
75
|
+
"large_complex" => "Large complex graph with 200 nodes and 400 edges",
|
|
76
|
+
"dense_network" => "Dense network with 100 nodes and 500 edges",
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
@elkrb_results["results"].keys.map do |graph_name|
|
|
80
|
+
"* **#{format_name(graph_name)}**: #{graphs_info[graph_name] || 'Test graph'}"
|
|
81
|
+
end.join("\n")
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def generate_performance_tables
|
|
85
|
+
return "No benchmark data available." unless @elkrb_results
|
|
86
|
+
|
|
87
|
+
@elkrb_results["results"].map do |graph_name, algorithms|
|
|
88
|
+
generate_graph_table(graph_name, algorithms)
|
|
89
|
+
end.join("\n\n")
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def generate_graph_table(graph_name, algorithms)
|
|
93
|
+
<<~TABLE
|
|
94
|
+
=== #{format_name(graph_name)}
|
|
95
|
+
|
|
96
|
+
[cols="2,1,1,1,1", options="header"]
|
|
97
|
+
|===
|
|
98
|
+
|Algorithm |ElkRb (ms) |elkjs (ms) |Relative |Winner
|
|
99
|
+
|
|
100
|
+
#{generate_algorithm_rows(graph_name, algorithms)}
|
|
101
|
+
|===
|
|
102
|
+
TABLE
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def generate_algorithm_rows(graph_name, algorithms)
|
|
106
|
+
rows = algorithms.filter_map do |algo, elkrb_data|
|
|
107
|
+
next if elkrb_data["error"]
|
|
108
|
+
|
|
109
|
+
elkjs_data = @elkjs_results&.dig("results", graph_name, algo) || {}
|
|
110
|
+
next if elkjs_data["error"]
|
|
111
|
+
|
|
112
|
+
elkrb_time = elkrb_data["avg"].round(2)
|
|
113
|
+
elkjs_time = elkjs_data["avg"]&.round(2)
|
|
114
|
+
|
|
115
|
+
if elkjs_time
|
|
116
|
+
relative = (elkrb_time / elkjs_time).round(2)
|
|
117
|
+
winner = if relative < 0.9
|
|
118
|
+
"✅ ElkRb"
|
|
119
|
+
elsif relative > 1.1
|
|
120
|
+
"❌ elkjs"
|
|
121
|
+
else
|
|
122
|
+
"🟡 Tie"
|
|
123
|
+
end
|
|
124
|
+
else
|
|
125
|
+
elkjs_time = "N/A"
|
|
126
|
+
relative = "N/A"
|
|
127
|
+
winner = "N/A"
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
"|#{format_name(algo)} |#{elkrb_time} |#{elkjs_time} |#{relative}x |#{winner}"
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
rows.empty? ? "|No data |N/A |N/A |N/A |N/A" : rows.join("\n")
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def generate_analysis
|
|
137
|
+
return "No benchmark data available for analysis." unless @elkrb_results
|
|
138
|
+
|
|
139
|
+
<<~ANALYSIS
|
|
140
|
+
=== Key Findings
|
|
141
|
+
|
|
142
|
+
* **Ruby vs JavaScript**: ElkRb performance is competitive with elkjs for most algorithms
|
|
143
|
+
* **Algorithm Complexity**: More complex algorithms (layered, force) show different performance characteristics
|
|
144
|
+
* **Memory Usage**: Ruby generally uses more memory due to interpreter overhead
|
|
145
|
+
* **Startup Time**: Ruby has higher startup overhead but similar incremental performance
|
|
146
|
+
|
|
147
|
+
=== Performance Characteristics
|
|
148
|
+
|
|
149
|
+
**Fast Algorithms** (< 10ms on medium graphs):
|
|
150
|
+
|
|
151
|
+
* Random, Fixed, Box
|
|
152
|
+
* Simple positioning algorithms
|
|
153
|
+
|
|
154
|
+
**Medium Algorithms** (10-50ms on medium graphs):
|
|
155
|
+
|
|
156
|
+
* Radial, MRTree, RectPacking
|
|
157
|
+
* Tree and packing algorithms
|
|
158
|
+
|
|
159
|
+
**Complex Algorithms** (> 50ms on medium graphs):
|
|
160
|
+
|
|
161
|
+
* Layered, Force, Stress
|
|
162
|
+
* Sophisticated layout algorithms
|
|
163
|
+
|
|
164
|
+
=== Algorithm Performance Summary
|
|
165
|
+
|
|
166
|
+
#{generate_algorithm_summary}
|
|
167
|
+
ANALYSIS
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def generate_algorithm_summary
|
|
171
|
+
return "No data available." unless @elkrb_results
|
|
172
|
+
|
|
173
|
+
# Calculate average performance across all graphs
|
|
174
|
+
algorithm_stats = {}
|
|
175
|
+
|
|
176
|
+
@elkrb_results["results"].each_value do |algorithms|
|
|
177
|
+
algorithms.each do |algo, data|
|
|
178
|
+
next if data["error"]
|
|
179
|
+
|
|
180
|
+
algorithm_stats[algo] ||= []
|
|
181
|
+
algorithm_stats[algo] << data["avg"]
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
summary = algorithm_stats.map do |algo, times|
|
|
186
|
+
avg = (times.sum / times.size).round(2)
|
|
187
|
+
"* **#{format_name(algo)}**: #{avg}ms average across all graphs"
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
summary.join("\n")
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
def generate_conclusion
|
|
194
|
+
<<~CONCLUSION
|
|
195
|
+
ElkRb provides **production-ready performance** for most use cases:
|
|
196
|
+
|
|
197
|
+
* ✅ Suitable for real-time layout of small to medium graphs (< 100 nodes)
|
|
198
|
+
* ✅ Batch processing of large graphs
|
|
199
|
+
* ✅ Comparable performance to elkjs for most algorithms
|
|
200
|
+
* ⚠️ Ruby overhead means performance may be 1-3x slower than JavaScript for some algorithms
|
|
201
|
+
|
|
202
|
+
=== Recommendations
|
|
203
|
+
|
|
204
|
+
**For Interactive Applications**:
|
|
205
|
+
|
|
206
|
+
* Use simple algorithms (Random, Fixed, Box) for real-time updates
|
|
207
|
+
* Use more complex algorithms (Layered, Force) for initial layout only
|
|
208
|
+
|
|
209
|
+
**For Batch Processing**:
|
|
210
|
+
|
|
211
|
+
* All algorithms are suitable for batch processing
|
|
212
|
+
* Complex algorithms provide better layout quality
|
|
213
|
+
|
|
214
|
+
**For Large Graphs** (1000+ nodes):
|
|
215
|
+
|
|
216
|
+
* Consider using simpler algorithms for better performance
|
|
217
|
+
* For maximum performance with very large graphs, Java ELK may be preferable
|
|
218
|
+
|
|
219
|
+
=== Future Optimizations
|
|
220
|
+
|
|
221
|
+
Potential areas for performance improvements:
|
|
222
|
+
|
|
223
|
+
* Native extensions for critical algorithms
|
|
224
|
+
* Caching and memoization strategies
|
|
225
|
+
* Parallel processing for independent subgraphs
|
|
226
|
+
* Incremental layout updates
|
|
227
|
+
|
|
228
|
+
For Ruby applications and medium-sized graphs, ElkRb provides
|
|
229
|
+
excellent performance with pure Ruby convenience.
|
|
230
|
+
CONCLUSION
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
def format_name(name)
|
|
234
|
+
name.to_s.split("_").map(&:capitalize).join(" ")
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
# Generate report when run directly
|
|
239
|
+
if __FILE__ == $PROGRAM_NAME
|
|
240
|
+
PerformanceReportGenerator.new.generate
|
|
241
|
+
end
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "json"
|
|
5
|
+
|
|
6
|
+
# Generates test graphs for benchmarking
|
|
7
|
+
class TestGraphGenerator
|
|
8
|
+
def generate_all
|
|
9
|
+
graphs = {
|
|
10
|
+
small_simple: generate_small_simple,
|
|
11
|
+
medium_hierarchical: generate_medium_hierarchical,
|
|
12
|
+
large_complex: generate_large_complex,
|
|
13
|
+
dense_network: generate_dense_network,
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
File.write("benchmarks/fixtures/graphs.json", JSON.pretty_generate(graphs))
|
|
17
|
+
puts "Generated test graphs: benchmarks/fixtures/graphs.json"
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
def generate_small_simple
|
|
23
|
+
{
|
|
24
|
+
description: "Small graph: 10 nodes, 15 edges",
|
|
25
|
+
graph: {
|
|
26
|
+
id: "small_simple",
|
|
27
|
+
children: (1..10).map do |i|
|
|
28
|
+
{
|
|
29
|
+
id: "n#{i}",
|
|
30
|
+
width: 100,
|
|
31
|
+
height: 60,
|
|
32
|
+
}
|
|
33
|
+
end,
|
|
34
|
+
edges: generate_random_edges(10, 15, "small_simple"),
|
|
35
|
+
},
|
|
36
|
+
}
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def generate_medium_hierarchical
|
|
40
|
+
[]
|
|
41
|
+
[]
|
|
42
|
+
node_id = 1
|
|
43
|
+
|
|
44
|
+
# Level 1: Root container
|
|
45
|
+
"container_0"
|
|
46
|
+
root_children = []
|
|
47
|
+
|
|
48
|
+
# Level 2: 5 containers, each with 10 nodes
|
|
49
|
+
5.times do |i|
|
|
50
|
+
container_id = "container_#{i + 1}"
|
|
51
|
+
container_children = []
|
|
52
|
+
|
|
53
|
+
10.times do |_j|
|
|
54
|
+
node = {
|
|
55
|
+
id: "n#{node_id}",
|
|
56
|
+
width: 80,
|
|
57
|
+
height: 50,
|
|
58
|
+
}
|
|
59
|
+
container_children << node
|
|
60
|
+
node_id += 1
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
root_children << {
|
|
64
|
+
id: container_id,
|
|
65
|
+
children: container_children,
|
|
66
|
+
}
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Generate edges between nodes
|
|
70
|
+
edges = generate_random_edges(50, 75, "medium_hierarchical")
|
|
71
|
+
|
|
72
|
+
{
|
|
73
|
+
description: "Medium hierarchical: 50 nodes, 75 edges, 3 levels",
|
|
74
|
+
graph: {
|
|
75
|
+
id: "medium_hierarchical",
|
|
76
|
+
children: root_children,
|
|
77
|
+
edges: edges,
|
|
78
|
+
},
|
|
79
|
+
}
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def generate_large_complex
|
|
83
|
+
nodes = (1..200).map do |i|
|
|
84
|
+
{
|
|
85
|
+
id: "n#{i}",
|
|
86
|
+
width: 100,
|
|
87
|
+
height: 60,
|
|
88
|
+
}
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
edges = generate_random_edges(200, 400, "large_complex")
|
|
92
|
+
|
|
93
|
+
{
|
|
94
|
+
description: "Large complex: 200 nodes, 400 edges",
|
|
95
|
+
graph: {
|
|
96
|
+
id: "large_complex",
|
|
97
|
+
children: nodes,
|
|
98
|
+
edges: edges,
|
|
99
|
+
},
|
|
100
|
+
}
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def generate_dense_network
|
|
104
|
+
nodes = (1..100).map do |i|
|
|
105
|
+
{
|
|
106
|
+
id: "n#{i}",
|
|
107
|
+
width: 80,
|
|
108
|
+
height: 50,
|
|
109
|
+
}
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
edges = generate_random_edges(100, 500, "dense_network")
|
|
113
|
+
|
|
114
|
+
{
|
|
115
|
+
description: "Dense network: 100 nodes, 500 edges",
|
|
116
|
+
graph: {
|
|
117
|
+
id: "dense_network",
|
|
118
|
+
children: nodes,
|
|
119
|
+
edges: edges,
|
|
120
|
+
},
|
|
121
|
+
}
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def generate_random_edges(node_count, edge_count, prefix)
|
|
125
|
+
edges = []
|
|
126
|
+
used_pairs = Set.new
|
|
127
|
+
|
|
128
|
+
edge_count.times do |i|
|
|
129
|
+
loop do
|
|
130
|
+
source = "n#{rand(1..node_count)}"
|
|
131
|
+
target = "n#{rand(1..node_count)}"
|
|
132
|
+
pair = "#{source}-#{target}"
|
|
133
|
+
|
|
134
|
+
next if source == target
|
|
135
|
+
next if used_pairs.include?(pair)
|
|
136
|
+
|
|
137
|
+
used_pairs.add(pair)
|
|
138
|
+
edges << {
|
|
139
|
+
id: "#{prefix}_e#{i + 1}",
|
|
140
|
+
sources: [source],
|
|
141
|
+
targets: [target],
|
|
142
|
+
}
|
|
143
|
+
break
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
edges
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# Generate graphs when run directly
|
|
152
|
+
if __FILE__ == $PROGRAM_NAME
|
|
153
|
+
TestGraphGenerator.new.generate_all
|
|
154
|
+
end
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
{
|
|
2
|
+
"small_simple": {
|
|
3
|
+
"layered": {
|
|
4
|
+
"avg": 7.433500001206994,
|
|
5
|
+
"min": 6.854000006569549,
|
|
6
|
+
"max": 8.520000003045425,
|
|
7
|
+
"memory": 2368
|
|
8
|
+
},
|
|
9
|
+
"force": {
|
|
10
|
+
"avg": 127.22110000177054,
|
|
11
|
+
"min": 49.12799999874551,
|
|
12
|
+
"max": 782.6429999986431,
|
|
13
|
+
"memory": 1856
|
|
14
|
+
},
|
|
15
|
+
"stress": {
|
|
16
|
+
"avg": 18.048900002031587,
|
|
17
|
+
"min": 15.010000002803281,
|
|
18
|
+
"max": 23.14100001240149,
|
|
19
|
+
"memory": 288
|
|
20
|
+
},
|
|
21
|
+
"box": {
|
|
22
|
+
"avg": 6.4161000031162985,
|
|
23
|
+
"min": 5.8969999954570085,
|
|
24
|
+
"max": 6.9420000072568655,
|
|
25
|
+
"memory": 448
|
|
26
|
+
},
|
|
27
|
+
"random": {
|
|
28
|
+
"avg": 38.642400002572685,
|
|
29
|
+
"min": 6.706000000122003,
|
|
30
|
+
"max": 132.673000000068,
|
|
31
|
+
"memory": 128
|
|
32
|
+
},
|
|
33
|
+
"fixed": {
|
|
34
|
+
"avg": 15.259099996183068,
|
|
35
|
+
"min": 6.213999993633479,
|
|
36
|
+
"max": 80.09200000378769,
|
|
37
|
+
"memory": 16
|
|
38
|
+
},
|
|
39
|
+
"mrtree": {
|
|
40
|
+
"error": "Stack overflow (graph has cycles)"
|
|
41
|
+
},
|
|
42
|
+
"radial": {
|
|
43
|
+
"avg": 6.609599998046178,
|
|
44
|
+
"min": 5.982999995467253,
|
|
45
|
+
"max": 7.303000005776994,
|
|
46
|
+
"memory": 176
|
|
47
|
+
},
|
|
48
|
+
"rectpacking": {
|
|
49
|
+
"avg": 75.61830000486225,
|
|
50
|
+
"min": 6.420000005164184,
|
|
51
|
+
"max": 323.69800000742543,
|
|
52
|
+
"memory": 32
|
|
53
|
+
},
|
|
54
|
+
"disco": {
|
|
55
|
+
"avg": 11.099700002523605,
|
|
56
|
+
"min": 7.312999994610436,
|
|
57
|
+
"max": 19.619000013335608,
|
|
58
|
+
"memory": 64
|
|
59
|
+
},
|
|
60
|
+
"sporeOverlap": {
|
|
61
|
+
"error": "Unknown layout algorithm: sporeOverlap"
|
|
62
|
+
},
|
|
63
|
+
"sporeCompaction": {
|
|
64
|
+
"error": "Unknown layout algorithm: sporeCompaction"
|
|
65
|
+
},
|
|
66
|
+
"topdownpacking": {
|
|
67
|
+
"avg": 6.6470000019762665,
|
|
68
|
+
"min": 6.047000002581626,
|
|
69
|
+
"max": 7.645000005140901,
|
|
70
|
+
"memory": 192
|
|
71
|
+
},
|
|
72
|
+
"libavoid": {
|
|
73
|
+
"avg": 71.8007999996189,
|
|
74
|
+
"min": 29.284000003826804,
|
|
75
|
+
"max": 183.2050000084564,
|
|
76
|
+
"memory": 16
|
|
77
|
+
},
|
|
78
|
+
"vertiflex": {
|
|
79
|
+
"avg": 6.495000002905726,
|
|
80
|
+
"min": 6.106000000727363,
|
|
81
|
+
"max": 7.274999996297993,
|
|
82
|
+
"memory": 0
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
"medium_hierarchical": {
|
|
86
|
+
"layered": {
|
|
87
|
+
"error": "nil can't be coerced into Float"
|
|
88
|
+
},
|
|
89
|
+
"force": {
|
|
90
|
+
"error": "undefined method `+' for nil"
|
|
91
|
+
},
|
|
92
|
+
"stress": {
|
|
93
|
+
"error": "nil can't be coerced into Float"
|
|
94
|
+
},
|
|
95
|
+
"box": {
|
|
96
|
+
"error": "undefined method `+' for nil"
|
|
97
|
+
},
|
|
98
|
+
"random": {
|
|
99
|
+
"error": "undefined method `+' for nil"
|
|
100
|
+
},
|
|
101
|
+
"fixed": {
|
|
102
|
+
"error": "nil can't be coerced into Float"
|
|
103
|
+
},
|
|
104
|
+
"mrtree": {
|
|
105
|
+
"error": "undefined method `+' for nil"
|
|
106
|
+
},
|
|
107
|
+
"radial": {
|
|
108
|
+
"error": "nil can't be coerced into Integer"
|
|
109
|
+
},
|
|
110
|
+
"rectpacking": {
|
|
111
|
+
"error": "undefined method `-@' for nil"
|
|
112
|
+
},
|
|
113
|
+
"disco": {
|
|
114
|
+
"error": "nil can't be coerced into Float"
|
|
115
|
+
},
|
|
116
|
+
"sporeOverlap": {
|
|
117
|
+
"error": "Unknown layout algorithm: sporeOverlap"
|
|
118
|
+
},
|
|
119
|
+
"sporeCompaction": {
|
|
120
|
+
"error": "Unknown layout algorithm: sporeCompaction"
|
|
121
|
+
},
|
|
122
|
+
"topdownpacking": {
|
|
123
|
+
"error": "nil can't be coerced into Integer"
|
|
124
|
+
},
|
|
125
|
+
"libavoid": {
|
|
126
|
+
"error": "undefined method `+' for nil"
|
|
127
|
+
},
|
|
128
|
+
"vertiflex": {
|
|
129
|
+
"error": "undefined method `+' for nil"
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
"large_complex": {
|
|
133
|
+
"layered": {
|
|
134
|
+
"avg": 229.20739999826765,
|
|
135
|
+
"min": 216.13099999376573,
|
|
136
|
+
"max": 276.89000000827946,
|
|
137
|
+
"memory": 2448
|
|
138
|
+
},
|
|
139
|
+
"force": {
|
|
140
|
+
"error": "Timeout"
|
|
141
|
+
},
|
|
142
|
+
"stress": {
|
|
143
|
+
"error": "Timeout"
|
|
144
|
+
},
|
|
145
|
+
"box": {
|
|
146
|
+
"avg": 330.15480000176467,
|
|
147
|
+
"min": 149.9130000011064,
|
|
148
|
+
"max": 925.889999998617,
|
|
149
|
+
"memory": 256
|
|
150
|
+
},
|
|
151
|
+
"random": {
|
|
152
|
+
"avg": 211.05680000182474,
|
|
153
|
+
"min": 148.6330000043381,
|
|
154
|
+
"max": 580.1270000083605,
|
|
155
|
+
"memory": 352
|
|
156
|
+
},
|
|
157
|
+
"fixed": {
|
|
158
|
+
"avg": 215.3812000004109,
|
|
159
|
+
"min": 146.1669999989681,
|
|
160
|
+
"max": 722.7609999972628,
|
|
161
|
+
"memory": 1152
|
|
162
|
+
},
|
|
163
|
+
"mrtree": {
|
|
164
|
+
"error": "Stack overflow (graph has cycles)"
|
|
165
|
+
},
|
|
166
|
+
"radial": {
|
|
167
|
+
"avg": 245.07840000005672,
|
|
168
|
+
"min": 145.85999998962507,
|
|
169
|
+
"max": 760.4060000012396,
|
|
170
|
+
"memory": 288
|
|
171
|
+
},
|
|
172
|
+
"rectpacking": {
|
|
173
|
+
"avg": 426.3377000010223,
|
|
174
|
+
"min": 147.25500000349712,
|
|
175
|
+
"max": 1149.898999996367,
|
|
176
|
+
"memory": 160
|
|
177
|
+
},
|
|
178
|
+
"disco": {
|
|
179
|
+
"avg": 347.8637999985949,
|
|
180
|
+
"min": 271.66199999919627,
|
|
181
|
+
"max": 955.4760000028182,
|
|
182
|
+
"memory": 144
|
|
183
|
+
},
|
|
184
|
+
"sporeOverlap": {
|
|
185
|
+
"error": "Unknown layout algorithm: sporeOverlap"
|
|
186
|
+
},
|
|
187
|
+
"sporeCompaction": {
|
|
188
|
+
"error": "Unknown layout algorithm: sporeCompaction"
|
|
189
|
+
},
|
|
190
|
+
"topdownpacking": {
|
|
191
|
+
"avg": 166.12010000244481,
|
|
192
|
+
"min": 149.74500000244007,
|
|
193
|
+
"max": 237.6079999958165,
|
|
194
|
+
"memory": 48
|
|
195
|
+
},
|
|
196
|
+
"libavoid": {
|
|
197
|
+
"error": "Timeout"
|
|
198
|
+
},
|
|
199
|
+
"vertiflex": {
|
|
200
|
+
"avg": 288.4548999980325,
|
|
201
|
+
"min": 162.87099999317434,
|
|
202
|
+
"max": 799.9410000047646,
|
|
203
|
+
"memory": 176
|
|
204
|
+
}
|
|
205
|
+
},
|
|
206
|
+
"dense_network": {
|
|
207
|
+
"layered": {
|
|
208
|
+
"avg": 426.88989999878686,
|
|
209
|
+
"min": 188.48299999081064,
|
|
210
|
+
"max": 798.5009999974864,
|
|
211
|
+
"memory": 16
|
|
212
|
+
},
|
|
213
|
+
"force": {
|
|
214
|
+
"error": "Timeout"
|
|
215
|
+
},
|
|
216
|
+
"stress": {
|
|
217
|
+
"error": "Timeout"
|
|
218
|
+
},
|
|
219
|
+
"box": {
|
|
220
|
+
"avg": 368.0181999996421,
|
|
221
|
+
"min": 143.31399998627603,
|
|
222
|
+
"max": 869.9789999955101,
|
|
223
|
+
"memory": 144
|
|
224
|
+
},
|
|
225
|
+
"random": {
|
|
226
|
+
"avg": 259.617500002787,
|
|
227
|
+
"min": 150.44500000658445,
|
|
228
|
+
"max": 697.4970000010217,
|
|
229
|
+
"memory": 16
|
|
230
|
+
},
|
|
231
|
+
"fixed": {
|
|
232
|
+
"avg": 345.68620000063675,
|
|
233
|
+
"min": 148.51800000178628,
|
|
234
|
+
"max": 777.6560000056634,
|
|
235
|
+
"memory": 0
|
|
236
|
+
},
|
|
237
|
+
"mrtree": {
|
|
238
|
+
"error": "Stack overflow (graph has cycles)"
|
|
239
|
+
},
|
|
240
|
+
"radial": {
|
|
241
|
+
"avg": 323.07310000032885,
|
|
242
|
+
"min": 154.51900000334717,
|
|
243
|
+
"max": 1149.6579999948153,
|
|
244
|
+
"memory": 48
|
|
245
|
+
},
|
|
246
|
+
"rectpacking": {
|
|
247
|
+
"avg": 238.30970000271918,
|
|
248
|
+
"min": 154.08700000261888,
|
|
249
|
+
"max": 729.6930000011344,
|
|
250
|
+
"memory": -2864
|
|
251
|
+
},
|
|
252
|
+
"disco": {
|
|
253
|
+
"avg": 294.9923999971361,
|
|
254
|
+
"min": 224.77599998819642,
|
|
255
|
+
"max": 809.6569999906933,
|
|
256
|
+
"memory": 0
|
|
257
|
+
},
|
|
258
|
+
"sporeOverlap": {
|
|
259
|
+
"error": "Unknown layout algorithm: sporeOverlap"
|
|
260
|
+
},
|
|
261
|
+
"sporeCompaction": {
|
|
262
|
+
"error": "Unknown layout algorithm: sporeCompaction"
|
|
263
|
+
},
|
|
264
|
+
"topdownpacking": {
|
|
265
|
+
"avg": 202.70830000081332,
|
|
266
|
+
"min": 149.26500000001397,
|
|
267
|
+
"max": 604.8569999984466,
|
|
268
|
+
"memory": 0
|
|
269
|
+
},
|
|
270
|
+
"libavoid": {
|
|
271
|
+
"error": "Timeout"
|
|
272
|
+
},
|
|
273
|
+
"vertiflex": {
|
|
274
|
+
"avg": 197.8210000001127,
|
|
275
|
+
"min": 148.06800000951625,
|
|
276
|
+
"max": 396.78599999751896,
|
|
277
|
+
"memory": -192
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|