Skip to content

Instantly share code, notes, and snippets.

@amtoine
Last active October 4, 2023 17:11
Show Gist options
  • Save amtoine/3fe1435edb656964d8066b5b7da9af5f to your computer and use it in GitHub Desktop.
Save amtoine/3fe1435edb656964d8066b5b7da9af5f to your computer and use it in GitHub Desktop.
Plot startup times of Nushell

Python Requirements

Simply pip install -r requirements.txt

How to compute startup times automatically

Put the following hook into your $env.config.hooks.env_change.PWD list

{|before, _|
    if $before == null {
        let file = $nu.home-path | path join ".local" "share" "nushell" "startup-times.nuon"
        if not ($file | path exists) {
            mkdir ($file | path dirname)
            touch $file
        }

        let version = (version)

        open $file | append {
            date: (date now)
            time: $nu.startup-time
            build: $version.build_rust_channel
            allocator: $version.allocator
            version: $version.version
            commit: $version.commit_hash
            build_time: $version.build_time
        } | save --force $file
    }
}

Input of the script

The shape of the first positional argument should be

table<commit: string, build_time: date, avg: duration, stddev: duration>

in Nushell notation.

Example:

let startup_times = open ~/.local/share/nushell/startup-times.nuon
    | group-by commit
    | transpose commit data
    | insert avg {|it| $it.data.time | math avg}
    | insert stddev {|it|
        $it.data.time | into int | into float | math stddev | into int | into duration
    }
    | select commit data.build_time.0 avg stddev
    | rename -c {data_build_time_0: build_time}
    | update build_time { into datetime }
    | sort-by build_time

python plot.py ($startup_times | to json)

if there are too many labels on the x axis, you can use the --skip-timestamps (-s) option.

Gallery

MacOs Windows Linux

import json
import argparse
import numpy as np
import matplotlib.pyplot as plt
from datetime import datetime
DATE_FORMAT = "%Y-%m-%d %H:%M:%S %z"
NB_NS_IN_MS = 1_000_000
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("data")
parser.add_argument("-s", "--skip-timestamps", type=int, default=0)
args = parser.parse_args()
data = json.loads(args.data)
build_times = [datetime.strptime(row["build_time"], DATE_FORMAT) for row in data]
timestamps = [build_time.timestamp() for build_time in build_times]
commits = [row["commit"] for row in data]
avgs = np.array([row["avg"] / NB_NS_IN_MS for row in data])
stddevs = np.array([row["stddev"] / NB_NS_IN_MS for row in data])
fig, ax = plt.subplots(nrows=1, sharex=True)
ax.plot(timestamps, avgs, color="blue", marker="o", label="mean startup time")
ax.fill_between(
timestamps,
avgs + stddevs,
avgs - stddevs,
alpha=0.15,
color="blue",
label="standard deviation"
)
ax.set_title("startup times for each build of Nushell")
plt.xticks(
timestamps[::args.skip_timestamps + 1],
[
build_time.strftime("%Y-%m-%d") + f"\n{commit[:7]}"
for (build_time, commit) in zip(build_times, commits)
][::args.skip_timestamps + 1]
)
plt.xlabel("build (date and commit)")
plt.ylabel("time (in ms)")
plt.grid(True)
plt.legend()
plt.show()
numpy
matplotlib
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment