stocking

git clone https://git.bradleygannon.com/stocking.git
Log | Files | Refs

commit 80ef6c1054dda705e6a4dd4a527ee81cf06115a9
parent ccbf1e22718c6d1d30caecb647c878480e6377d5
Author: Bradley Gannon <bradley@bradleygannon.com>
Date:   Thu, 18 Dec 2025 18:26:02 -0500

Add some performance tracking and optimizations

Diffstat:
A.cargo/config.toml | 2++
MCargo.toml | 5+++++
Msrc/camera.rs | 31+++++++++++++++++++++++++------
Msrc/main.rs | 5+++--
4 files changed, 35 insertions(+), 8 deletions(-)

diff --git a/.cargo/config.toml b/.cargo/config.toml @@ -0,0 +1,2 @@ +[build] +rustflags = ["-C", "target-cpu=native"] diff --git a/Cargo.toml b/Cargo.toml @@ -4,3 +4,8 @@ version = "0.1.0" edition = "2024" [dependencies] + +[profile.release] +codegen-units = 1 +lto = "fat" +panic = "abort" diff --git a/src/camera.rs b/src/camera.rs @@ -1,9 +1,12 @@ +use std::time::Instant; + use crate::{ color::LinearColor, hittable::Hittable, interval::Interval, random::RandomNumberGenerator, ray::Ray, vec3::Vec3, }; -struct Image { +#[derive(Clone, Debug, PartialEq, PartialOrd)] +pub struct Image { data: Vec<Vec<LinearColor>>, } @@ -17,7 +20,7 @@ impl Image { data: vec![vec![LinearColor::default(); width]; height], } } - fn to_ppm_string(&self) -> String { + pub fn to_ppm_string(&self) -> String { let mut output = "P3\n".to_string(); let height = self.data.len(); let width = if height > 0 { self.data[0].len() } else { 0 }; @@ -143,10 +146,12 @@ impl Camera { } } - pub fn render(&mut self, world: &[Box<dyn Hittable>]) { + pub fn render(&mut self, world: &[Box<dyn Hittable>]) -> Image { let mut image = Image::new(self.image_width, self.image_height); - for i in 0..self.image_width { - for j in 0..self.image_height { + let image_start = Instant::now(); + for j in 0..self.image_height { + let line_start = Instant::now(); + for i in 0..self.image_width { let mut pixel_color = LinearColor::new(0., 0., 0.); for _ in 0..self.samples_per_pixel { let r = self.get_ray(i, j); @@ -155,8 +160,22 @@ impl Camera { } image.data[j][i] = pixel_color; } + let line_duration = line_start.elapsed(); + let pixels_per_second = self.image_width as f64 / line_duration.as_secs_f64(); + eprint!( + "\rLine {:>5}/{:>5} ({:.2} pixels / second) ", + j + 1, + self.image_height, + pixels_per_second + ); } - println!("{}", image.to_ppm_string()); + let image_duration = image_start.elapsed(); + eprintln!( + "\rDone in {:.1} seconds ({:.1} pixels / second) ", + image_duration.as_secs_f64(), + self.image_width as f64 * self.image_height as f64 / image_duration.as_secs_f64() + ); + image } fn ray_color(&mut self, r: &Ray, world: &[Box<dyn Hittable>], depth: usize) -> LinearColor { diff --git a/src/main.rs b/src/main.rs @@ -80,7 +80,7 @@ fn main() { let config = CameraConfig { aspect_ratio: 16. / 9., image_width: 1200, - samples_per_pixel: 500, + samples_per_pixel: 300, max_bounces: 50, field_of_view_degrees: 20., look_from: Vec3::new(13., 2., 3.), @@ -91,5 +91,6 @@ fn main() { rng, }; let mut camera = Camera::new(&config); - camera.render(&world); + let image = camera.render(&world); + println!("{}", image.to_ppm_string()); }