Apply performance tracing to various functions

This commit is contained in:
Savanni D'Gerinel 2023-06-14 23:47:12 -04:00
parent ef045117be
commit 6456389eef
4 changed files with 117 additions and 101 deletions

View File

@ -19,3 +19,14 @@ impl CoreApi {
}); });
} }
} }
pub fn perftrace<F, A>(trace_name: &str, f: F) -> A
where
F: FnOnce() -> A,
{
let start = std::time::Instant::now();
let result = f();
let end = std::time::Instant::now();
println!("[Trace: {}] {:?}", trace_name, end - start);
return result;
}

View File

@ -1,43 +1,35 @@
use gtk::prelude::*; use gtk::prelude::*;
use kifu_core::{CoreApp, CoreRequest, CoreResponse}; use kifu_core::{CoreApp, CoreRequest, CoreResponse};
use kifu_gtk::{ use kifu_gtk::{
perftrace,
ui::{NewGame, PlayingField}, ui::{NewGame, PlayingField},
CoreApi, CoreApi,
}; };
use std::sync::{Arc, RwLock}; use std::sync::{Arc, RwLock};
fn perftrace<F, A>(trace_name: &str, f: F) -> A
where
F: FnOnce() -> A,
{
let start = std::time::Instant::now();
let result = f();
let end = std::time::Instant::now();
println!("[Trace: {}] {:?}", trace_name, end - start);
return result;
}
fn handle_response(api: CoreApi, window: gtk::ApplicationWindow, message: CoreResponse) { fn handle_response(api: CoreApi, window: gtk::ApplicationWindow, message: CoreResponse) {
let playing_field = Arc::new(RwLock::new(None)); let playing_field = Arc::new(RwLock::new(None));
match message { match message {
CoreResponse::NewGameView(view) => { CoreResponse::NewGameView(view) => perftrace("NewGameView", || {
let api = api.clone(); let api = api.clone();
let new_game = NewGame::new(api, view); let new_game = NewGame::new(api, view);
window.set_child(Some(&new_game)); window.set_child(Some(&new_game));
} }),
CoreResponse::PlayingFieldView(view) => { CoreResponse::PlayingFieldView(view) => perftrace("PlayingFieldView", || {
let api = api.clone(); let api = api.clone();
let mut playing_field = playing_field.write().unwrap(); let mut playing_field = playing_field.write().unwrap();
if playing_field.is_none() { if playing_field.is_none() {
let field = PlayingField::new(api, view); perftrace("creating a new playing field", || {
window.set_child(Some(&field)); let field = PlayingField::new(api, view);
*playing_field = Some(field); window.set_child(Some(&field));
*playing_field = Some(field);
})
} else { } else {
playing_field.as_ref().map(|field| field.update_view(view)); playing_field.as_ref().map(|field| field.update_view(view));
} }
} }),
} }
} }

View File

