Code Monkey home page Code Monkey logo

Comments (26)

shenenya avatar shenenya commented on August 24, 2024 1

I found the memory leak happens again.

I reproduced the problem with ReactVegaLiteDemo as follows:

  1. install react-timeout to stories
  2. change ReactVegaLiteDemo.jsx to follows:
import React from "react";
import { action } from "@storybook/addon-actions";
import { Vega, createClassFromSpec } from "../../react-vega/src";
import ReactTimeout from "react-timeout";

const data1 = {
  myData: [
    { a: "A", b: 20 },
    { a: "B", b: 34 },
    { a: "C", b: 55 },
    { a: "D", b: 19 },
    { a: "E", b: 40 },
    { a: "F", b: 34 },
    { a: "G", b: 91 },
    { a: "H", b: 78 },
    { a: "I", b: 25 },
    { a: "A", b: 20 },
    { a: "B", b: 34 },
    { a: "C", b: 55 },
    { a: "D", b: 19 },
    { a: "E", b: 40 },
    { a: "F", b: 34 },
    { a: "G", b: 91 },
    { a: "H", b: 78 },
    { a: "I", b: 25 }
  ]
};

const data2 = {
  myData: [
    { a: "A", b: 28 },
    { a: "B", b: 55 },
    { a: "C", b: 43 },
    { a: "D", b: 91 },
    { a: "E", b: 81 },
    { a: "F", b: 53 },
    { a: "G", b: 19 },
    { a: "H", b: 87 },
    { a: "I", b: 52 }
  ]
};

const spec1 = {
  $schema: "https://vega.github.io/schema/vega-lite/v4.0.0-beta.10.json",
  data: { name: "myData" },
  description: "A simple bar chart with embedded data.",
  encoding: {
    x: { field: "a", type: "ordinal" },
    y: { field: "b", type: "quantitative" }
  },
  mark: "bar"
};

const spec2 = {
  data: { name: "myData" },
  description: "A simple bar chart with embedded data.",
  encoding: {
    x: { field: "b", type: "quantitative" },
    y: { field: "a", type: "ordinal" }
  },
  mark: "bar"
};

const BarChart = createClassFromSpec({ mode: "vega-lite", spec: spec1 });

const code1 = `<VegaLite data={this.state.data} spec={this.state.spec} />`;

const code2 = `const BarChart = ReactVegaLite.createClassFromLiteSpec(spec1);
<BarChart data={this.state.data} />`;

class Demo extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      data: data1,
      info: "",
      spec: spec1
    };

    this.handleHover = this.handleHover.bind(this);
    this.handleToggleSpec = this.handleToggleSpec.bind(this);
    this.handleUpdateData = this.handleUpdateData.bind(this);
    this.handlers = { hover: this.handleHover };
  }

  setTimer = () => {
    var timer = function() {
      this.handleUpdateData();
      this.handleToggleSpec();
      this.timerHandle = this.props.setTimeout(timer.bind(this), 1);
    };
    this.timerHandle = this.props.setTimeout(timer.bind(this), 1);
  };

  componentDidMount = () => {
    this.setTimer();
  };

  handleHover(...args) {
    action("hover", {
      limit: 5
    })(args);
    this.setState({
      info: JSON.stringify(args)
    });
  }

  handleToggleSpec() {
    const { spec } = this.state;
    action("toggle spec")(spec);
    if (spec === spec1) {
      this.setState({ spec: spec2 });
    } else {
      this.setState({ spec: spec1 });
    }
  }

  handleUpdateData() {
    const { data } = this.state;
    action("update data")(data);
    if (data === data1) {
      this.setState({ data: data2 });
    } else if (data === data2) {
      this.setState({ data: data1 });
    }
  }

  render() {
    const { data, spec, info } = this.state;

    return (
      <div>
        <div style={{ float: "right" }}>
          <iframe
            title="star"
            src="https://ghbtns.com/github-btn.html?user=vega&repo=react-vega&type=star&count=true"
            frameBorder="0"
            scrolling="0"
            width="100px"
            height="20px"
          />
        </div>
        <button type="button" onClick={this.handleToggleSpec}>
          Toggle Spec
        </button>
        <button type="button" onClick={this.handleUpdateData}>
          Update data
        </button>
        <h3>
          <code>&lt;VegaLite&gt;</code> React Component
        </h3>
        Will recompile when spec changes and update when data changes.
        <pre>{code1}</pre>
        <Vega data={data} spec={spec} />
        <h3>
          <code>ReactVegaLite.createClassFromLiteSpec()</code>
        </h3>
        Use the given spec to create a reusable component.
        <pre>{code2}</pre>
        <BarChart data={data} />
        {info}
      </div>
    );
  }
}

