Skip to content

Instantly share code, notes, and snippets.

@mdvsh
Created April 10, 2024 21:49
Show Gist options
  • Save mdvsh/06f9a3af287e761c84258dee0576920b to your computer and use it in GitHub Desktop.
Save mdvsh/06f9a3af287e761c84258dee0576920b to your computer and use it in GitHub Desktop.
Nathan Hamish C++ game engine talk

notes

talk on high performance, safe C++ enngineering

slides

firsts done by him

  • discord stuff init, in game genAI, stadia
  • 25+ c++ exp

coding standards

  • why important, if not do

type safety and init

  • init every variable, constructor, strong type
  • be specific and clear with integer types
  • specify invalid values for types. UINT8 - 1 diff from UINT32 - 1
  • handles instead of raw pointers
  • avoid keeping pointers for longer than necessary, function scope is good way to go about it
  • sparingly use auto, except for complex type declarations
    • good place is: template container iterator

classes and casting

  • minimize class hierarchies, reduce complexity, increase maintainability
  • type conversion warnings as errors really good to have
  • avoid C-style casting, reinterpret_cast<> scary
  • const_cast usage very minimal, probably doing it wrong

code structure and flow control

  • function chunking down
  • move varibales closer to declaration, get rid of early returns (if can. would help)
  • wow early returns are really hated upon...
  • SM instead of multiple bools
    • enums helpful
    • side effect handling improves
    • do everything from transitions, maintanable, debuggable
  • dont call functions in conditions of control statements
  • don't chain multiple funcs
  • obvious; but never deref value of func before checking for null
  • magic numbers bad
  • return vals should always be in a var close to func starting (debugger says thank you)

error handling and resource management

  • RAII for systems stuff
  • unhandled exception is a crash
  • check if pointers are non-null before using them,
    • use assertions to enforce this. If nullptr is exceptional, then write a debug message to the error log.

performance and multi-threading

  • profile and optimize hot paths, regularly in context of greater codebase
  • pre-mature optimization is bad, mosst of the them if thinking optimizes, doesn't until the profiler tells you
  • use mempools and cusom allocators for freq touched objects
  • avoid false sharing
  • have cors work on block of data and not interleaved
  • minimize cache misses, recall 370 struct alignment, etc
  • string hashes for comparision multitude faster
  • wow OS class mentioned!!!
  • atomics and test_set where appropriate
  • love lambdas, async and futures
  • seperation of code writing to shared memory and the readers to it
  • message passing and work queues bw r/w tasks to avoid direct data interaction/mutation
  • consider multicore cache behavior when setting up memory layout
    • DoD: array of structs, structs of arrays
  • read thread local storage where necessary

code quality and maintability

  • enforced code review
  • actively try to reduce technical debt
  • document complex design, DS and algo choices; link to wiki in code works
  • very imp: component and module architectures
  • obvious, but better naming, better cmake warning enforcement
  • schemas for file format
  • hotload very imp; for resources to allow changes
  • automated testing, QA
  • const reference and const;

cost of something broken grows exponentially from the moment it was broken

  • keep app specific code diff from low-level libs
  • interface headers: prefer to wrap 3rd party libs and legacy in narrow IH
  • any strings touching protocols or external inft should be UTF8 (/16), sticking with standards basically
  • any file must be compilable outide of bucket build
  • clang-tidy very IMP, and static analyses very IMP
  • UNIT or physics stuff important (recall rover accident)
  • Werrors very good to have
  • multiple compilers helps

consistency

  • static_asserts to enforce compile time invariants
  • eg: struct size for network? assert
  • if and endif instead of ifdef (obscure cross platform)

prepreprocessors #pragma region/endregion to organize sections of code

saving cognitive load is crucial

  • no using namespace in header
  • dont rely on static variable initialization
  • NO use of inline in class declaration
  • dont put any implementation in class declaration
    • compiler build time slows
  • typdef templated types for readability

static analyses

  • use everyone of them, all of them help in their own way, crucial, would save days
  • forward declarations when you can use it, saves build and compile time

document common pitfalls and anti-patterns specific to codebase


more resources

  1. C++ Concurrency in Action by Anthony Williams https://a.co/d/b4NyugQ
  2. The Art of Multiprocessor Programming by Maurice Herlihy and Nir Shavit https://a.co/d/2AarGER
  3. Effective Modern C++: 42 Specific Ways to Improve Your Use of C++11 and C++14 by Scott Meyers https://a.co/d/fM0vfIK
  4. Intel Threading Building Blocks: Outfitting C++ for Multi-core Processor Parallelism by James Reinders https://a.co/d/0xBcjBm
  5. Game Engine Architecture, Third Edition 3rd Edition by Jason Gregory https://a.co/d/fnZ42AM
  6. Game Programming Patterns by Robert Nystrom https://a.co/d/bxXhOIg
  7. If you CAN take a parallel / multithreading / multicore class DO
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment