{"id":15686153,"url":"https://github.com/cirocosta/chicken-gun","last_synced_at":"2025-06-27T22:05:44.322Z","repository":{"id":73883721,"uuid":"175843146","full_name":"cirocosta/chicken-gun","owner":"cirocosta","description":"stressing your system, a chicken at a time","archived":false,"fork":false,"pushed_at":"2019-10-20T22:38:47.000Z","size":345,"stargazers_count":9,"open_issues_count":13,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-06-27T22:04:49.275Z","etag":null,"topics":["helm","kubernetes","linux","stress-testing"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cirocosta.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-03-15T15:12:24.000Z","updated_at":"2022-04-21T21:46:41.000Z","dependencies_parsed_at":null,"dependency_job_id":"8f560784-1cc3-4c7f-9cb7-217bd9aeb912","html_url":"https://github.com/cirocosta/chicken-gun","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/cirocosta/chicken-gun","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cirocosta%2Fchicken-gun","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cirocosta%2Fchicken-gun/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cirocosta%2Fchicken-gun/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cirocosta%2Fchicken-gun/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cirocosta","download_url":"https://codeload.github.com/cirocosta/chicken-gun/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cirocosta%2Fchicken-gun/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262341622,"owners_count":23296069,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["helm","kubernetes","linux","stress-testing"],"created_at":"2024-10-03T17:35:31.512Z","updated_at":"2025-06-27T22:05:44.293Z","avatar_url":"https://github.com/cirocosta.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# chicken-gun \n\n\u003e A **chicken gun** is a large-diameter, compressed-air cannon used to fire dead chickens at aircraft components in order to simulate high-speed bird strikes during the aircraft's flight. (source: [*Wikipedia*](https://en.wikipedia.org/wiki/Chicken_gun))\n\nHere you can find `cg`, a tool aimed at providing very targetted load at specific parts of a machine to verify:\n\n- what happens when specific problematic scenarios occur, and\n- if we're properly collecting telemetry from our systems.\n\n**Table of contents**\n\n\u003c!-- START doctoc generated TOC please keep comment here to allow auto update --\u003e\n\u003c!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --\u003e\n\n\n- [Scenarios](#scenarios)\n  - [`cpu`](#cpu)\n  - [`context-switches`](#context-switches)\n  - [`pids`](#pids)\n  - [`files-open`](#files-open)\n  - [`tcp-transmitter` and `tcp-receiver`](#tcp-transmitter-and-tcp-receiver)\n- [In a container](#in-a-container)\n- [LICENSE](#license)\n\n\u003c!-- END doctoc generated TOC please keep comment here to allow auto update --\u003e\n\n\n## Scenarios\n\n### `cpu`\n\nExercises the CPU time spent on userspace code by creating `n` threads that each keep running a busy loop indefinitely.\n\n```sh\n# run four threads with busyloops in them.\ncg cpu --threads 4\n```\n\nOnce the scenario runs, we can look at CPU utilization metrics to verify that we're really exercising the CPUs, but first, let's see where we can gather that info from:\n\n```sh\ncat /proc/stat\ncpu  15336 204 1036 1949794 774 0 133 0 0 0  #  -- aggregate over all cpus\ncpu0 5135  42  370  649932  248 0 21  0 0 0\ncpu1 5106  162 315  649920  275 0 102 0 0 0\n#     |    |   |    |       |   |  |  | | |\n#     |    |   |    |       |   |  |  | | *guest_nice\n#     |    |   |    |       |   |  |  | *guest\n#     |    |   |    |       |   |  |  *steal\n#     |    |   |    |       |   |  *softirq\n#     |    |   |    |       |   *irq\n#     |    |   |    |       *iowait\n#     |    |   |    *idle\n#     |    |   *system\n#     |    *nice\n#     *user    \n```\n\nWhere each number measures the number of jiffies (100HZ on x86) that the cpu saw itself in that mode since the time that the system booted.\n\n| metric | description |\n| ------ | ----------- |\n| user   | normal processes executing in user mode |\n| nice   | `nice`d processes executing in user mode |\n| system | processes executing in kernel mode |\n| idle | idle |\n| iowait | time during which a particular CPU was idle and there was at least one outstanding disk I/O operation requested by a task scheduled on that CPU (at the time it generated that I/O request) |\n\nReferences:\n\n- [The precise meaning of I/O wait time in Linux](http://veithen.io/2013/11/18/iowait-linux.html)\n- [The `/proc` filesystem](https://www.kernel.org/doc/Documentation/filesystems/proc.txt)\n\n\n### `context-switches`\n\nIn this scenario, threads get their execution swapped in `n` cores all the time, constantly.\n\nAs a result, we end up with:\n\n- not much userspace CPU consumption,\n- very high per-task context switch numbers, and\n- high kernel-space CPU utilization for `migration/*` processes.\n\nFor instance, looking at the results of sampling a mostly idle system that only has `cg context-switches` running for `30s`:\n\n![](./assets/context-switches-flamegraph.png)\n\n```sh\n# take samples of the whole callgraph 99 times a second for every\n# cpu in the machine while running the `sleep` command.\n#\n#    -F,--freq        Profile at this frequency.\n#\n#    -a,--all-cpus    System-wide collection from all CPUs \n#                     (default if no target is specified).\n#\n#    -g               Enables call-graph (stack chain/backtrace) recording.\n#\nperf record --freq 99 -a -g sleep 30\n\n\n# `perf-script` reads perf.data (created by perf record) and displays \n# trace output.\n#\n# With the traces generated by `perf script`, `stackcollapse` then \n# collapses that multiline output of samples into semicolon-separated single\n# lines, appropriate for `flamegraph.pl` to consume.\n#\n# From those collapsed stack traces, `flamegraph.pl` generates the\n# `svg` with the flamegraph visualization.\nperf script | \\\n\tstackcollapse-perf.pl | \\\n\tflamegraph.pl --hash --width=1000 \u003e \\\n\tcontext-switches-flamegraph.svg\n```\n\nNow, looking at the number of context switches as reported by `procfs`, we can see how aggressive we are in terms of context switching:\n\n```sh\ncd /proc/$(cat /tmp/cg.pid)/tasks\nfind . -name \"status\" | xargs -n1 grep 'ctxt'\nvoluntary_ctxt_switches:\t4\nnonvoluntary_ctxt_switches:\t1\nvoluntary_ctxt_switches:\t214\nnonvoluntary_ctxt_switches:\t1590249\nvoluntary_ctxt_switches:\t232\nnonvoluntary_ctxt_switches:\t1590307\nvoluntary_ctxt_switches:\t240\nnonvoluntary_ctxt_switches:\t1590386\nvoluntary_ctxt_switches:\t242\nnonvoluntary_ctxt_switches:\t1590412\n```\n\nIf we're even more curious and want to know in which CPUs the threads were when they ran, we can then look at a tailored output of `perf script`:\n\n```sh\n# filtering the system-wide samples, look at only those\n# for the `cg` command, then output the corresponding `cpu`\n# where each `tid` ran.\nperf script --fields comm,cpu,tid | awk '/cg/{print $2 $3}'\n```\n\nSomething interesting that happens when exercising context switches is that we can't just see the overhead associated with them by looking only at `user` and `system` CPU utilization, despite the fact that a `1 - idle` reveals that our CPUs are busy with such activity.\n\n![](./assets/context-switches-cpu-util.png)\n\n\n### `pids`\n\nCreates `n` different processes under the same process group as the parent `cg` initiated by `cg pids`.\n\n```sh\ncg pids -n 5\n\n# check the process group\npstree -p $(cat /tmp/cg.pid)\ncg(2016)─┬─exe(2017)\n         ├─exe(2018)\n         ├─exe(2019)\n         ├─exe(2020)\n         └─exe(2021)\n```\n\nUnder the hood, `cg pids` creates child processes from its own image (`/proc/self/exe`), specifying the hidden `cg sleep` - one that just sleeps forever - as their command.\n\nThis has the effect of having several processes (not just threads) under the same process group as `cg`.\n\nDespite the fact that Linux does not provide us with a single file containing the exact number of processes created, we can rely on what [`getdents(2)`](http://man7.org/linux/man-pages/man2/getdents.2.html) on `/proc` returns:\n\n```sh\nls /proc/ | awk '/^[0-9]+$/'\n```\n\n\n### `files-open`\n\nBy creating `n` files under a particular directory and keeping them open, this scenario can be used to verify either that, for instance, per-process limits are really enforced.\n\nFor example:\n\n```sh\n# check out what the current limit for the current process is\ncat /proc/$$/limits\nLimit                Soft Limit     Hard Limit    Units\n...\nMax resident set     unlimited      unlimited     bytes\nMax open files       1024           1048576       files\nMax locked memory    16777216       16777216      bytes\n...\n\n# configure the current process to have a limit\n# of 20 open files\nulimit -n 20\n\n\n# verify that we indeed changes the limit for the current process\ncat /proc/$$/limits\nLimit                Soft Limit     Hard Limit    Units\n...\nMax resident set     unlimited      unlimited     bytes\nMax open files       20             20            files\nMax locked memory    16777216       16777216      bytes\n...\n\n# see that we can't go past that limit:\ncg files-open -d /tmp -n 30\nthread 'main' panicked at 'failed to create /tmp/17: Too many open files (os error 24)', src/fs.rs:18:25\n```\n\nIn order to check what the current number of open files we have, we can inspect the process' `/proc/$pid/fd`:\n\n```sh\n# create and open a number of open files that we're allowed to handle\ncg files-open -d /tmp -n 10\nls /proc/$(cat /tmp/cg.pid)/fd | wc -l\n13\t# \u003c 10 files + stdin, stdout, and stderr.\n```\n\n### `tcp-transmitter` and `tcp-receiver`\n\nRespectively, sends/receives bytes from/to files as quickly as possible using as few userspace time as possible (leverages [`splice`](http://man7.org/linux/man-pages/man2/splice.2.html) heavily).\n\n```sh\n# in one terminal\ncg tcp-receiver -a 127.0.0.1:1337\n\n# in another terminal\ncg tcp-transmitter -a 127.0.0.1:1337\n\n# in yet another terminal\nsar -n DEV 1\n21:23:14        IFACE   rxpck/s   txpck/s    rxkB/s    txkB/s   rxcmp/s   txcmp/s  rxmcst/s   %ifutil\n21:23:15       enp0s3      4.00      4.00      0.23      0.40      0.00      0.00      0.00      0.00\n21:23:15           lo 240386.00 240386.00 5263101.63 5263101.63      0.00      0.00      0.00      0.00\n21:23:15       enp0s8      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00\n21:23:15      docker0      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00\n\ntop\n...\n%Cpu(s):  1.5 us, 31.5 sy,  0.0 ni, 60.0 id,  0.0 wa, ...\n\t *------* *-----*\n```\n\n\n## In a container\n\nJust like in a regular bare-metal or virtual machine, `cg` can run in containerized environments too.\n\nA container image can be found on DockerHub: [cirocosta/chicken-gun](https://hub.docker.com/r/cirocosta/chicken-gun).\n\n```sh\ndocker run cirocosta/chicken-gun cpu --threads 4\n```\n\n## LICENSE\n\nMIT - See [`./LICENSE`](./license).\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcirocosta%2Fchicken-gun","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcirocosta%2Fchicken-gun","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcirocosta%2Fchicken-gun/lists"}