0% found this document useful (0 votes)
121 views

The Rust Programming Language For Game Tooling: Dan Olson Principal Software Architect

The document discusses using Rust for game tooling. It provides an overview of Rust and examples comparing code to calculate MD5 sums in different languages. Rust code is shown to be easy to read and write while efficiently handling errors. The author also pitches Rust's efficiency of writing code like Python and running code like C++, and its large ecosystem of libraries and integrated build/package/test tool.

Uploaded by

Ruboto Boto
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
121 views

The Rust Programming Language For Game Tooling: Dan Olson Principal Software Architect

The document discusses using Rust for game tooling. It provides an overview of Rust and examples comparing code to calculate MD5 sums in different languages. Rust code is shown to be easy to read and write while efficiently handling errors. The author also pitches Rust's efficiency of writing code like Python and running code like C++, and its large ecosystem of libraries and integrated build/package/test tool.

Uploaded by

Ruboto Boto
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 42

The Rust Programming

Language for Game Tooling

Dan Olson
Principal Software Architect
Who am I?
• Working in games since 2004, Treyarch since 2008.

• Core Engine team.

• Focused on data pipeline and infrastructure tooling.

The Rust Programming Language For Game Tooling


What is Rust?
• Started by Mozilla in 2006, stable release in 2015.

• Currently supported by Amazon, Facebook, Microsoft, and others.

• Focused on security and performance.

The Rust Programming Language For Game Tooling


Outline
• The case for Rust.

• Survey of several interesting uses for Rust.

• Integrating Rust at Treyarch.

The Rust Programming Language For Game Tooling


Code comparison: md5sum
• Easy to read. hasher = hashlib.md5()
with open(filename, 'rb') as f:
• Easy to write. hasher.update(f.read())
print(hasher.hexdigest())
• Errors are handled.

• Performs well.

The Rust Programming Language For Game Tooling


Code comparison: md5sum
• Easy to read. 😀 hasher = hashlib.md5()
with open(filename, 'rb') as f:
• Easy to write. 😀 hasher.update(f.read())
print(hasher.hexdigest())
• Errors are handled.

• Performs well.

The Rust Programming Language For Game Tooling


Code comparison: md5sum
• Easy to read. 😀 hasher = hashlib.md5()
with open(filename, 'rb') as f:
• Easy to write. 😀 hasher.update(f.read())
print(hasher.hexdigest())
• Errors are handled. 😐

• Performs well.

The Rust Programming Language For Game Tooling


Code comparison: md5sum
• Easy to read. 😀 hasher = hashlib.md5()
with open(filename, 'rb') as f:
• Easy to write. 😀 hasher.update(f.read())
print(hasher.hexdigest())
• Errors are handled. 😐

• Performs well. 🤔

The Rust Programming Language For Game Tooling


Code comparison: md5sum
int file_descript = open(filename, O_RDONLY);
• Easy to read. if(file_descript < 0) exit(-1);

• Easy to write. unsigned long file_size =


get_size_by_fd(file_descript);
• Errors are handled.
char* file_buffer = mmap(0, file_size,
PROT_READ, MAP_SHARED, file_descript, 0);
• Performs well. MD5((unsigned char*) file_buffer, file_size,
result);
munmap(file_buffer, file_size);

print_md5_sum(result);
Source: https://stackoverflow.com/a/1220177/69283

The Rust Programming Language For Game Tooling


Code comparison: md5sum
int file_descript = open(filename, O_RDONLY);
• Easy to read. 😐 if(file_descript < 0) exit(-1);

• Easy to write. unsigned long file_size =


get_size_by_fd(file_descript);
• Errors are handled.
char* file_buffer = mmap(0, file_size,
PROT_READ, MAP_SHARED, file_descript, 0);
• Performs well. MD5((unsigned char*) file_buffer, file_size,
result);
munmap(file_buffer, file_size);

print_md5_sum(result);
Source: https://stackoverflow.com/a/1220177/69283

The Rust Programming Language For Game Tooling


Code comparison: md5sum
int file_descript = open(filename, O_RDONLY);
• Easy to read. 😐 if(file_descript < 0) exit(-1);

• Easy to write. 😢 unsigned long file_size =


get_size_by_fd(file_descript);
• Errors are handled.
char* file_buffer = mmap(0, file_size,
PROT_READ, MAP_SHARED, file_descript, 0);
• Performs well. MD5((unsigned char*) file_buffer, file_size,
result);
munmap(file_buffer, file_size);

