Skip to content
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

Viewer remounting on changing entities causing severe lag #46

Closed
tmercado opened this issue Jan 2, 2019 · 12 comments
Closed

Viewer remounting on changing entities causing severe lag #46

tmercado opened this issue Jan 2, 2019 · 12 comments

Comments

@tmercado
Copy link

tmercado commented Jan 2, 2019

Hi all,
I went from v0.2.2 to 1.0.0 didn't change any code and started getting a severe drop in performance. These entities are being updated about every second to a new location so on zooming in they will be moving.
Before:
resium0 2 2

After:
resium1 0 0
image

code:

const entities = Object.values(events).map((e) => {
    const lat = e.geometry.coordinates[0];
    const long = e.geometry.coordinates[1];
    const z = e.geometry.coordinates[2];
    const identifier = e.properties.identifier.toLowerCase();
    const color = entityColors[identifier]? entityColors[identifier] : '#FFFF00';

    return (
        <Entity
             key={e.properties.callsign}
             name={e.properties.callsign}
             position={Cartesian3.fromDegrees(lat,long,z)}
             point={{ pixelSize: 10,color: Color.fromCssColorString(color) }} />
    );
});

return(
<Viewer full>
    <Scene>
        <Camera onMoveEnd={this.onMoveEnd} ref={ref => this.camera = ref} >
            {entities}
        </Camera>
    </Scene>
</Viewer>
);
@tmercado tmercado changed the title Viewer remounting on changing entities causing sever lag Viewer remounting on changing entities causing severe lag Jan 3, 2019
@rot1024 rot1024 added the bug label Jan 3, 2019
@rot1024
Copy link
Member

rot1024 commented Jan 3, 2019

Hi, thank you for your bug reporting! I will investigate the code you provided.

@rot1024
Copy link
Member

rot1024 commented Jan 7, 2019

@tmercado It seems not to be a bug. Please fix your code:

return (
  <Viewer full>
    <Camera onMoveEnd={this.onMoveEnd} ref={ref => this.camera = ref} />
    {entities}
  </Viewer>
);

Isn't the issue be resolved even if you fix it?

@rot1024 rot1024 added question and removed bug labels Jan 7, 2019
@tmercado
Copy link
Author

You might be right. I will take a look into seeing if that works and get back ASAP

@tmercado
Copy link
Author

Update: used the code you provided and still having the same issue.
Again those entities will be changing location several times a second. With the previous version I wouldn't have any slow down until i hit around 20,000 entities where 20 entity updates would happen every millisecond.

@rot1024
Copy link
Member

rot1024 commented Jan 18, 2019

Ok, could you provide the code to reproduce that issue?

@tmercado
Copy link
Author

reducer.js

export default function reducer (state = initialState, action) {
  switch (action.type) {
    case EVENTS_RECEIVED: { // entity updates from backend server only 20 come in at a time
      const events = state.get('events').toJS();
      const nEvents = action.value;
      const nKeys = Object.keys(nEvents);

      for (let i = 0; i < nKeys.length; i++) {
        events[nKeys[i]] = nEvents[nKeys[i]]; //update or add
      }
      return state.set('events',fromJS(events)); // update state
    }
    case GET_BASE_LAYERS_SUCCESS:
      return state.set('baseLayers', fromJS(action.value));
    default:
      return state;
  }
}

viewer.js

render() {
 const entities = Object.values(events).map((e) => {
      const lat = e.coordinates[0];
      const long = e.coordinates[1];
      const z = e.coordinates[2];
      const color = entityColors[e.color]? entityColors[e.color] : '#FFFF00';

      return (
          <Entity
               name={events.name}
               position={Cartesian3.fromDegrees(lat, long, z)}
               point={{ pixelSize: 5, color: Color.fromCssColorString(color) }} />
      );
    });
  return(
    <Viewer full>
      <Camera ... />
       {entities}
     </Viewer>
    );
}

let me know if you need more information

@rot1024
Copy link
Member

rot1024 commented Jan 21, 2019

I tried the following code but it works well.

index.js

import React from "react";
import ReactDOM from "react-dom";
import { createStore } from "redux";
import { Provider, connect } from "react-redux";
import { fromJS } from "immutable";

import App from "./app";

const EVENTS_RECEIVED = "EVENTS_RECEIVED";
const GET_BASE_LAYERS_SUCCESS = "GET_BASE_LAYERS_SUCCESS";
const initalState = fromJS({ events: {}, baseLayers: undefined });