export default ReactTimeout(Demo);
  1. Check the system memory costs. You could find the memory used by browser keep increasing.

截屏2020-05-18 下午4 41 13

截屏2020-05-18 下午4 44 07

from react-vega.

domoritz avatar domoritz commented on August 24, 2024

Is this a Vegas or react Vega issue? Could you help us find out?

from react-vega.

shenenya avatar shenenya commented on August 24, 2024

I checked out codes of react-vega. It release old view with finalize function. I also look at vega-embed. But I do not find possible reason by now. I think it maybe caused by async or vega's implementation of finalize function.

from react-vega.

domoritz avatar domoritz commented on August 24, 2024

Can you try to reproduce this issue with just Vega?

from react-vega.

shenenya avatar shenenya commented on August 24, 2024

Ok. By now, I found that when we use onNewView in react-vega and update state in the function called. The memory leaks will be serious. Even I try to release the view with finalize function. Could you help me to explain why and what we could do? Thanks.

from react-vega.

domoritz avatar domoritz commented on August 24, 2024

Can you see whether the same happens with just Vega?

from react-vega.

shenenya avatar shenenya commented on August 24, 2024

I reproduced the problem with ReactVegaLiteDemo as follows:

  1. install react-timeout to stories
  2. change ReactVegaLiteDemo.jsx to follows:
import React from "react";
import { action } from "@storybook/addon-actions";
import { Vega, createClassFromSpec } from "../../react-vega/src";
import ReactTimeout from "react-timeout";

const data1 = {
  myData: [
    { a: "A", b: 20 },
    { a: "B", b: 34 },
    { a: "C", b: 55 },
    { a: "D", b: 19 },
    { a: "E", b: 40 },
    { a: "F", b: 34 },
    { a: "G", b: 91 },
    { a: "H", b: 78 },
    { a: "I", b: 25 },
    { a: "A", b: 20 },
    { a: "B", b: 34 },
    { a: "C", b: 55 },
    { a: "D", b: 19 },
    { a: "E", b: 40 },
    { a: "F", b: 34 },
    { a: "G", b: 91 },
    { a: "H", b: 78 },
    { a: "I", b: 25 }
  ]
};

const data2 = {
  myData: [
    { a: "A", b: 28 },
    { a: "B", b: 55 },
    { a: "C", b: 43 },
    { a: "D", b: 91 },
    { a: "E", b: 81 },
    { a: "F", b: 53 },
    { a: "G", b: 19 },
    { a: "H", b: 87 },
    { a: "I", b: 52 }
  ]
};

const spec1 = {
  $schema: "https://vega.github.io/schema/vega-lite/v4.0.0-beta.10.json",
  data: { name: "myData" },
  description: "A simple bar chart with embedded data.",
  encoding: {
    x: { field: "a", type: "ordinal" },
    y: { field: "b", type: "quantitative" }
  },
  mark: "bar"
};

const spec2 = {
  data: { name: "myData" },
  description: "A simple bar chart with embedded data.",
  encoding: {
    x: { field: "b", type: "quantitative" },
    y: { field: "a", type: "ordinal" }
  },
  mark: "bar"
};

const BarChart = createClassFromSpec({ mode: "vega-lite", spec: spec1 });

const code1 = `<VegaLite data={this.state.data} spec={this.state.spec} />`;

const code2 = `const BarChart = ReactVegaLite.createClassFromLiteSpec(spec1);
<BarChart data={this.state.data} />`;