print_md5_sum(result);
Source: https://stackoverflow.com/a/1220177/69283

The Rust Programming Language For Game Tooling


Code comparison: md5sum
int file_descript = open(filename, O_RDONLY);
• Easy to read. 😐 if(file_descript < 0) exit(-1);

• Easy to write. 😢 unsigned long file_size =


get_size_by_fd(file_descript);
• Errors are handled. 😬
char* file_buffer = mmap(0, file_size,
PROT_READ, MAP_SHARED, file_descript, 0);
• Performs well. MD5((unsigned char*) file_buffer, file_size,
result);
munmap(file_buffer, file_size);

print_md5_sum(result);
Source: https://stackoverflow.com/a/1220177/69283

The Rust Programming Language For Game Tooling


Code comparison: md5sum
int file_descript = open(filename, O_RDONLY);
• Easy to read. 😐 if(file_descript < 0) exit(-1);

• Easy to write. 😢 unsigned long file_size =


get_size_by_fd(file_descript);
• Errors are handled. 😬
char* file_buffer = mmap(0, file_size,
PROT_READ, MAP_SHARED, file_descript, 0);
• Performs well. 😀 MD5((unsigned char*) file_buffer, file_size,
result);
munmap(file_buffer, file_size);

print_md5_sum(result);
Source: https://stackoverflow.com/a/1220177/69283

The Rust Programming Language For Game Tooling


Code comparison: md5sum
• Easy to read. let data = std::fs::read(filename)?;
let hash = md5::compute(&data);
• Easy to write. println!("{:x}", hash);

• Errors are handled.

• Performs well.

The Rust Programming Language For Game Tooling


Code comparison: md5sum
• Easy to read. 😀 let data = std::fs::read(filename)?;
let hash = md5::compute(&data);
• Easy to write. 😀 println!("{:x}", hash);

• Errors are handled.

• Performs well.

The Rust Programming Language For Game Tooling


Code comparison: md5sum
• Easy to read. 😀 let data = std::fs::read(filename)?;
let hash = md5::compute(&data);
• Easy to write. 😀 println!("{:x}", hash);

• Errors are handled. 😐

• Performs well.

The Rust Programming Language For Game Tooling


Code comparison: md5sum
• Easy to read. 😀 let data = std::fs::read(filename)?;
let hash = md5::compute(&data);
• Easy to write. 😀 println!("{:x}", hash);

• Errors are handled. 😐

• Performs well. 😀

The Rust Programming Language For Game Tooling


Dan’s Rust Sales Pitch
• Efficiency of writing code: closer to Python.

• Efficiency of running code: closer to C++.