const store = createStore((state = initalState, action) => {=
  switch (action.type) {
    case EVENTS_RECEIVED: {
      // entity updates from backend server only 20 come in at a time
      const events = state.get("events").toJS();
      const nEvents = action.value;
      const nKeys = Object.keys(nEvents);

      for (let i = 0; i < nKeys.length; i++) {
        events[nKeys[i]] = nEvents[nKeys[i]]; //update or add
      }
      return state.set("events", fromJS(events)); // update state
    }
    case GET_BASE_LAYERS_SUCCESS:
      return state.set("baseLayers", fromJS(action.value));
    default:
      return state;
  }
});

const WrappedApp = connect(state => ({ events: state.get("events").toJS() }))(App);

ReactDOM.render(
  <Provider store={store}>
    <WrappedApp />
  </Provider>,
  document.getElementById("root"),
);

// fetch data
window.setTimeout(() => {
  const act = {
    type: EVENTS_RECEIVED,
    value: new Array(20).fill().reduce( // generate dummy data
      (a, b, i) => ({
        ...a,
        [`test${i}`]: {
          coordinates: [Math.random() * 360 - 180, Math.random() * 180 - 90, 100],
        },
      }),
      {},
    ),
  };
  store.dispatch(act);
}, 3000);

app.js

import React from "react";
import { hot } from "react-hot-loader";
import { Cartesian3, Color } from "cesium";
import { Viewer, Entity } from "resium";

const App = ({ events }) => (
  <Viewer full>
    {Object.entries(events).map(([key, e]) => {
      const lat = e.coordinates[0];
      const long = e.coordinates[1];
      const z = e.coordinates[2];
      // const color = entityColors[e.color] ? entityColors[e.color] : "#FFFF00";

      return (
        <Entity
          key={key}
          name={key}
          position={Cartesian3.fromDegrees(lat, long, z)}
          point={{ pixelSize: 5, color: Color.fromCssColorString("#fff") }}
        />
      );
    })}
  </Viewer>
);

export default hot(module)(App);

image

I think key prop is necessary in Entity component as bellow.

       return (
          <Entity
               key={key}  // something like id
               name={events.name}
               position={Cartesian3.fromDegrees(lat, long, z)}
               point={{ pixelSize: 5, color: Color.fromCssColorString(color) }} />
      );

If you don't mind, provide the whole project.

@tmercado
Copy link
Author

Can you try with 10,000 entities (then update 20 of them every 10ms)? Unfortunately that is pretty much the whole project. I might have to do some culling when dots are behind the globe/out of view.

@rot1024
Copy link
Member

rot1024 commented Jan 22, 2019

I tried 10,000 entities and updating 20 entities every 1s (every 10ms is too heavy), but it works well. (I recommend PointPrimitive than Entity because there are too many points)

But are you using CameraFlyTo or CameraFlyToBoundingSphere component?

I found a bug: camera position is changed every rendering time If it is used as following.

// In this code, camera position is changed every 1s

class Example extends React.PureComponent {
  state = { count: 0 };
  dest = Cartesian3.fromDegrees(0, 0, 100000);

  componentDidMount() {
    setInterval(() => {
      this.setState(s => ({ count: s.count + 1 })); // update
    }, 1000);
  }

  render() {
    return (
      <Viewer>
        <CameraFlyTo destination={this.dest} duration={0} />
      </Viewer>
    );
  }
}

But it works well as following

// In this code, camera position never change every 1s

class Test extends React.PureComponent {
  state = { count: 0 };
  dest = Cartesian3.fromDegrees(0, 0, 100000);

  componentDidMount() {
    setInterval(() => {
      this.setState(s => ({ count: s.count + 1 })); // update
    }, 1000);
  }

  render() {
    return (
      <CameraFlyTo destination={this.dest} duration={0} />
    );
  }
}

class Example extends React.PureComponent {
  render() {
    return (
      <Viewer>
        <Test />
      </Viewer>
    );
  }
}

It is a bug. I have fixed Resium and released new version. Please try v1.2.1!

@rot1024 rot1024 added the bug label Jan 22, 2019
@tmercado
Copy link
Author

I'm currently not using CameraFlyTo or CameraFlyToBoundingSphere. Do you have an example of the Point Primitive?

@rot1024
Copy link
Member

rot1024 commented Jan 23, 2019

PointPrimitive example:

Documentation:

@tmercado
Copy link
Author

Awesome thank you! I got it almost the speed I want.

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

No branches or pull requests

2 participants