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

Feature: Count over time #3

Open
kirbysayshi opened this issue Mar 17, 2014 · 4 comments
Open

Feature: Count over time #3

kirbysayshi opened this issue Mar 17, 2014 · 4 comments

Comments

@kirbysayshi
Copy link

I think I'm looking for something like:

function physicsEngineCollisionCallback(a, b) {
  rstats('collisions').mark(); // alternative: .inc()
}

The idea being that we want to know the "flow frequency" of how many collisions are happening over time without manually managing decay.

I could also see this being used to monitor a stream:

someStream.on('data', function(chunk) {
  rstats('someStream emit').mark();
});

If I wanted to measure flow rate, .set is good enough, but not for frequency of flow.

Perhaps this is possible today, and I'm missing something?

For context, I'm measuring both a standard game loop as well as when asynchronous messages arrive via postMessage from a web worker:

worker.addEventListener('message', function(ev) {
  rstats('msgs: recv').tick();
  rstats().update(); // ensure the graph always reflects
  // Do stuff with message
});

.tick will measure the time between calls, but I want to measure how many calls over time. Not sure how best to handle that, which is why I'm opening this ticket.

@spite
Copy link
Owner

spite commented Mar 17, 2014

When you say "over time" do you mean every second, over an undetermined period of time, or since the start of the execution?

rStats is designed to calculate values per-frame, but it can be modified to accumulate values in a different manner. If it's over a frame, you can see a way of doing it in the WebGL plugin https://github.com/spite/rstats/blob/master/src/rStats.extras.js#L32

I've been thinking about adding measures over other time frames, so let's talk about how it could work best.

@kirbysayshi
Copy link
Author

Yes, I was looking at the webgl plugin when trying to figure out a way to handle this. One thing to note is that those counts are never reset and even though it's a plugin the counts are being managed manually.

My use case is slightly unique: I'm trying to separate rendering from "world" updates via web workers. So I actually have a few calls to rstats.update since the main loop can be stopped and yet I still want to render the graphs. Perhaps I'm using rstats improperly then. I suppose I should have one .update call within an rAF callback regardless if the main loop is running or not. I'll look into that! Is it assumed that multiple .update calls break the reporting?

When I say "over time" I guess I mean outside of a frame context, meaning per second. Seems like .set already measures since the start of the execution (since subsequent .set with the same value produces a flat graph).

Even if the measurement was just per frame, I think something like .mark would work. The semantics would be:

  • Calling (name).mark() increments a counter named name by 1
  • Calling .update() graphs the number of calls to (name).mark() and resets the counter to 0.

This would then be able to give you thinks like "draw calls per frame" or "messages received per frame" without manually managing counters outside of rstats.

An alternative way would be for rstats to provide a root rstats.monitor method that does the same thing as https://github.com/spite/rstats/blob/master/src/rStats.extras.js#L13, but has a signature of 'stat name', fn, opt_cb.

@spite
Copy link
Owner

spite commented Mar 18, 2014

If I understand correctly, you should be using .frame(), like 'FPS' in the examples. That method accumulates (+1) each call, and calculates the correct value over 1000ms (https://github.com/spite/rstats/blob/master/src/rStats.js#L228). It does linear interpolation to compensate for the time accuracy, so it might give you fractional values.

If that works, I could add a flag to the value definition so it doesn't interpolate the value.

I've added a flag:

var rS = new rStats( {
    values: {
        fps: { caption: 'Framerate (FPS)', interpolate: false }
    }
}

When used with:

rS( 'FPS' ).frame();

the graph will show the correct value per second when calling .update(). You will still have to call it regularly: every frame, or every second at least. I would advice sticking it to the rAF callback.

@kirbysayshi
Copy link
Author

This gets me close, but still doesn't manage flow. For example:

worker.addEventListener('message', function(ev) {
  rs('msgs: main-recv').frame();
})

(function graph() {
  requestAnimationFrame(graph);
  rs().update();
}());

Once messages stop coming in (e.g. msgs: main-recv stops being called) then, like you basically said, the graph sticks at the last recorded value.

This works for me:

         function _flow(num) {
            var t = performance.now();
            var e = t - _time;
            _total += (num || 0);
            if( e > 1000 ) {
                if( _def && _def.interpolate === false ) {
                    _value = _total;
                } else {
                    _value = _total * 1000 / e;
                }
                _total = 0;
                _time = t;
                _average( _value );
           }
        }

and then:

worker.addEventListener('message', function(ev) {
  rs('msgs: main-recv').flow(1);
})

(function graph() {
  requestAnimationFrame(graph);
  rs('msgs: main-recv').flow(0);
  rs().update();
}());

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

No branches or pull requests

2 participants