• Large, centralized ecosystem of “crates”, or community libraries (https://crates.io/).

• Integrated build + package + test tool (“cargo”).

The Rust Programming Language For Game Tooling


Code comparison: md5sum
q:\>cargo new md5sum
Created binary (application) `md5sum` package
q:\>cd md5sum
q:\md5sum>cargo add md5
Adding md5 v0.7.0 to dependencies
q:\md5sum>cargo run -- src/main.rs
Compiling md5 v0.7.0
Compiling md5sum v0.1.0 (Q:\md5sum)
Finished dev [unoptimized + debuginfo] target(s) in 1.66s
Running `target\debug\md5sum.exe src/main.rs`
4911739566caf58bf40be5b6d6a19262

The Rust Programming Language For Game Tooling


Code comparison: md5sum
q:\>cargo new md5sum
Created binary (application) `md5sum` package
q:\>cd md5sum
q:\md5sum>cargo add md5
Adding md5 v0.7.0 to dependencies
q:\md5sum>cargo run -- src/main.rs
Compiling md5 v0.7.0
Compiling md5sum v0.1.0 (Q:\md5sum)
Finished dev [unoptimized + debuginfo] target(s) in 1.66s
Running `target\debug\md5sum.exe src/main.rs`
4911739566caf58bf40be5b6d6a19262

The Rust Programming Language For Game Tooling


Code comparison: md5sum
q:\>cargo new md5sum
Created binary (application) `md5sum` package
q:\>cd md5sum
q:\md5sum>cargo add md5
Adding md5 v0.7.0 to dependencies
q:\md5sum>cargo run -- src/main.rs
Compiling md5 v0.7.0
Compiling md5sum v0.1.0 (Q:\md5sum)
Finished dev [unoptimized + debuginfo] target(s) in 1.66s
Running `target\debug\md5sum.exe src/main.rs`
4911739566caf58bf40be5b6d6a19262

The Rust Programming Language For Game Tooling


Code comparison: md5sum
q:\>cargo new md5sum
Created binary (application) `md5sum` package
q:\>cd md5sum
q:\md5sum>cargo add md5
Adding md5 v0.7.0 to dependencies
q:\md5sum>cargo run -- src/main.rs
Compiling md5 v0.7.0
Compiling md5sum v0.1.0 (Q:\md5sum)
Finished dev [unoptimized + debuginfo] target(s) in 1.66s
Running `target\debug\md5sum.exe src/main.rs`
4911739566caf58bf40be5b6d6a19262

The Rust Programming Language For Game Tooling


Dan’s Rust Sales Pitch
• Efficiency of writing code: closer to Python.

• Efficiency of running code: closer to C++.

• Large, centralized ecosystem of “crates”, or community libraries (https://crates.io/).

• Integrated build + package + test tool (“cargo”).

• Static, compile-time validation of common memory problems.

• Static, compile-time validation of common multithreading problems.

The Rust Programming Language For Game Tooling


Case study: Treyarch Image Packer
• Rust version deployed in 2018.

• Heavily multithreaded.

• Active development throughout its lifetime.

• Total “crash” issues encountered: 2.

The Rust Programming Language For Game Tooling


Dan’s Rust Sales Pitch
• Efficiency of writing code: closer to Python.

• Efficiency of running code: closer to C++.

• Large, centralized ecosystem of “crates”, or community libraries (https://crates.io/).

• Integrated build + package + test tool (“cargo”).

• Static, compile-time validation of common memory problems.

• Static, compile-time validation of common multithreading problems.

The Rust Programming Language For Game Tooling


Rust for Game Tools
• Error Handling

• Multithreading

• Parsing Text

• Command Line Interfaces

• Parsing Debug Info

• C ABI compatibility

• Web Applications

• GUIs
The Rust Programming Language For Game Tooling
1/8 - Error Handling
• Result – holds the success or failure state of an operation.

• Panic – instant program failure for unrecoverable errors.

• ? Operator – pass a failed Result up the callstack.

let file = std::fs::read(path)?;

• Use the anyhow crate to add context to errors.

The Rust Programming Language For Game Tooling


1/8 - Error Handling

Error: The system cannot find the file specified.


let file = std::fs::read(path)?;
(os error 2)

let file = std::fs::read(path)


.with_context(|| format!("Reading contents of {:?}", path))?;

Error: Reading contents of "test.txt"

Caused by:
The system cannot find the file specified. (os error 2)

The Rust Programming Language For Game Tooling


2/8 - Multithreading
• Using the rayon crate, multithreading is quick, easy, and safe.

file_names file_names
.iter() .par_iter()
.map(|x| hash_file(x)) .map(|x| hash_file(x))
.collect(); .collect();

The Rust Programming Language For Game Tooling


2/8 - Multithreading
• Using the rayon crate, multithreading is quick, easy, and safe.

file_names
.par_iter()
.map(|x| hash_file(x, &mut count))
.collect();

The Rust Programming Language For Game Tooling


3/8 - Parsing Text
• Use the serde crate for generic serialization/deserialization.

#[derive(Deserialize)]
struct Config {
string: String,
number: i32,
list: Vec<String>,
}

let config: Config = serde_json::from_str(&text)?;

let config: Config = serde_yaml::from_str(&text)?;

The Rust Programming Language For Game Tooling


4/8 - Command Line Interfaces
• Use the structopt crate to create command line interfaces.
sourcehash
/// Generate
0.1.0a hash of all source and include files specified
Generate
by one aor
hash
more
of.vcxproj
all source
files.
and include files specified by one or
more
#[derive(StructOpt)]
.vcxproj files
struct SourceHash {
USAGE: /// One or more vcxproj files contributing to the hash.
sourcehash.exe
#[structopt(parse(from_os_str))]
[FLAGS] [files]...
files: Vec<PathBuf>,
FLAGS:
-h,#[structopt(long)]
--help Prints help information
-V,verbose:
--version
bool, Prints version information
} --verbose

ARGS: let options = SourceHash::from_args();


The Rust Programming Language For Game Tooling

<files>... One or more vcxproj files contributing to the hash


5/8 - Parsing Debug Info
gz_header_s - 80 bytes, 12 padding
• Use pdb (win) and gimli (elf) crates to (optimal size should be 72 bytes, 4 padding)
struct gz_header_s
inspect debug info. {
int text; // 4 bytes
<padding> ; // 4 bytes
• This tool is now open-sourced! uLong time; // 8 bytes
int xflags; // 4 bytes
int os; // 4 bytes
• https://github.com/Activision/structpack Bytef* extra; // 8 bytes
uInt extra_len; // 4 bytes
uInt extra_max; // 4 bytes
Bytef* name; // 8 bytes
uInt name_max; // 4 bytes
<padding> ; // 4 bytes
Bytef* comment; // 8 bytes
uInt comm_max; // 4 bytes
int hcrc; // 4 bytes
int done; // 4 bytes
<padding> ; // 4 bytes
};

The Rust Programming Language For Game Tooling


6/8 - C ABI compatibility
• Bind Rust code to other languages (e.g. python, nodejs, C, wasm).
/// Formats the sum of two numbers as string.
#[pyfunction]
fn sum_as_string(a: usize, b: usize) -> PyResult<String> {
Ok((a + b).to_string())
}

/// A Python module implemented in Rust.


#[pymodule]
fn string_sum(py: Python, m: &PyModule) -> PyResult<()> {
m.add_function(wrap_pyfunction!(sum_as_string, m)?)?;

Ok(())
}
Source: https://crates.io/crates/pyo3
The Rust Programming Language For Game Tooling
7/8 - Web Applications
• There are lots and lots of crates for web apps. I like rouille for quick, simple ones.
rouille::start_server("0.0.0.0:80", move |request| {
Response::text("hello world")
});
Source: https://docs.rs/rouille/3.1.1/rouille/
• But tide or actix-web might be better for more substantial apps.
#[async_std::main]
async fn main() -> tide::Result<()> {
let mut app = tide::new();
app.at("/orders/shoes").post(order_shoes);
app.listen("127.0.0.1:8080").await?;
Ok(())
}
Source: https://crates.io/crates/tide
The Rust Programming Language For Game Tooling
8/8 - GUIs
• Native Rust: iced, druid, egui

• C++ Bindings: ritual (Qt), relm (Gtk), imgui-rs, web-view

ui.heading("My egui Application");


ui.horizontal(|ui| {
ui.label("Your name: ");
ui.text_edit_singleline(&mut name);
});
ui.add(egui::Slider::new(&mut age, 0..=120).text("age"));
if ui.button("Click each year").clicked() {
age += 1;
}
ui.label(format!("Hello '{}', age {}", name, age));

Source: https://crates.io/crates/egui

The Rust Programming Language For Game Tooling


Integrating Rust at Treyarch
• Started work in late 2017.

• 3 major tools, around 20 smaller one-off tools.

• Around 120K LOC

• 27 individual contributors.

• Extremely high stability.

The Rust Programming Language For Game Tooling


Rust Downsides
• Steep learning curve… very different from C++.

• Complicated language… lots of corners.

• Relies heavily on ecosystem.

• Compile times as bad as or worse than C++.

Managing these downsides is key to successful integration!

The Rust Programming Language For Game Tooling


Integration Tips
• Communicate!

• Keep Rust siloed off until there is a critical mass of experience.


▪ Find an unmaintained tool and make it better!

• Start with the best workflow.


▪ vscode + rust_analyzer + cargo-edit + rustfmt + clippy

• Bad Rust code has the same safety guarantees as good Rust code!

• Initial hurdles are high, but large productivity gains after they are cleared.

• Provide time and space to both learn and teach.


▪ Presentations, courses, examples, code reviews.

The Rust Programming Language For Game Tooling


Learning Resources
• Dive into code!
▪ https://leetcode.com/
▪ https://adventofcode.com/

• Dive into a book!


▪ “The Rust Programming Language” – Klabnik & Nichols
▪ “Programming Rust” – Blandy & Orendorff

• Dive into online resources!


▪ https://www.rust-lang.org/learn
▪ https://play.rust-lang.org/

The Rust Programming Language For Game Tooling


Thank you!
We’re Hiring!

Gameplay Engineers (mid/senior)


UI Engineers (mid/senior)
Online Engineers (mid/senior)
Senior Test Automation Engineers

And many more!

https://careers.treyarch.com/

You might also like