Reputation: 3684
If I clone a layout configuration with Object.assign
and try to use that layout, cytoscape quickly causes an out of memory error. I can work around this by just defining a second layout mostly identical to the first and not cloning, but I am interested to know the reason behind the problem, or if it's a possible bug in cytoscape.
With this example code, click add and layout 2
right after loading the page and it will hang/run out of memory. (Have your task manager handy to kill your tab or browser.) Different combinations of adding nodes and running the cloned layout will mostly hang, but not always.
let cy
const layout1 = {
name: 'euler',
springLength: edge => 80,
mass: node => 4,
randomize: true,
animate: false,
gravity: -1.2,
maxIterations: 1000,
maxSimulationTime: 4000,
}
const layout2 = Object.assign({}, layout1, {
fit: false,
animate: true,
randomize: false,
})
document.addEventListener('DOMContentLoaded', function() {
cy = cytoscape({
container: document.getElementById('cy'),
layout: layout1,
style: [
{
selector: 'node',
style: {
label: 'data(id)',
},
},
],
elements: [
{ data: { id: 'a' } },
{ data: { id: 'b' } },
{ data: { id: 'a_b', source: 'a', target: 'b' } },
],
})
})
function add() {
cy.add([
{ data: { id: 'c' } },
{ data: { id: 'd' } },
{ data: { id: 'c_d', source: 'c', target: 'd' } },
])
// cy.layout(layout2).run()
}
function doLayout1() {
cy.layout(layout1).run()
}
function doLayout2() {
cy.layout(layout2).run()
}
function addAndLayout2() {
add()
doLayout2()
}
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/cytoscape/3.5.0/cytoscape.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/cytoscape-euler.min.js"></script>
</head>
<style>
body {
height: 100%;
}
#cy {
height: 100%;
flex-grow: 1;
}
.main {
height: 100vh;
display: flex;
flex: 1;
}
</style>
<body>
<button onclick="add()">add nodes</button>
<button onclick="doLayout1()">layout 1</button>
<button onclick="doLayout2()">layout 2</button>
<button onclick="addAndLayout2()">add and layout 2</button>
<div class="main">
<div id="cy"></div>
</div>
</body>
</html>
Upvotes: 0
Views: 613
Reputation: 1065
This has nothing to do with Ojbect.assign
(even if you did not copy the object properly, it should not hang).
The reason is the randomize
option. For this particular graph, when the randomize option is set to false
, the layout never ends. Just remove randomize: false
from the second layout, or after adding the new nodes and before running layout2
, run the random
layout (or just randomize the nodes manually) -- the layout2
will terminate.
The problem is that: the layout must terminate at some point (in the worst case when the umber of max iterations is reached). But this particular layout never terminates.
The interesting thing is that this simple graph turns out to be one of the worst cases for some other layout algorithms as well (for randomized: false
). I tried cose-bilkent
. It also takes a little bit longer and terminates when the maximum number of iterations is reached (setting numIter
option to lower number will result in early termination, worse quality) -- but the result is really bad.
Upvotes: 1