New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Visualisation library #3

Closed
jonathanKingston opened this Issue May 9, 2017 · 7 comments

Comments

Projects
None yet
3 participants
@jonathanKingston
Member

jonathanKingston commented May 9, 2017

A decision needs to be made about how visualisations are made. It is clear the current Lightbeam has performance issues that need to be resolved on the rewrite.
Currently we are using SVG, we should probably look to a canvas or WebGL option.

I would suggest whatever is decided on for the library, we should communicate to a object that does the drawing rather than directly calling the library.

chartInstance.addNodes({
    hosts: [
      {hostname: "blah.com", favicon: "blob...."},
      {hostname: "google.com"},
      {hostname: "me.com"}
    ],
    links: [
      {firstParty: "blah.com", thirdParty: "google.com"},
      {firstParty: "me.com", thirdParty: "google.com"}
    ]
  }
})

And:

class Chart {
  constructor() {
    // make a canvas
  },
  addNodes() {
    // store
  },
  draw() {
    // parse storage and draw in library
  }
}

This means if we decide to change the rendering we only have to rewrite Chart rather than decouple all the code etc. If we wanted a different view on the data too, we can add a different mode to draw or a subclass.

Prior discussions:
mozilla/lightbeam#681
mozilla/lightbeam#525

@jonathanKingston

This comment has been minimized.

Show comment
Hide comment
@jonathanKingston

jonathanKingston May 9, 2017

Member

The suggested greuler dies on 300 nodes... so that is out :D

var nodes = [];
for (var i = 0; i< 300; i++) {
  nodes.push({id: i});
}
var instance = greuler({
  target: '#demo',
  width: 480,
  height: 500,
  data: {
    nodes: nodes,
    links: [
      {source: 0, target: 1},
      {source: 0, target: 2, directed: true},
      {source: 0, target: 3},
      {source: 1, target: 2, directed: true},
      {source: 4, target: 0},
      {source: 5, target: 0, directed: true},
      {source: 4, target: 5}
    ]
  }
}).update()
Member

jonathanKingston commented May 9, 2017

The suggested greuler dies on 300 nodes... so that is out :D

var nodes = [];
for (var i = 0; i< 300; i++) {
  nodes.push({id: i});
}
var instance = greuler({
  target: '#demo',
  width: 480,
  height: 500,
  data: {
    nodes: nodes,
    links: [
      {source: 0, target: 1},
      {source: 0, target: 2, directed: true},
      {source: 0, target: 3},
      {source: 1, target: 2, directed: true},
      {source: 4, target: 0},
      {source: 5, target: 0, directed: true},
      {source: 4, target: 5}
    ]
  }
}).update()
@princiya

This comment has been minimized.

Show comment
Hide comment
@princiya

princiya May 16, 2017

Collaborator

An attempt to understand how SVG vs CANVAS vs WEBGL affects a viz library's performance:

viz libs_1

Collaborator

princiya commented May 16, 2017

An attempt to understand how SVG vs CANVAS vs WEBGL affects a viz library's performance:

viz libs_1

@princiya

This comment has been minimized.

Show comment
Hide comment
@princiya

princiya May 16, 2017

Collaborator

Viz library's comparisons:
viz libs_2

  • Greuler is out already :)
  • D3 is the one used with the current version of Lightbeam
  • Ogma (previously Linkurius.js)
  • Sigma.js
Collaborator

princiya commented May 16, 2017

Viz library's comparisons:
viz libs_2

  • Greuler is out already :)
  • D3 is the one used with the current version of Lightbeam
  • Ogma (previously Linkurius.js)
  • Sigma.js
@jonathanKingston

This comment has been minimized.

Show comment
Hide comment
@jonathanKingston

jonathanKingston May 16, 2017

Member

@gregtatum just a heads up as I know you were contacted about this for info. Would appreciate your fav libraries for review here also 👍

Member

jonathanKingston commented May 16, 2017

@gregtatum just a heads up as I know you were contacted about this for info. Would appreciate your fav libraries for review here also 👍

@gregtatum

This comment has been minimized.

Show comment
Hide comment
@gregtatum

gregtatum May 23, 2017

Member

In my experience performance is not blocked on the actual force layout, but on the rendering of the nodes. I would think doing the force layout using d3, and then rendering with canvas would yield good performance:

Pseudo-code:

const [nodes, edges] = createNodes();

const updateForceLayout = createForceLayout(nodes, edges);
loop(() => {
  // This should layout in real-time.
  updateForceLayout();

  // Updating via canvas can be done in a few milliseconds:
  
  // begin path, set color for context, etc.
  edges.forEach(edge => {
    ctx.moveTo(edge.start.x, edges.start.y);
    ctx.lineTo(edge.end.x, edges.end.y);
  });
  ctx.stroke();

  // Set the context color
  edges.forEach(edge => {
    ctx.fillRect(node.x, node.y, node.width, node.height);
  });

  // Find the node under the cursors
  const node = nodes.find(node => nodeIsInRange(node, mousePosition));
  if (node) {
    // Draw the node highlighted.
  }
});

In my opinion, force layout is not a great candidate for server side, as it's an integration based layout, and requires many iterations to get correct results. There could be other layouts that will show the information you care about.

Member

gregtatum commented May 23, 2017

In my experience performance is not blocked on the actual force layout, but on the rendering of the nodes. I would think doing the force layout using d3, and then rendering with canvas would yield good performance:

Pseudo-code:

const [nodes, edges] = createNodes();

const updateForceLayout = createForceLayout(nodes, edges);
loop(() => {
  // This should layout in real-time.
  updateForceLayout();

  // Updating via canvas can be done in a few milliseconds:
  
  // begin path, set color for context, etc.
  edges.forEach(edge => {
    ctx.moveTo(edge.start.x, edges.start.y);
    ctx.lineTo(edge.end.x, edges.end.y);
  });
  ctx.stroke();

  // Set the context color
  edges.forEach(edge => {
    ctx.fillRect(node.x, node.y, node.width, node.height);
  });

  // Find the node under the cursors
  const node = nodes.find(node => nodeIsInRange(node, mousePosition));
  if (node) {
    // Draw the node highlighted.
  }
});

In my opinion, force layout is not a great candidate for server side, as it's an integration based layout, and requires many iterations to get correct results. There could be other layouts that will show the information you care about.

@princiya

This comment has been minimized.

Show comment
Hide comment
@princiya

princiya May 23, 2017

Collaborator

@gregtatum Thanks for your inputs :) I will try to reflect on what you have suggested, and get back soon with further doubts/questions.

Collaborator

princiya commented May 23, 2017

@gregtatum Thanks for your inputs :) I will try to reflect on what you have suggested, and get back soon with further doubts/questions.

@jonathanKingston

This comment has been minimized.

Show comment
Hide comment
@jonathanKingston

jonathanKingston Jul 4, 2017

Member

I think we can close this in favour of #90. Thanks for your work here @princiya

Member

jonathanKingston commented Jul 4, 2017

I think we can close this in favour of #90. Thanks for your work here @princiya

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment