Easy templating with Python and Jinja

At work, I’ve been using both Golang and Ruby to render Nomad jobspec files in a consistent manner across environments. But Python is my one true love and I wanted to learn how to do it in Python. Turns out I already knew how… you can do it in Jinja2! I’ve used Jinja2 in the past a lot for Django and Ansible, so this was pretty easy to pick up. Here are some notes for future me when I want to inevitably do this again....

2023-07-04

Latency Numbers Every Programmer Should Know

These are useful and I’m putting them here so I can find them easily wherever I am. Latency Comparison Numbers (~2012) ---------------------------------- L1 cache reference 0.5 ns Branch mispredict 5 ns L2 cache reference 7 ns 14x L1 cache Mutex lock/unlock 25 ns Main memory reference 100 ns 20x L2 cache, 200x L1 cache Compress 1K bytes with Zippy 3,000 ns 3 us Send 1K bytes over 1 Gbps network 10,000 ns 10 us Read 4K randomly from SSD* 150,000 ns 150 us ~1GB/sec SSD Read 1 MB sequentially from memory 250,000 ns 250 us Round trip within same datacenter 500,000 ns 500 us Read 1 MB sequentially from SSD* 1,000,000 ns 1,000 us 1 ms ~1GB/sec SSD, 4X memory Disk seek 10,000,000 ns 10,000 us 10 ms 20x datacenter roundtrip Read 1 MB sequentially from disk 20,000,000 ns 20,000 us 20 ms 80x memory, 20X SSD Send packet CA->Netherlands->CA 150,000,000 ns 150,000 us 150 ms Notes ----- 1 ns = 10^-9 seconds 1 us = 10^-6 seconds = 1,000 ns 1 ms = 10^-3 seconds = 1,000 us = 1,000,000 ns Credit ------ By Jeff Dean: http://research....

2023-06-24

Python dataclasses are awesome!

Last week, I was working on some Python at work and I found myself wishing for an equivalent to Golang’s structs. Rather than passing in a bunch of core data types (string, dict, int, etc.) in an out of methods, I wanted to pass in a single object with predictable attributes. But…. I didn’t want to go through all the trouble of creating a class with a constructor, and passing in all the various attributes....

2023-05-22

nil maps in Golang

I’ve been a bit confused for a while over when a map in Golang gets created with a value of nil (its zero value) and when it does not, so I’m writing this to help me remember. Let’s look at various ways to initialize a map: package main import "fmt" func main() { m1 := map[string]string{} // initializes map m2 := make(map[string]string) // also initializes map var m3 map[string]string // does NOT initialize the map!...

2023-01-07

Thoughts on travel to Hawaii

My wife and I recently went to the Hawaiin islands for a few days for a vacatoin. Here’s what worked well and didn’t well about the trip. Resorts We stayed in resorts for the first time. This was new; normally we stay in Airbnbs or the like. Pros: Consistent experience. Clean and nice. Pools and hottubs. Safe. We felt very good leaving laptops and the like in the room. Cons:...

2022-11-08

Built-in Go HTTP server

Go has a built-in HTTP server in net/http. Here’s me playing around using it: package main import ( "fmt" "net/http" "strings" ) func hello(w http.ResponseWriter, req *http.Request) { fmt.Fprintf(w, "hello\n") } func details(w http.ResponseWriter, req *http.Request) { resp := []string{} resp = append(resp, "Request Details:") resp = append(resp, fmt.Sprintf("- Request proto: %s", req.Proto)) resp = append(resp, fmt.Sprintf("- Headers:")) for name, val := range req.Header { resp = append(resp, fmt.Sprintf("\t- %s: %s", name, val)) } resp = append(resp, "\n") fmt....

2022-10-14

Fixing: File is not `goimports`-ed (goimports)

The other day, I was linting my Go code with golangci-lint when I got this error: File is not `goimports`-ed (goimports) I examined the file and found nothing amiss, but the linter insisted something was wrong. Eventually, I realized I had used spaces to indent the file rather than tabs. Changing the indent character to tabs fixed it. I then ran into the same error on a second file. This time, I had a comment which was wrong....

2022-10-05

Linux load average

This post documents the high level concepts I need to remember about *nix Load Average. Load average can been seen in the output of uptime and top: From uptime: $ uptime 14:40 up 21 days, 21:48, 5 users, load averages: 2.63 2.75 3.45 From top: root@blog-server-2:~# top -n 1 | head -2 top - 15:28:37 up 10 days, 12:41, 1 user, load average: 0.04, 0.03, 0.00 Tasks: 95 total, 1 running, 94 sleeping, 0 stopped, 0 zombie root@blog-server-2:~# There are 3 decimal numbers shown....

2022-09-16

Using entr to get immediate test feedback

Old and new workflows My dev workflow used to look like this: Write some code and save it Change to my Terminal window Up-arrow to find my command to run unit tests (typically make test) Press Enter Wait for tests to run and examine test output This worked pretty well, but was a lot of manual steps when you figure that I did this dozens (hundreds?) of times per day. That’s a lot of energy spent doing the same thing over and over again....

2022-09-07

Go and pass by value

Go normally uses pass-by-value for function calls. When you pass a variable into a function or method, Go will (under the hood) create a new variable, copy the old variable’s value into it, and then pass the new variable (not the original variable) into the function or method. Non-pointer values These types behave as described above and are sometimes called non-pointer values: Strings Ints Floats Booleans Arrays Structs Here’s an example of how these work....

2022-09-01