How to correctly calculate FPS in XNA? - xna

I wrote a component to display current FPS.
The most important part of it is:
public override void Update(GameTime gameTime)
{
elapseTime += (float)gameTime.ElapsedRealTime.TotalSeconds;
frameCounter++;
if (elapseTime > 1)
{
FPS = frameCounter;
frameCounter = 0;
elapseTime = 0;
}
base.Update(gameTime);
}
public override void Draw(GameTime gameTime)
{
spriteBatch.Begin();
spriteBatch.DrawString(font, "FPS " + ((int)FPS).ToString(), position, color, 0, origin, scale, SpriteEffects.None, 0);
spriteBatch.End();
base.Draw(gameTime);
}
In most cases it works ok, but recently I had a problem.
When I put following code into Update method of game strange thing starts to happen.
if (threadPath == null || threadPath.ThreadState != ThreadState.Running)
{
ThreadStart ts = new ThreadStart(current.PathFinder.FindPaths);
threadPath = new Thread(ts);
threadPath.Priority = ThreadPriority.Highest;
threadPath.Start();
}
Main idea of this code is to run pathFinding algorithm in different thread all the time.
By strange things I mean that sometimes FPS drasticly decreases, this is obvious, but displayed FPS changes more often than once a second. If I understand this code FPS can't change more often than once a second.
Can someone explain me what's going on?
Edit 26.03.2010
I've posted also code of Draw method.
Edit 31.03.2010 Answers to Venesectrix questions
1) are you running with a fixed or variable time step?
IsFixedTimeStep and SynchronizeWithVerticalRetrace is set to true.
2)Were you moving the XNA window around when this occurred?
No
3)Did the XNA window have focus?
Yes
4) How noticeable was it (ie, updating so fast you can't read it, or just barely updating more than a second)?
I was able to read updates, FPS was updating ~3 times a second.
5) And all of this only happens with the thread code in there?
Yes

Shawn Hargreaves has a great post about this here. The first difference I see between his code and yours is the fact that you reset your elapseTime to 0 each time, which will lose some time, whereas Shawn just subtracts 1 second from his elapsedTime. Also, Shawn uses ElapsedGameTime instead of ElapsedRealTime. He updates his frameCounter in the Draw function instead of the Update function as well.
As far as why he uses ElapsedRealTime, he explains it in a comment after the post:
> Surely 1 / gameTime.ElapsedRealTime.TotalSeconds
> will therefore give the current framerate.
That will tell you how long it was
since the previous call to Update, but
that is not the same thing as your
framerate!
a) If the game is dropping frames,
Update will be called more frequently
in order to catch up. You want to time
the number of actual draws that are
taking place, not just these extra
catch-up logic frames.
b) The time for a single Update can
fluctuate widely, so the figure you
get out of that will be too flickery
to be easily readable.
I would try his component, and see if it works for you. The post is pretty old, and I think you will have to change LoadGraphicsContent to LoadContent and UnloadGraphicsContent to UnloadContent, as another one of the comments points out.

