piston
piston copied to clipboard
Slow 2D performance on Windows when using code from getting started tutorial
I've built a simple app using bits of code pieced together from different tutorials. However, I'm having performance issues. Or are the numbers below to be expected on a Core i7 2.2GHz?
- Drawing a solid background: 33 FPS
- Drawing 10 squares on solid background: 33 FPS
- 1 000 squares: 30 FPS
- 5 000 squares: 23 FPS
- 10 000 squares: 11 FPS
I might be just measuring FPS incorrectly but I also notice significant lag when I go above 5 000 squares. One of my CPU cores also peaks when I have more than about 5 000 squares so it seems to be CPU bound.
Windows 10 (MS Surface Pro 4), Rust 1.8, Piston 0.19.0
Complete code:
[package]
name = "test"
version = "0.1.0"
authors = ["Joel"]
[[bin]]
name = "test"
[dependencies]
piston = "0.19.0"
piston2d-graphics = "0.16.0"
piston2d-opengl_graphics = "0.26.0"
piston_window = "0.42.0"
rand = "*"
extern crate piston_window;
extern crate piston;
extern crate rand;
use piston_window::*;
use rand::Rng;
fn main() {
const SIZE: [u32; 2] = [600,600];
const GREEN: [f32; 4] = [0.0, 1.0, 0.0, 1.0];
const NUM: u32 = 5000; //change this to change number of polygons
const SQUARESIZE: f64 = 10.0;
// Create an Glutin window.
let window: PistonWindow = WindowSettings::new("test",SIZE)
.exit_on_esc(true)
.build()
.unwrap();
let mut frames = 0;
let mut passed = 0.0;
let mut rng = rand::thread_rng();
for e in window {
if let Some(_) = e.render_args() {
e.draw_2d(|c, g| {
//clear the screen.
clear(GREEN, g);
for i in 0..NUM {
//setting up so that it looks pretty
let x = (i % SIZE[0]) as f64;
let y = (i % SIZE[1]) as f64;
let fill = (x / (SIZE[0] as f64)) as f32;
let color: [f32; 4] = [fill,1.0-fill,fill,fill];
let x = rng.gen_range::<f64>(0.0,SIZE[0] as f64);
//draw the square
let square = rectangle::square(0.0, 0.0, SQUARESIZE);
let transform = c.transform.trans(x-SQUARESIZE/2.0,y-SQUARESIZE/2.0);
rectangle(color, square, transform, g);
}
frames+=1;
});
}
if let Some(u) = e.update_args() {
passed += u.dt;
if passed > 1.0 {
let fps = (frames as f64) / passed;
println!("FPS: {}",fps);
frames = 0;
passed = 0.0;
}
}
}
}
Thanks for your help and apologies if this is not the correct place for such questions.
Do you run in with --release
? The OpenGL back-end is not optimized yet.
Notice that if you're running in debug mode, the numbers you get aren't reliable at all. In release mode there are often changes in the bottlenecks.
You can use the fps_counter library.
Also, if you call window.set_bench_mode(true)
the game loop will render as fast as it can with no sleep, so you can time the overall performance. This gives better accuracy.
I don't remember which version of piston_window which uses the faster Gfx back-end, but it's around 0.42.0 somewhere. I recommend trying the newest version.
You don't need the piston crate when using piston_window, because everything is reexported. Just use piston_window::*
.
I'm running in release mode.
Currently I'm using piston_window 0.42.0, if I try to use 0.43.0 or higher I get error: the trait core::iter::Iterator is not implemented for the type piston_window::PistonWindow
Using window.set_bench_mode(true)
changes the behaviour: it now says about 60 FPS, however it still looks laggy, and the prints are coming much farther apart than one second. My counter is supposed to print when the dt
of update_args
adds up to 1, but that seems to take much longer than 1 second when in bench mode. Maybe my counter is flawed (I can take a look at fps_counter), but it's quite apparent that the framerate is low, judging from the lag.
EDIT: In fact, bench mode seems to make the lag much worse.
I managed to update to 0.47.0 by modifying my game loop code. I still get the same framerate though.
Closing as outdated.