@ -1,4 +1,4 @@
use crate::CoreApi; use crate::{perftrace, CoreApi};
use gio::resources_lookup_data; use gio::resources_lookup_data;
use glib::Object; use glib::Object;
use gtk::{ use gtk::{
@ -83,86 +83,88 @@ impl ObjectImpl for BoardPrivate {
self.drawing_area self.drawing_area
.set_draw_func(move |_, context, width, height| { .set_draw_func(move |_, context, width, height| {
let render_start = std::time::Instant::now(); perftrace("render drawing area", || {
let board = board.borrow(); let render_start = std::time::Instant::now();
let board = board.borrow();
match background { match background {
Ok(Some(ref background)) => { Ok(Some(ref background)) => {
context.set_source_pixbuf(&background, 0., 0.); context.set_source_pixbuf(&background, 0., 0.);
context.paint().expect("paint should succeed"); context.paint().expect("paint should succeed");
} }
Ok(None) | Err(_) => context.set_source_rgb(0.7, 0.7, 0.7), Ok(None) | Err(_) => context.set_source_rgb(0.7, 0.7, 0.7),
}; };
let _ = context.paint(); let _ = context.paint();
context.set_source_rgb(0.1, 0.1, 0.1); context.set_source_rgb(0.1, 0.1, 0.1);
context.set_line_width(2.); context.set_line_width(2.);
let hspace_between = ((width - 40) as f64) / ((board.size.width - 1) as f64); let hspace_between = ((width - 40) as f64) / ((board.size.width - 1) as f64);
let vspace_between = ((height - 40) as f64) / ((board.size.height - 1) as f64); let vspace_between = ((height - 40) as f64) / ((board.size.height - 1) as f64);
let pen = Pen { let pen = Pen {
x_offset: MARGIN as f64, x_offset: MARGIN as f64,
y_offset: MARGIN as f64, y_offset: MARGIN as f64,
hspace_between, hspace_between,
vspace_between, vspace_between,
}; };
(0..board.size.width).for_each(|col| { (0..board.size.width).for_each(|col| {
context.move_to( context.move_to(
(MARGIN as f64) + (col as f64) * hspace_between, (MARGIN as f64) + (col as f64) * hspace_between,
MARGIN as f64, MARGIN as f64,
); );
context.line_to( context.line_to(
(MARGIN as f64) + (col as f64) * hspace_between, (MARGIN as f64) + (col as f64) * hspace_between,
(height as f64) - (MARGIN as f64), (height as f64) - (MARGIN as f64),
); );
let _ = context.stroke(); let _ = context.stroke();
}); });
(0..board.size.height).for_each(|row| { (0..board.size.height).for_each(|row| {
context.move_to( context.move_to(
MARGIN as f64, MARGIN as f64,
(MARGIN as f64) + (row as f64) * vspace_between, (MARGIN as f64) + (row as f64) * vspace_between,
); );
context.line_to( context.line_to(
(width - MARGIN) as f64, (width - MARGIN) as f64,
(MARGIN as f64) + (row as f64) * vspace_between, (MARGIN as f64) + (row as f64) * vspace_between,
); );
let _ = context.stroke(); let _ = context.stroke();
});
context.set_source_rgb(0.1, 0.1, 0.0);
vec![3, 9, 15].into_iter().for_each(|col| {
vec![3, 9, 15].into_iter().for_each(|row| {
pen.star_point(context, col, row);
}); });
});
(0..19).for_each(|col| { context.set_source_rgb(0.1, 0.1, 0.0);
(0..19).for_each(|row| { vec![3, 9, 15].into_iter().for_each(|col| {
match board.stone(row, col) { vec![3, 9, 15].into_iter().for_each(|row| {
IntersectionElement::Filled(stone) => { pen.star_point(context, col, row);
pen.stone(&context, row, col, stone.color, stone.liberties); });
} });
(0..19).for_each(|col| {
(0..19).for_each(|row| {
match board.stone(row, col) {
IntersectionElement::Filled(stone) => {
pen.stone(&context, row, col, stone.color, stone.liberties);
}
_ => {}
};
})
});
let cursor = cursor_location.borrow();
match *cursor {
None => {}
Some(ref cursor) => match board.stone(cursor.row, cursor.column) {
IntersectionElement::Empty(_) => pen.ghost_stone(
context,
cursor.row,
cursor.column,
*current_player.borrow(),
),
_ => {} _ => {}
}; },
}) }
}); let render_end = std::time::Instant::now();
println!("board rendering time: {:?}", render_end - render_start);
let cursor = cursor_location.borrow(); })
match *cursor {
None => {}
Some(ref cursor) => match board.stone(cursor.row, cursor.column) {
IntersectionElement::Empty(_) => pen.ghost_stone(
context,
cursor.row,
cursor.column,
*current_player.borrow(),
),
_ => {}
},
}
let render_end = std::time::Instant::now();
println!("board rendering time: {:?}", render_end - render_start);
}); });
let motion_controller = gtk::EventControllerMotion::new(); let motion_controller = gtk::EventControllerMotion::new();

View File

@ -1,8 +1,17 @@
use crate::ui::{Board, Chat, PlayerCard}; use crate::{
use crate::CoreApi; perftrace,
ui::{Board, Chat, PlayerCard},
CoreApi,
};
use glib::Object; use glib::Object;
use gtk::{prelude::*, subclass::prelude::*}; use gtk::{prelude::*, subclass::prelude::*};
use kifu_core::ui::PlayingFieldView; use kifu_core::{
ui::{
BoardElement, ChatElement, IntersectionElement, PlayerCardElement, PlayingFieldView,
StoneElement, TextFieldElement,
},
Color, CoreApp, Size,
};
use std::{cell::RefCell, rc::Rc}; use std::{cell::RefCell, rc::Rc};
pub struct PlayingFieldPrivate { pub struct PlayingFieldPrivate {
@ -69,10 +78,12 @@ impl PlayingField {
} }
pub fn update_view(&self, view: PlayingFieldView) { pub fn update_view(&self, view: PlayingFieldView) {
self.imp().board.borrow().as_ref().map(|board| { perftrace("update_view", || {
board.set_board(view.board); self.imp().board.borrow().as_ref().map(|board| {
board.set_current_player(view.current_player); board.set_board(view.board);
}); board.set_current_player(view.current_player);
});
})
} }
} }
@ -82,8 +93,8 @@ pub fn playing_field_view() -> PlayingFieldView {
width: 19, width: 19,
height: 19, height: 19,
}); });
*board.stone_mut(4, 4) = IntersectionElement::Filled(StoneElement::new(Color::White)); *board.stone_mut(4, 4) = IntersectionElement::Filled(StoneElement::new(Color::White, None));
*board.stone_mut(15, 15) = IntersectionElement::Filled(StoneElement::new(Color::Black)); *board.stone_mut(15, 15) = IntersectionElement::Filled(StoneElement::new(Color::Black, None));
*board.stone_mut(18, 18) = IntersectionElement::Unplayable; *board.stone_mut(18, 18) = IntersectionElement::Unplayable;
let player_card_black = PlayerCardElement { let player_card_black = PlayerCardElement {
color: Color::Black, color: Color::Black,