Here is how I do it and with this method:
You average over n Frames
You can use it with any initialization method you choose
It should be easy to read and follow
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
namespace _60fps
{
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
SpriteFont OutputFont;
float Fps = 0f;
private const int NumberSamples = 50; //Update fps timer based on this number of samples
int[] Samples = new int[NumberSamples];
int CurrentSample = 0;
int TicksAggregate = 0;
int SecondSinceStart = 0;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
base.Initialize();
graphics.SynchronizeWithVerticalRetrace = false;
int DesiredFrameRate = 60;
TargetElapsedTime = new TimeSpan(TimeSpan.TicksPerSecond / DesiredFrameRate);
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
OutputFont = Content.Load<SpriteFont>("MessageFont");
}
protected override void UnloadContent()
{/* Nothing to do */}
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState(PlayerIndex.One).IsKeyDown(Keys.Escape))
this.Exit();
base.Update(gameTime);
}
private float Sum(int[] Samples)
{
float RetVal = 0f;
for (int i = 0; i < Samples.Length; i++)
{
RetVal += (float)Samples[i];
}
return RetVal;
}
private Color ClearColor = Color.FromNonPremultiplied(20, 20, 40, 255);
protected override void Draw(GameTime gameTime)
{
Samples[CurrentSample++] = (int)gameTime.ElapsedGameTime.Ticks;
TicksAggregate += (int)gameTime.ElapsedGameTime.Ticks;
if (TicksAggregate > TimeSpan.TicksPerSecond)
{
TicksAggregate -= (int)TimeSpan.TicksPerSecond;
SecondSinceStart += 1;
}
if (CurrentSample == NumberSamples) //We are past the end of the array since the array is 0-based and NumberSamples is 1-based
{
float AverageFrameTime = Sum(Samples) / NumberSamples;
Fps = TimeSpan.TicksPerSecond / AverageFrameTime;
CurrentSample = 0;
}
GraphicsDevice.Clear(ClearColor);
spriteBatch.Begin();
if (Fps > 0)
{
spriteBatch.DrawString(OutputFont, string.Format("Current FPS: {0}\r\nTime since startup: {1}", Fps.ToString("000"), TimeSpan.FromSeconds(SecondSinceStart).ToString()), new Vector2(10,10), Color.White);
}
spriteBatch.End();
base.Draw(gameTime);
}
}
}
As for:
"but the question why displayed FPS was changing more often than once a second is still open"
The difference between ElapsedGameTime and ElapsedRealTime is that "ElapsedGameTime" is the amount of time since the last time you entered the Update or Draw statement (depending on which "gameTime" you're using - the one from Update or the one from Draw).
ElapsedRealTime is the time since the game started. Because of this, it increases linearly as the game continues to run. Indeed, after 1 second, you'll update every frame because your logic looked like this:
(Let's assume you were running 4 fps for the sake of easy explanation):
Frame 1: ElapsedRealTime: 0.25. Running total now: 0.25
Frame 2: ElapsedRealTime: 0.5 Running total now: 0.75
Frame 3: ElapsedRealTime: 0.75 Running total now: 1.5
Running total greater than 1!!! Show FPS!
Set Running total = 0
Frame 4: ElapsedRealTime: 1.00 Running total now: 1.0
Running total greater than 1!!! Show FPS!
Now that you've fixed the counter, you should now only be getting Elapsed Game Time changes of a steady 0.25 so the progression now moves:
Frame 1: ElapsedGameTime: 0.25. Running total now: 0.25
Frame 2: ElapsedGameTime: 0.25 Running total now: 0.50
Frame 3: ElapsedGameTime: 0.25 Running total now: 0.75
Frame 4: ElapsedGameTime: 0.25 Running total now: 1.00
Running total greater than 1!!! Show FPS!
Set Running total = 0
Frame 5: ElapsedGameTime: 0.25. Running total now: 0.25
Frame 6: ElapsedGameTime: 0.25 Running total now: 0.50
Frame 7: ElapsedGameTime: 0.25 Running total now: 0.75
Frame 8: ElapsedGameTime: 0.25 Running total now: 1.00
Running total greater than 1!!! Show FPS!
Set Running total = 0
Which is what you're expecting. In short, now that you corrected the first problem, you should have corrected the second too and "why" is explained above.

As an aside ... you should avoid setting the thread priority. By assigning the highest thread priority to what should be a background thread, you could end up starving the main thread of cpu time because the scheduler would give priority to threadPath

Are you actively checking if IsRunningSlowly is being changed? Even with IsFixedTimeStep to true, if your program isn't able to do as many Updates as it expects, it will call it more frequently.
A way I have mitigated this before is by directly calling ResetElapsedTime() instead of keeping track of it yourself.
Not sure if that'll work for you though. I did notice that when i was debugging the previous issue I had, it wouldn't call the extra Updates, probably a 'feature' when debugging.

You should run your fps counter under the draw method

Hi guys if you want to show your real framerate you have to implement framerate counter to method Draw, because XNA do it like this:
"If your computer can't serve the method Update it suspend Draw method and instead of that it serve the Update method"

Related

Google Lighthouse Speed Index 100% visually completed frame definition

I'm looking for a way to optimize our website's Speed Index metric on Lighthouse
I found this helpful article describe Speed Index metric very well, and help me understand how Speed Index is calculated.
https://calendar.perfplanet.com/2016/speed-index-tips-and-tricks/
But there is a key concept not being described clear on the article, and I search for a lot of other Speed Index related blogs still can't found the answer.
What is the 100% visual completeness frame?
We all know the First Frame is 0% VC because it's blank, but the VC keep increasing during the page load process, so what frame will be consider as 100% visual completeness?
The definition of 100% VC frame is important because it's the baseline for calculate all other frame's visual completeness.
If I have a page that simply print from 1 to 100 with interval 100ms and just enough to fill in the viewport, will the 100% VC frame be the frame that number 100 is printed?
Lighthouse
According to Google's description of the Lighthouse "Speed Index" audit:
Lighthouse uses a node module called Speedline to generate the Speed Index score.
sends Speedline
Speedline's Github readme says
The Speed Index, introduced by WebpageTest.org, aims to solve this issue. It measures how fast the page content is visually displayed. The current implementation is based on the Visual Progress from Video Capture calculation method described on the Speed Index page. The visual progress is calculated by comparing the distance between the histogram of the current frame and the final frame.
(Italics mine.)
a timeline of paints
The Speed Index page goes into painful detail about how visual progress is calculated. Here's a snippet:
In the case of Webkit-based browsers, we collect the timeline data which includes paint rects as well as other useful events.
I believe "timeline data" refers to a JSON object retrieved via the Performance Timeline API.
It seems Lighthouse passes the JSON timeline to Speedline, which then extracts an array of "frames," describing the page load's paint events:
/**
* #param {string|Array<TraceEvent>|{traceEvents: Array<TraceEvent>}} timeline
* #param {Options} opts
*/
function extractFramesFromTimeline(timeline, opts) {
which calculates histograms
Speedline converts the image data from each paint event to an image histogram, interestingly excluding pixels that are "close enough" to pass as white:
/**
* #param {number} i
* #param {number} j
* #param {ImageData} img
*/
function isWhitePixel(i, j, img) {
return getPixel(i, j, 0, img.width, img.data) >= 249 &&
getPixel(i, j, 1, img.width, img.data) >= 249 &&
getPixel(i, j, 2, img.width, img.data) >= 249;
}
A lot of math goes into calculating and comparing histograms. The project maintainer is the right person to ask about that. But this is where the eventual determination of the "visually complete" happens:
// find visually complete
for (let i = 0; i < frames.length && !visuallyCompleteTs; i++) {
if (frames[i][progressToUse]() >= 100) {
visuallyCompleteTs = frames[i].getTimeStamp();
}
}
and infers "progress",
The "progress" of a given frame seems to be calculated by this function:
/**
* #param {Frame} current
* #param {Frame} initial
* #param {Frame} target
*/
function calculateFrameProgress(current, initial, target) {
let total = 0;
let match = 0;
const currentHist = current.getHistogram();
const initialHist = initial.getHistogram();
const targetHist = target.getHistogram();
for (let channel = 0; channel < 3; channel++) {
for (let pixelVal = 0; pixelVal < 256; pixelVal++) {
const currentCount = currentHist[channel][pixelVal];
const initialCount = initialHist[channel][pixelVal];
const targetCount = targetHist[channel][pixelVal];
const currentDiff = Math.abs(currentCount - initialCount);
const targetDiff = Math.abs(targetCount - initialCount);
match += Math.min(currentDiff, targetDiff);
total += targetDiff;
}
}
let progress;
if (match === 0 && total === 0) { // All images are the same
progress = 100;
} else { // When images differs
progress = Math.floor(match / total * 100);
}
return progress;
}
and "visually complete" is the first frame with 100% progress.
Without fully auditing the code, my interpretation is that the "visually complete frame" is the first frame calculated to have the same total difference from the initial frame as the final frame (which is determined by which frames Lighthouse chooses to send to Speedline).
Or, in other words, it's complicated.
Visually complete is when the page in the viewport stops changing. I.e. the visuals are not changing.
It is calculated by taking screenshots throughout the load and comparing them to each other and to the final end state. So yes in your example when all numbers 1-100 are printed and the page stops changing you are “visually complete”.
So if a page loads the data in view quickly but renders “below the fold” content (e.g. off screen images) more slowly then you will get a quick visually complete, even if the page overall load time is still long.
Similarly if most of the on screen content is drawn early on but one small part is drawn later (perhaps a “click to chat” option) you will get mostly visually complete early on and so a good speed index, even if not as good as the above example.
On the other hand if you load fonts, or perhaps a large hero image, last and it redraws large parts of the page in view you will get a slow visual complete time and also a slow speed index score.
More details here: https://sites.google.com/a/webpagetest.org/docs/using-webpagetest/metrics/speed-index
I just got the answer from Lighthouse repo contributor, pls check this link guys.
https://github.com/GoogleChrome/lighthouse/issues/8148

Understanding random numbers in iOS Swift 2

How do I make a random number continue to change over time in the program (I.E. become a new one within the range everytime I want to use it)?
I'm stumped. I've read more than 20 different posts and articles on how to generate random numbers in this language (which I'm pretty new to) and I just can't seem to get it to work.
I'm basically trying to get a random double from 1.0-3.0. I can do this pretty easily, but once it has selected that number it doesn't change. This is my code that I use:
var randomNumber:Double = (Double(arc4random() % 3) + 1);
Then I use this as a value for the line:
SKAction.waitForDuration(randomNumber)
Every time I run this I want to change the number again, but once the program starts it continues that same number (It's different every time i reset the program)
I understand how to generate the number, but I can't seem to find anything on updating it!
I've tried adding
randomNumber = (Double(arc4random() % 3) + 1);
into the code in a spot where it will be ran many times, but it still gives me the same thing.
I'm very familiar with c++ so if you're trying to explain something you can reference its style and I will most likely understand.
What you need it is a read only computed property that will return a new random every time you try to access it:
var randomNumber: Double {
return Double(arc4random_uniform(3).successor())
}
print(randomNumber) // 2.0
print(randomNumber) // 2.0
print(randomNumber) // 1.0
print(randomNumber) // 3.0
print(randomNumber) // 3.0
Use:
SKAction.waitForDuration(sec: NSTimeInterval, withRange: NSTimeInterval)
where sec is the middle of the range in time you want to use, since range goes in a +- direction.
So in your case you want:
SKAction.waitForDuration(2, withRange: 2), this will get you a range of 1 to 3 (-1 to 1 range)
If for some reason you need a method that will constantly create a new random wait, you can always do:
extension SKAction
{
func waitForRandomDuration() -> SKAction
{
var randomNumber:Double = (Double(arc4random() % 3) + 1);
return SKAction.waitForDuration(randomNumber);
}
}
And then make sure that you add this as a new action onto your sprite every time you need to get it done, if you store it into a variable, your randomness won't change.
Try this code:
func randomNumberBetween1_0And3_0() -> Double {
return 1 + Double(arc4random_uniform(2000)) / 1000.0
}
for index in 1...10 {
print(randomNumberBetween1_0And3_0())
}
Sample output is:
2.087
1.367
1.867
1.32
2.402
1.803
1.325
1.703
2.069
2.335

can I make glsl bail out of a loop when it's been running too long?

I'm doing some glsl fractals, and I'd like to make the calculations bail if they're taking too long to keep the frame rate up (without having to figure out what's good for each existing device and any future ones).
It would be nice if there were a timer I could check every 10 iterations or something....
Failing that, it seems the best approach might be to track how long it took to render the previous frame (or previous N frames) and change the "iterate to" number dynamically as a uniform...?
Or some other suggestion? :)
As it appears there's no good way to do this in the GPU, one can do a simple approach to "tune" the "bail after this number of iterations" threshold outside the loop, once per frame.
CFTimeInterval previousTimestamp = CFAbsoluteTimeGetCurrent();
// gl calls here
CFTimeInterval frameDuration = CFAbsoluteTimeGetCurrent() - previousTimestamp;
float msecs = frameDuration * 1000.0;
if (msecs < 0.2) {
_dwell = MIN(_dwell + 16., 256.);
} else if (msecs > 0.4) {
_dwell = MAX(_dwell - 4., 32.);
}
So my "dwell" is kept between 32 and 256, and more optimistically raised than decreased, and is pushed as a uniform in the "gl calls here" section.

AChartEngine in thread

I'm using AChartengine in my project. I'm showing users charts with database data.
I'm using actually 1.0.0 version of AChartEngine.
I wanted to change showing charts function in my app to threads.
Everything works but ... I've got a problem. Chart showed by runnable thread has no zooming possibilities.
On handler I've checked the GraphicalView if it is enabled. And it is. I tried so many options. Is this the AChartEngine issue?
I'm using this renderer options:
renderer.setXLabels(7);
renderer.setYLabels(10);
renderer.setLegendHeight(60);
renderer.setShowGrid(true);
renderer.setXLabelsAlign(Align.CENTER);
renderer.setYLabelsAlign(Align.RIGHT);
renderer.setZoomButtonsVisible(false);
renderer.setZoomEnabled(true);
renderer.setExternalZoomEnabled(true);
renderer.setApplyBackgroundColor(true);
renderer.setBackgroundColor(Color.WHITE);
renderer.setLabelsColor(Color.BLACK);
renderer.setMarginsColor(Color.WHITE);
renderer.setChartTitle("");
renderer.setMargins(new int[] { 15, AChartMarginLeft, 20, 15 });
renderer.setPanLimits(new double[] { x.get(0)[0].getTime(),
x.get(0)[(ileC - 1)].getTime() + (1 * 24 * 60 * 60 * 1000),
minvalY, maxY });
renderer.setZoomLimits(new double[] { x.get(0)[0].getTime(),
x.get(0)[(ileC - 1)].getTime() + (1 * 24 * 60 * 60 * 1000),
minvalY, maxY });
renderer.setPointSize(4);
renderer.setShowAxes(false);
renderer.setAxisTitleTextSize(AChartAxisTitleTextSize);
renderer.setLabelsTextSize(AChartsetLabelsTextSize);
renderer.setLegendTextSize(AChartsetLegendTextSize);
So zooming is enabled.
mChartView in handler is showing that mChartView has zoom enabled.
private final Handler myHandler = new Handler();
final Runnable updateRunnable = new Runnable() {
public void run() {
Log.d("updateRunnable","RUNNABLE");
if (mRenderer.isZoomEnabled()) {
Log.d("ZOOM ENABLED","ENABLED");
} else {
Log.d("NO","NO ZOOMING");
}
}
};
SOLUTION
Edit:
I found answer to my question. I tried so many things. It wasn't zoom/pan margins.
I moved this part from thread to handler and now zooming works. If this part was in thread the chart was OK but like I said zooming hasn't been working.
mChartView = ChartFactory.getBarChartView(getApplicationContext(),
ChartFunctions.buildBarDataset(titles, values),
renderer,type.DEFAULT);
You are setting some zoom limits that seem to be exactly your chart values range. This means that you cannot zoom outside that range.

Manipulating Opacity in Blackberry 5

I am building a news ticker that needs to be implemented on Blackberry 5. When transitioning from one element to the next, I am looking at a fade out/fade in transition. Mostly because I am having trouble finding resources on creating animations in the Blackberry 5 reference.
the basic flow I am looking at is:
public void updateUI() {
//fade out
//set values
//fade in
}
So far I have all the UI elements contained inside a HorizontalFieldManager. I have tried digging through the Field and Graphics documents, but did not find what I was looking for.
Keep in mind, supporting Blackberry 5 is the client's requirement, not mine.
You need to handle animations explicitly, using a timer for transitions.
My typical solution is something like this (inside the paint() method):
final long time = System.currentTimeMillis();
final int alpha;
if (startFadeIn != 0) {
alpha = (int) Math.min((time - startFadeIn) / SPEED, 255);
if (alpha < 255) {
invalidate();
}
} else if (startFadeOut != 0) {
alpha = (int) Math.max(255 + (startFadeOut - time) / SPEED, 0);
if (alpha > 0) {
invalidate();
}
} else {
alpha = 255;
}
graphics.setGlobalAlpha(alpha);
It burns some CPU cycles (for a short time), but it works.

Resources