From 77a4ccd66a247d8c8c9ba1e901c7797ad7dcb473 Mon Sep 17 00:00:00 2001 From: Brett Holman Date: Fri, 15 Apr 2022 21:13:09 -0600 Subject: [PATCH 1/4] Shave ~8ms off generator runtime - remove redundant file reads and subcommands[1] - add make target that renders templates[2] - add make target that benchmarks generator[3] [1] cuts time in lxd from 17-20ms down to 8-13ms in lxc on my local machine [2] example: make render-template FILE=./systemd/cloud-init-generator.tmpl [3] usage: NUM_RUNS=42 make benchmark-generator --- Makefile | 25 ++++++++++++++++++++++--- systemd/cloud-init-generator.tmpl | 6 +++--- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 5f0c5b1bdb8..73d40d130b9 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,6 @@ +SHELL:=/bin/bash CWD=$(shell pwd) +VARIANT ?= ubuntu YAML_FILES=$(shell find cloudinit tests tools -name "*.yaml" -type f ) YAML_FILES+=$(shell find doc/examples -name "cloud-config*.txt" -type f ) @@ -6,12 +8,15 @@ YAML_FILES+=$(shell find doc/examples -name "cloud-config*.txt" -type f ) PYTHON = python3 PIP_INSTALL := pip3 install +NUM_RUNS ?= 100 + ifeq ($(distro),) distro = redhat endif READ_VERSION=$(shell $(PYTHON) $(CWD)/tools/read-version || echo read-version-failed) CODE_VERSION=$(shell $(PYTHON) -c "from cloudinit import version; print(version.version_string())") +GENERATOR_F=./systemd/cloud-init-generator all: check @@ -26,6 +31,20 @@ flake8: unittest: clean_pyc python3 -m pytest -v tests/unittests cloudinit +render-template: + $(PYTHON) ./tools/render-cloudcfg --variant=$(VARIANT) $(FILE) $(subst .tmpl,,$(FILE)) + +# from systemd-generator(7) regarding generators: +# "We do recommend C code however, since generators are executed +# synchronously and hence delay the entire boot if they are slow." +# +# Our generator is a shell script. Make it easy to measure the +# generator. This should be monitored for performance regressions +benchmark-generator: FILE=$(GENERATOR_F).tmpl +benchmark-generator: render-template + chmod +x $(GENERATOR_F) + time for _ in {1..$(NUM_RUNS)}; do $(GENERATOR_F); done + ci-deps-ubuntu: @$(PYTHON) $(CWD)/tools/read-dependencies --distro ubuntu --test-distro @@ -76,7 +95,7 @@ clean_release: rm -rf new-upstream-changes.txt commit.msg clean: clean_pyc clean_pytest clean_packaging clean_release - rm -rf doc/rtd_html .tox .coverage tags + rm -rf doc/rtd_html .tox .coverage tags $(GENERATOR_F) yaml: @$(PYTHON) $(CWD)/tools/validate-yaml.py $(YAML_FILES) @@ -142,5 +161,5 @@ fix_spelling: .PHONY: test flake8 clean rpm srpm deb deb-src yaml .PHONY: check_version pip-test-requirements pip-requirements clean_pyc -.PHONY: unittest style-check doc fix_spelling -.PHONY: clean_pytest clean_packaging check_spelling clean_release +.PHONY: unittest style-check fix_spelling render-template benchmark-generator +.PHONY: clean_pytest clean_packaging check_spelling clean_release doc diff --git a/systemd/cloud-init-generator.tmpl b/systemd/cloud-init-generator.tmpl index 6c4a66d1b0a..7ec961be990 100644 --- a/systemd/cloud-init-generator.tmpl +++ b/systemd/cloud-init-generator.tmpl @@ -72,9 +72,9 @@ kernel_cmdline() { # use KERNEL_CMDLINE if present in environment even if empty cmdline=${KERNEL_CMDLINE} debug 1 "kernel command line from env KERNEL_CMDLINE: $cmdline" - elif read_proc_cmdline; then - read_proc_cmdline && cmdline="$_RET" - debug 1 "kernel command line ($_RET_MSG): $cmdline" + else + read_proc_cmdline && cmdline="$_RET" || + debug 1 "kernel command line ($_RET_MSG): $cmdline" fi _RET="unset" cmdline=" $cmdline " From 6b3d0e6e8509e447b3edb4a61ed8fe668539adf5 Mon Sep 17 00:00:00 2001 From: Brett Holman Date: Sat, 16 Apr 2022 11:09:53 -0600 Subject: [PATCH 2/4] add ds-identify benchmark target --- Makefile | 13 ++++++++++--- systemd/cloud-init-generator.tmpl | 2 +- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 73d40d130b9..ed9db8dd1a1 100644 --- a/Makefile +++ b/Makefile @@ -17,6 +17,7 @@ endif READ_VERSION=$(shell $(PYTHON) $(CWD)/tools/read-version || echo read-version-failed) CODE_VERSION=$(shell $(PYTHON) -c "from cloudinit import version; print(version.version_string())") GENERATOR_F=./systemd/cloud-init-generator +DS_IDENTIFY=./tools/ds-identify all: check @@ -31,6 +32,10 @@ flake8: unittest: clean_pyc python3 -m pytest -v tests/unittests cloudinit +benchmark-bin: + chmod +x $(GENERATOR_F) + time for _ in {1..$(NUM_RUNS)}; do $(BIN); done + render-template: $(PYTHON) ./tools/render-cloudcfg --variant=$(VARIANT) $(FILE) $(subst .tmpl,,$(FILE)) @@ -41,9 +46,11 @@ render-template: # Our generator is a shell script. Make it easy to measure the # generator. This should be monitored for performance regressions benchmark-generator: FILE=$(GENERATOR_F).tmpl -benchmark-generator: render-template - chmod +x $(GENERATOR_F) - time for _ in {1..$(NUM_RUNS)}; do $(GENERATOR_F); done +benchmark-generator: BIN=$(GENERATOR_F) +benchmark-generator: render-template benchmark-bin + +benchmark-ds-identify: BIN=$(DS_IDENTIFY) +benchmark-ds-identify: benchmark-bin ci-deps-ubuntu: @$(PYTHON) $(CWD)/tools/read-dependencies --distro ubuntu --test-distro diff --git a/systemd/cloud-init-generator.tmpl b/systemd/cloud-init-generator.tmpl index 7ec961be990..668930983a3 100644 --- a/systemd/cloud-init-generator.tmpl +++ b/systemd/cloud-init-generator.tmpl @@ -73,7 +73,7 @@ kernel_cmdline() { cmdline=${KERNEL_CMDLINE} debug 1 "kernel command line from env KERNEL_CMDLINE: $cmdline" else - read_proc_cmdline && cmdline="$_RET" || + read_proc_cmdline && cmdline="$_RET" && debug 1 "kernel command line ($_RET_MSG): $cmdline" fi _RET="unset" From 4ed19e9fabf36daf57964df2054dd05395355f02 Mon Sep 17 00:00:00 2001 From: Brett Holman Date: Tue, 19 Apr 2022 09:12:48 -0600 Subject: [PATCH 3/4] Switch from makefile to shell script --- Makefile | 17 ++++++++--------- tools/benchmark.sh | 8 ++++++++ 2 files changed, 16 insertions(+), 9 deletions(-) create mode 100755 tools/benchmark.sh diff --git a/Makefile b/Makefile index ed9db8dd1a1..295bd1a3c9e 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ YAML_FILES+=$(shell find doc/examples -name "cloud-config*.txt" -type f ) PYTHON = python3 PIP_INSTALL := pip3 install -NUM_RUNS ?= 100 +NUM_ITER ?= 100 ifeq ($(distro),) distro = redhat @@ -18,6 +18,7 @@ READ_VERSION=$(shell $(PYTHON) $(CWD)/tools/read-version || echo read-version-fa CODE_VERSION=$(shell $(PYTHON) -c "from cloudinit import version; print(version.version_string())") GENERATOR_F=./systemd/cloud-init-generator DS_IDENTIFY=./tools/ds-identify +BENCHMARK=./tools/benchmark.sh all: check @@ -32,10 +33,6 @@ flake8: unittest: clean_pyc python3 -m pytest -v tests/unittests cloudinit -benchmark-bin: - chmod +x $(GENERATOR_F) - time for _ in {1..$(NUM_RUNS)}; do $(BIN); done - render-template: $(PYTHON) ./tools/render-cloudcfg --variant=$(VARIANT) $(FILE) $(subst .tmpl,,$(FILE)) @@ -46,11 +43,13 @@ render-template: # Our generator is a shell script. Make it easy to measure the # generator. This should be monitored for performance regressions benchmark-generator: FILE=$(GENERATOR_F).tmpl -benchmark-generator: BIN=$(GENERATOR_F) -benchmark-generator: render-template benchmark-bin +benchmark-generator: export ITER=$(NUM_ITER) +benchmark-generator: render-template + $(BENCHMARK) $(GENERATOR_F) -benchmark-ds-identify: BIN=$(DS_IDENTIFY) -benchmark-ds-identify: benchmark-bin +benchmark-ds-identify: export ITER=$(NUM_ITER) +benchmark-ds-identify: + $(BENCHMARK) $(DS_IDENTIFY) ci-deps-ubuntu: @$(PYTHON) $(CWD)/tools/read-dependencies --distro ubuntu --test-distro diff --git a/tools/benchmark.sh b/tools/benchmark.sh new file mode 100755 index 00000000000..c382f374472 --- /dev/null +++ b/tools/benchmark.sh @@ -0,0 +1,8 @@ +#!/usr/bin/bash + +BIN="$@" +chmod +x "$BIN" + +time for _ in $(seq 1 $ITER); do + "$BIN"; +done From ed0df9dcd3741c61a508f8c507e8486cc67e5f83 Mon Sep 17 00:00:00 2001 From: Brett Holman Date: Wed, 20 Apr 2022 07:36:45 -0600 Subject: [PATCH 4/4] unrelated makefile fixes --- Makefile | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 295bd1a3c9e..cb0054675d5 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,3 @@ -SHELL:=/bin/bash CWD=$(shell pwd) VARIANT ?= ubuntu @@ -69,9 +68,10 @@ test: unittest check_version: @if [ "$(READ_VERSION)" != "$(CODE_VERSION)" ]; then \ - echo "Error: read-version version '$(READ_VERSION)'" \ - "not equal to code version '$(CODE_VERSION)'"; exit 2; \ - else true; fi + echo "Error: read-version version '$(READ_VERSION)'" \ + "not equal to code version '$(CODE_VERSION)'"; \ + exit 2; \ + else true; fi config/cloud.cfg: $(PYTHON) ./tools/render-cloudcfg config/cloud.cfg.tmpl config/cloud.cfg @@ -115,14 +115,14 @@ srpm: deb: @which debuild || \ { echo "Missing devscripts dependency. Install with:"; \ - echo sudo apt-get install devscripts; exit 1; } + echo sudo apt-get install devscripts; exit 1; } $(PYTHON) ./packages/bddeb deb-src: @which debuild || \ { echo "Missing devscripts dependency. Install with:"; \ - echo sudo apt-get install devscripts; exit 1; } + echo sudo apt-get install devscripts; exit 1; } $(PYTHON) ./packages/bddeb -S -d doc: @@ -165,7 +165,7 @@ fix_spelling: awk -F ': | -> ' '{printf "sed -i \047s/%s/%s/g\047 %s\n", $$2, $$3, $$1}' | \ sh -.PHONY: test flake8 clean rpm srpm deb deb-src yaml +.PHONY: all check test flake8 clean rpm srpm deb deb-src yaml .PHONY: check_version pip-test-requirements pip-requirements clean_pyc .PHONY: unittest style-check fix_spelling render-template benchmark-generator .PHONY: clean_pytest clean_packaging check_spelling clean_release doc