class Demo extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      data: data1,
      info: "",
      spec: spec1
    };

    this.handleHover = this.handleHover.bind(this);
    this.handleToggleSpec = this.handleToggleSpec.bind(this);
    this.handleUpdateData = this.handleUpdateData.bind(this);
    this.handlers = { hover: this.handleHover };
  }

  setTimer = () => {
    var timer = function() {
      this.handleUpdateData();
      this.handleToggleSpec();
      this.timerHandle = this.props.setTimeout(timer.bind(this), 1);
    };
    this.timerHandle = this.props.setTimeout(timer.bind(this), 1);
  };

  componentDidMount = () => {
    this.setTimer();
  };

  handleHover(...args) {
    action("hover", {
      limit: 5
    })(args);
    this.setState({
      info: JSON.stringify(args)
    });
  }

  handleToggleSpec() {
    const { spec } = this.state;
    action("toggle spec")(spec);
    if (spec === spec1) {
      this.setState({ spec: spec2 });
    } else {
      this.setState({ spec: spec1 });
    }
  }

  handleUpdateData() {
    const { data } = this.state;
    action("update data")(data);
    if (data === data1) {
      this.setState({ data: data2 });
    } else if (data === data2) {
      this.setState({ data: data1 });
    }
  }

  render() {
    const { data, spec, info } = this.state;

    return (
      <div>
        <div style={{ float: "right" }}>
          <iframe
            title="star"
            src="https://ghbtns.com/github-btn.html?user=vega&repo=react-vega&type=star&count=true"
            frameBorder="0"
            scrolling="0"
            width="100px"
            height="20px"
          />
        </div>
        <button type="button" onClick={this.handleToggleSpec}>
          Toggle Spec
        </button>
        <button type="button" onClick={this.handleUpdateData}>
          Update data
        </button>
        <h3>
          <code>&lt;VegaLite&gt;</code> React Component
        </h3>
        Will recompile when spec changes and update when data changes.
        <pre>{code1}</pre>
        <Vega data={data} spec={spec} />
        <h3>
          <code>ReactVegaLite.createClassFromLiteSpec()</code>
        </h3>
        Use the given spec to create a reusable component.
        <pre>{code2}</pre>
        <BarChart data={data} />
        {info}
      </div>
    );
  }
}

export default ReactTimeout(Demo);
  1. Check the system memory costs. You could find the memory used by browser keep increasing.

from react-vega.

domoritz avatar domoritz commented on August 24, 2024

Can you reproduce the same with just Vega (no react)?

Note that Vega uses a reactive data flow and therefore has to keep track of some data. However, this doesn’t mean that memory usage continuously increases.

from react-vega.

shenenya avatar shenenya commented on August 24, 2024

Hi. I reproduce the same problem with just vega-lite as follows.

<!DOCTYPE html>
<head>
  <meta charset="utf-8" />
  <script src="https://cdn.jsdelivr.net/npm/vega@5"></script>
  <script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
  <script src="https://cdn.jsdelivr.net/npm/vega-embed@5"></script>
</head>

<body>
  <div id="vis"></div>

  <script>
    const spec1 = {
      $schema: "https://vega.github.io/schema/vega-lite/v3.json",
      description: "A simple bar chart with embedded data.",
      width: 360,
      data: {
        values: [
          { a: "A", b: 28 },
          { a: "B", b: 55 },
          { a: "C", b: 43 },
          { a: "D", b: 91 },
          { a: "E", b: 81 },
          { a: "F", b: 53 },
          { a: "G", b: 19 },
          { a: "H", b: 87 },
          { a: "I", b: 52 }
        ]
      },
      mark: "bar",
      encoding: {
        x: { field: "a", type: "ordinal" },
        y: { field: "b", type: "quantitative" },
        tooltip: { field: "b", type: "quantitative" }
      }
    };
    const spec2 = {
      $schema: "https://vega.github.io/schema/vega-lite/v3.json",
      description: "A simple bar chart with embedded data.",
      width: 500,
      data: {
        values: [
          { a: "A", b: 33 },
          { a: "B", b: 32 },
          { a: "C", b: 16 },
          { a: "D", b: 28 },
          { a: "E", b: 35 },
          { a: "F", b: 81 },
          { a: "G", b: 90 },
          { a: "H", b: 10 },
          { a: "I", b: 5 }
        ]
      },
      mark: "bar",
      encoding: {
        x: { field: "a", type: "ordinal" },
        y: { field: "b", type: "quantitative" },
        tooltip: { field: "b", type: "quantitative" }
      }
    };
    let spec = spec1;
    function myFunction() {
      setInterval(function() {
        if (spec === spec1) spec = spec2;
        else spec = spec1;

        vegaEmbed("#vis", spec)
          .then()
          .catch(console.warn);
      }, 1000);
    }
  </script>

  <button onclick="myFunction()">Update</button>
</body>

from react-vega.

domoritz avatar domoritz commented on August 24, 2024

The embed example is fixed by using .finalize(). See vega/vega-embed#270

React Vega already uses finalize so I'm not sure yet what's happening here

.

from react-vega.

shenenya avatar shenenya commented on August 24, 2024

