My swelling debts and the elusive race condition, part six.

· October 9, 2021

If programmers had a credit rating for their tech debt, they’d all be junk bonds.

A 3d printed bust of Marcus Aurelius, Home, Bangalore, 2021

Recap

For those new here, I aspire to write about what is happening with me on at least a weekly basis. To quote my older post

I hope I keep this up and eventually I can publish my future memoir of my wildly successful life with this a reference.

In that spirit, I had decided to rename this series to “My memoir”, and then soon later declared that I don’t like the name. I have now decided that I don’t want to restrict it to any name. Every chapter will have it’s own title followed by the chapter number. Let’s see how my titles get progressively worse. Enough with the rambling, read the rest of my “memoir” here. From this week on, I am adding a new section to my memoir - “Perusal”, where I recommend aritcles or books that I read.

Apart from this, all my chapters end with “Notes on the epigraph” where I give more context on the photograph in my frontmatter.

My debts

You may have hear about “tech debt”, a tech shop buzzword used to describe somewhat poor technical decsions made in order ship something faster or simplify some code. It’s called “tech debt” because programmers1 delude themselves into thinking they will pay back said debt. If programmers had a credit rating for their tech debt, they’d all be junk bonds. Why am I bringing up tech debt, you may ask (while stroking your chin). It’s because I am going to be clichéd and compare this to real life. Specifically my life.

Every decision is a debt in the making. All of us, knowingly or unknowingly are racking up on debts (or the rare few up us, are doing quite the opposite). But who is the debtor and who is the debtee, you make ask (while stroking your chin more vigourously). You are the debtor, and your future self is the debtee. Debt eventually catches up to you. There are a hundred ways you could rip this analogy to shreds, so I appeal to you to stop thinking about this analogy further. Let’s get back to me.

There was a strong period of 6-9 months starting September 2020 when I lived a debt free life. I exercised, I meditated and I read a lot. For the past three months, I have been racking up debt and screwing over my future self. My reading has dwindled, my meditiation is but a stream and I have gained about 5kg. A lot of this was because I never kept track of these life debts. I have now decided to keep track of said debts, and slowly start repaying them before I become the living, breathing equivalent of a junk bond. The new section “Perusal” is one step in that direction. A lifestyle change is overdue.

The art of racing in the code.

This week at work, my tech debt finally caught up to me. I had written a set of goroutines that ended up in a set of race conditions. At work, I am usually very cognisant of the tech debts I take, littering my code with TODOs and warnings. Unfortunately, this particular race condition I didn’t foresee. I took hours to find and fix it. On this journey, I also ended up learning about a Go compiler feature - the race flag.

Starting v1.1, Go has a -race flag that can be added while building, running, testing or installing go packages. I wish I knew about this sooner. Instead of explaining it with an original example, I am going to just show the one in the official go blog2

Create a race condition with this code as the example

package main

import "fmt"

func main() {
    done := make(chan bool)
    m := make(map[string]string)
    m["name"] = "world"
    go func() {
        m["name"] = "data race"
        done <- true
    }()
    fmt.Println("Hello,", m["name"])
    <-done
}

And run the code with the race flag, like so

go run -race racy.go

The go compiler will automagically catch race conditions,

Hello, world
==================
WARNING: DATA RACE
Write at 0x00c00011c180 by goroutine 7:
  runtime.mapaccess2_faststr()
      /opt/homebrew/opt/go/libexec/src/runtime/map_faststr.go:107 +0x48c
  main.main.func1()
      /Users/advait/Downloads/dumpster/racy.go:10 +0x48

Previous read at 0x00c00011c180 by main goroutine:
  runtime.evacuate_fast64()
      /opt/homebrew/opt/go/libexec/src/runtime/map_fast64.go:375 +0x3dc
  main.main()
      /Users/advait/Downloads/dumpster/racy.go:13 +0xfc

Goroutine 7 (running) created at:
  main.main()
      /Users/advait/Downloads/dumpster/racy.go:9 +0xd0
==================
==================
WARNING: DATA RACE
Write at 0x00c000142088 by goroutine 7:
  main.main.func1()
      /Users/advait/Downloads/dumpster/racy.go:10 +0x5c

Previous read at 0x00c000142088 by main goroutine:
  main.main()
      /Users/advait/Downloads/dumpster/racy.go:13 +0x10c

Goroutine 7 (running) created at:
  main.main()
      /Users/advait/Downloads/dumpster/racy.go:9 +0xd0
==================
Found 2 data race(s)
exit status 66

This only works during run time, but it’s not recommended that this flag be used in production systems. This is because the caveat here

…race-enabled binaries can use ten times the CPU and memory, so it is impractical to enable the race detector all the time. One way out of this dilemma is to run some tests with the race detector enabled…

But this is still a really useful feature to have when writing tests.

Perusal

What got me thinking about debt:

I also bought Skin In The Game this week, so next will be fun.

Notes on the epigraph.

I took this picture during my stoicism phase early this year (around the same time I was living a debt free life). I found the whole VC cult of stoicism pretty amusing so I thought it would be fun to 3d print the bust of old boy Marcus and make a snarky tweet about it. So I did it.

My snarky tweet

One of these days, I am going to go off the deep end.

Footnotes

  1. Including yours truly 

  2. Here is the link. 

Twitter, Facebook