an image

Handmade Boston 2023

First Handmade Conference on the East Coast.

Abner running since 2019.

An experiment -- Can we create more mentor-pupil relationships in the industry.

Ryan Fleury - Mastering Arenas

Systems Programmer, Epic Games

Claim: Every programmer should be at least familiar with how to solve this problem.

Quote: Casey Muratori - Handmade Hero - Day 57 : "I don't spend a lot of time thinking about memory."

Flip-flop diagram. flip_flop.jpg

A -> xform -> B

Linear memory? Virtual Address Space -> Physical Memory Virtual: 256 TB Physical: 8, 16, 32 GB https://en.wikipedia.org/wiki/Virtual_address_space

"Paged out to disk"

How to avoid conflict where two processes (accidentally) share memory.

alloc(size) : The allocator layer decides not to share the same memory to two processes.

Address space and physical memory are not infinite.

Kent Mitchell email Technical Consultant "An amusing story about a practical use of the null garbage collector" LOL

  1. Your program ending is its own "null garbage collector".

  2. "Lifetimes" - For every alloc, you have a symmetric free.

entity_alloc, entity_free

Problems with memory:

In C, these two calls are malloc and free.

glibc's malloc implementation is 5611 LOC.

Contention between threads accessing global allocator.

Q: Is malloc a C wrapper over an OS api?

Running code on microcontrollers: can't use code that assumes a dynamic allocator.

Failing half-way through freeing memory makes it difficult to recover and cleanup correctly.

  1. "Lifetime Soup" = Bad?

Things are in groups. Mentioned in "the Mike Acton talk".

Q: Which Mike Acton talk?

For the stack, lifetimes are corrolated with the scope. Implementing a stack is significantly easier than managing lifetimes: There is a stack pointer. Each allocation bumps the stack pointer. The OS still pays the cost to reserve memory for the stack, but it's done once per thread.

Why is everything not done on the stack?

Problem: foo can't ask bar to allocate some memory for foo's use. Workaround: Allocate in foo, ask bar to initialize. Workaround doesn't always work well: sometimes bar really should allocate, because it has the right information.

Recursive function. The data is too big. Need to share data between threads. Need to grow a data structure dynamically.

1 stack has limits. What about having N of them?

Arena: A linear allocator used to bundle lifetimes.

arena_alloc, arena_release, arena_clear.

One arena -> One lifetime stack.

Q: Nested arenas?

Back to the foo, bar problem: foo passes the arena to bar.

Examples:

WHat happens when you fill the arena?

Q: Why is reserving virtual address space cheaper than physical memory? Q: What syscalls or OS calls are related to reserving virtual address space instead of malloc? Q: What is "reserve commit"?

Answer: On linux, mmap.

Arena allocator is ~200 LOC

Q: Why use a scratch buffer instead of the stack?

Answer: Composability? (I didn't understand the answer here.) Helper code, auxiliary functions can work for both sets of problems.

Q: What kind of helper code, auxiliary functions do you tend to have?

Answer: Diagnostics, logging, visualizations.

Q: What kinds of issues might I create if I use scratch arenas in async code?

Problem: Can't free things in the middle of the arena. Solution: Use a free list. Keep track of what you'd like to free. When you allocate, check the freelist. When you free, push onto the free list. If there's one type, you have a PoolAllocator on top of an arena allocator. Alternatively, you have an AtlasAllocator. (Implementation with a quadtree?)

Demo. Visual diagnostic of three arenas: arena, name_chunk_arena (for string chunks), entities_arena. Each arena is 64GB reserved, small amount committed.

Observation: .... Oops, I forgot it.

Observation: The speaker passes a State* into his functions in the same way I use a global world or app or state.

Q: Is the basic argument that the memory problems listed before go away because there are so few arenas compared to the number of elements you are working with in the lifetime soup example? e.g. 10 alloc/frees instead of hundreds.

Q: You mentioned hesitation around object-oriented value of encapsulation. I noticed that you point a State* that likely exposes more than what each function needs. Working in games, I've developed a similar habit of having a global or pseudo-global world, app or state object, because it's simplified a number of things for me: where to store things, how to expose things, refactoring "layers", etc. Can you speak at all about this pattern -- when and how you use it, and whether you've encountered this pattern in codebases with many other programmers (e.g. does Unreal Engine have a pattern like this)?

Q: What is meta-desk?

Idea: Write rust code as C-like as possible: e.g. use arena allocator, but benefit from rust dev experience (cargo, rustup, etc).

https://crates.io/crates/bumpalo

Q: Are there any debug-versions of your allocator?

Can use the "address sanitizer" to help with things.

Q: When you use a scratch allocator, do you replace all of the space you would have reserved on the stack for Foos to Foo*s?

TODO: They mentioned a talk about JSON. FInd out what that is.

Q: Are there use cases where you are writing a library and expect the caller to be opinionated about allocations and frees?

Freya Holmér

Educator, twitter, mathematics, "shader sorceress".

It's good to do completely useless things because you care about them.

Technical Art - Shaders, Tools for Artists

Create educational content online.

Math != Code. Code != Math.

This talk was very visual and I didn't take many notes.

Jasper St. Pierre

Graphics programmer in the games industry (8 years in industry). Love shaders, shadow maps, materials and all this stuff.

Big passion for making graphics more understandable.

Boundary Break series?

https://magcius.github.io/xplain/article/x-basics.html https://renderdoc.org/ https://noclip.website/

Differed shading popularized in the early 2000s.

This talk is about how

RenderDoc: An invaluable tool for day-t-day job. Render debugger.

KodeLife: Real-time GPU shader editor

Johann Heinrich Lambert:

Q: RGB linear space? Gamma? How sensitive we are to different hues / intensities?

A: https://en.wikipedia.org/wiki/Gamma_correction

Q: Luma-chroma encoding?

A: https://en.wikipedia.org/wiki/Y%E2%80%B2UV

A: https://en.wikipedia.org/wiki/Luma_%28video%29

Multi-target rendering: Output multiple colors to different textures.

Q: Depth buffer / 8 bit images / 32 bit / intermediate texture format?

Q: How to know how far away "white" or 90% white is?

Challenge: Render perspective divide in a shader?

Idea: Measure how far away people tend to hold their phones, then use a perspective transformation that would accurately display what it would feel like to look through a same-sized portal.

Homogeneous coordinates were invented by August Ferdinand Möbius.

Notice: Does the projection matrix has 5 degrees of freedom?

"Nobody uses stencil. Ban stencil."

Q: Inverse square law?

Korg nanoKONTROL2

We put more precision in darker colors because of how our eyes work. sRGB electrical transfer function.

Q: What is Warp divergence?

A: https://en.wikipedia.org/wiki/Thread_block_(CUDA_programming)#Warps

Martins Mozeiko

Overview

How compiler can help you fix more errors in code? Easier debugging, finding bugs sooner, preventing new bugs

Compiler warnings Address Sanitizer libFuzzer git bisect

Compiler warnings

Don't ignore warnings

gcc/clang: -Wall -Wextra -Werror, -Wshadow, -Wconversion, useful-gcc-warning-options-not-enabled MSVC: /W3, /WX, /analyze

Address Sanitizer

Fast memory error detector COmpiler can help you detect bad memory usage https://github.com/google/sanitizers/wiki/AddressSanitizer

libFuzzer

git bisect