I tried react-vega. It has the problem.

from react-vega.

domoritz avatar domoritz commented on August 24, 2024

Moving discussion to vega/vega-embed#270.

from react-vega.

kristw avatar kristw commented on August 24, 2024

@eeyshen I notice that in the react-vega example, you setTimeout every 1ms while the vega-lite one is every 1000ms.

Is that intentional?

from react-vega.

shenenya avatar shenenya commented on August 24, 2024

I also tried vega-lite with 1ms. The problem will show itself more quick.

from react-vega.

domoritz avatar domoritz commented on August 24, 2024

To fix this, please call result.finalize() in Embed 6.2.0.

from react-vega.

shenenya avatar shenenya commented on August 24, 2024

Do you mean what have done in VegaEmbed.tsx:

  clearView() {
    this.modifyView(view => {
      view.finalize();
    });
    this.viewPromise = undefined;

    return this;
  }

from react-vega.

domoritz avatar domoritz commented on August 24, 2024

No, we should fix react Vega to call this. Users shouldn’t need to call finalize directly.

from react-vega.

shenenya avatar shenenya commented on August 24, 2024

@domoritz Hi, when will the next release of react-vega be published with the bug fixed? Thanks.

from react-vega.

domoritz avatar domoritz commented on August 24, 2024

I don't have the cycles to add the fix. Maybe you can send a or @kristw may have time.

from react-vega.

shenenya avatar shenenya commented on August 24, 2024

@kristw Do you have time to fix this bug with Vega-Embed 6.2 and release a new version?

from react-vega.

shenenya avatar shenenya commented on August 24, 2024

As Vega, Vega-Lite, Vega-Embed upgrades, is there some plan for react-vega upgrade? Thanks.

from react-vega.

kristw avatar kristw commented on August 24, 2024

I am on vacation with limited access. However, pull requests are welcome.

from react-vega.

kristw avatar kristw commented on August 24, 2024

Is this resolved?

from react-vega.

shenenya avatar shenenya commented on August 24, 2024

I believe so.

from react-vega.

shenenya avatar shenenya commented on August 24, 2024

I believe the problem appear again. The screenshot below show the memory profile of the example above.

<!DOCTYPE html>
<head>
  <meta charset="utf-8" />
  <script src="https://cdn.jsdelivr.net/npm/vega@5"></script>
  <script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
  <script src="https://cdn.jsdelivr.net/npm/vega-embed@6"></script>
</head>

<body>
  <div id="vis"></div>

  <script>
    const spec1 = {
      $schema: "https://vega.github.io/schema/vega-lite/v4.json",
      description: "A simple bar chart with embedded data.",
      width: 360,
      data: {
        values: [
          { a: "A", b: 28 },
          { a: "B", b: 55 },
          { a: "C", b: 43 },
          { a: "D", b: 91 },
          { a: "E", b: 81 },
          { a: "F", b: 53 },
          { a: "G", b: 19 },
          { a: "H", b: 87 },
          { a: "I", b: 52 }
        ]
      },
      mark: "bar",
      encoding: {
        x: { field: "a", type: "ordinal" },
        y: { field: "b", type: "quantitative" },
        tooltip: { field: "b", type: "quantitative" }
      }
    };
    const spec2 = {
      $schema: "https://vega.github.io/schema/vega-lite/v4.json",
      description: "A simple bar chart with embedded data.",
      width: 500,
      data: {
        values: [
          { a: "A", b: 33 },
          { a: "B", b: 32 },
          { a: "C", b: 16 },
          { a: "D", b: 28 },
          { a: "E", b: 35 },
          { a: "F", b: 81 },
          { a: "G", b: 90 },
          { a: "H", b: 10 },
          { a: "I", b: 5 }
        ]
      },
      mark: "bar",
      encoding: {
        x: { field: "a", type: "ordinal" },
        y: { field: "b", type: "quantitative" },
        tooltip: { field: "b", type: "quantitative" }
      }
    };
    let spec = spec1;
    function myFunction() {
      setInterval(function() {
        if (spec === spec1) spec = spec2;
        else spec = spec1;

        vegaEmbed("#vis", spec)
          .then()
          .catch(console.warn);
      }, 1000);
    }
  </script>

  <button onclick="myFunction()">Update</button>
</body>

截屏2020-05-18 上午9 17 01

from react-vega.

domoritz avatar domoritz commented on August 24, 2024

I responded in the related Vega embed issue.

from react-vega.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.