N/ NIFT LABS

Experiment 03 / practical shell work

Start a shell.
Then put it to work.

Startup, explicit configuration, substantial native logic, process pipelines and mixed filesystem tasks in Bash, Zsh, Fish, Nushell and Nift. Different architectures, checked outputs and every observation retained.

01 / timed boundaryProcess starts
02 / conceptual phaseRuntime initialises
03 / explicit variableRC loads
04 / PTY boundaryPrompt ready

Stages explain the model; individual stage durations were not measured. Only the total startup boundary is timed.

Series 20261015-v4120-final-c14d068 · Nift 4.12.0 final candidate · frozen source revision. Current figures use final audited observations. Earlier reports retain their own dated series; samples are not pooled.

Startup / distributions

A median does not show every stall.

Bare first-prompt latency distributions: lines are min–max, circles medians and diamonds p95, with a zero-based millisecond axis. Exact observations follow in the table.
Bare prepared state; 100 measured samples per startup cell
ShellExit msTrivial msPrompt msPrompt p95Prompt p99
bash1.7121.6202.0892.6782.979
zsh2.1862.0862.8443.5393.830
fish2.3642.22819.34724.00726.893
nu13.63813.56917.36519.74520.174
nift2.4252.2021.9862.4832.689

Bash’s bare prompt median was 2.089 ms and Zsh’s was 2.844 ms. Their p99 values were 2.979 and 3.830 ms; Nift’s was 2.689 ms. Tails remain visible even where medians are small.

Download the SVG figure · PNG figure.

Exit/trivial use C-supervised non-interactive command evaluation. Prompt startup uses a real controlling PTY, excludes Python/bridge launch but includes PTY forwarding and minimal xterm query handling, then validates RC state. Those boundaries differ; subtracting them would not recover RC cost.

Observed: Nift’s trivial bare invocation median was 2.202 ms; Bash’s was 1.620 ms. This describes this exact node and invocation, not overall shell quality.

Configuration is a variable

Bare → Empty → Light → Moderate

BareNo user config.
EmptyNormal path; empty files.
Light8 environment values + functions.
Moderate32 values + functions.

Light/moderate also prepend one PATH entry and perform a HOME-existence conditional. A post-prompt oracle validates representative environment, function and conditional state. No aliases or plugin managers are forced onto shells without equivalent facilities.

Prepared state, non-login; medians, 100 measured samples per cell
ShellBare msEmpty msLight msModerate ms
bash2.0893.6933.8334.035
zsh2.84427.53227.84827.812
fish19.34740.08941.10938.524
nu17.36520.64221.03721.051
nift1.9861.9742.3502.770
Fresh HOME/XDG per invocation, non-login; medians, 30 measured samples per cell
ShellBare msEmpty msLight msModerate ms
bash2.0813.7033.8654.080
zsh2.912538.7540.5541.3
fish20.04672.75268.96568.024
nu17.50320.51520.57621.171
nift1.9992.0422.3242.763
Prepared first-prompt startup. Median latency (ms). Zero-based axis.
Prepared first-prompt startup. Zero-based scale. SVG · PNG. Exact values appear in the accompanying tables.
Login matrix
Login prompt startup; Nift has no separate login mode
ShellBare msEmpty msLight msModerate ms
bash2.04918.58718.67618.822
zsh2.75327.55427.71627.660
fish20.64839.89839.68740.014
nu17.96420.83720.85921.320

Fresh configured Zsh medians were 538.7 ms for empty user files and 541.3 ms for moderate files. Ubuntu’s normal system completion setup rebuilds per fresh HOME; the normal-path matrix includes that work.

Bare means no user config. Zsh still reads compiled system zshenv. Normal/login paths retain distro-wide configuration. Nift uses isolated HOME because there is no no-RC option; Nu keeps its standard library. Direct startup measurements are never derived by subtracting RC time. Fresh application directories reset config/cache/history state without flushing OS caches.

Orchestration & native work

The shell has work to do.

Whole fresh invocation median ms; 10 measured samples per cell
Workloadbashzshfishnunift
native-sum5.0993.235107.614.4103.041
function-string1.7232.1912.69514.4352.256
external-10088.30999.04274.40494.05092.969
short-pipeline4.3354.7874.47016.0605.098
command-capture3.1203.5563.81414.9163.514
file-roundtrip4.0224.4534.63816.6684.910

Sum uses assignments, arithmetic, conditions and loops. Function-string defines a callable and changes case/replaces characters. External-100 runs the same absolute /usr/bin/true 100 times. Pipeline uses identical printf/tr executables; Nift uses structured run()/cmd().pipe() capture. The file row executes identical /usr/bin/printf and /usr/bin/cat helpers in all five shells; writing uses POSIX redirection, Nu save or Nift’s file API after structured capture. It measures that mixed orchestration/I/O workflow, not pure native file-read throughput. Equivalent output does not imply identical internal architecture.

Bash’s trivial invocation was 1.620 ms versus Nift’s 2.202 ms. Fish’s external-100 median was 74.404 ms versus Nift’s 92.969 ms. These rows show why prompt latency alone cannot rank shell performance.

Launching 100 external commands. Whole invocation median (ms). Zero-based axis.
Launching 100 external commands. Zero-based scale. SVG · PNG. Exact values appear in the accompanying tables.
Median Linux waited-child high-water RSS; not simultaneous aggregate tree RSS
ShellTrivial RSS MiB
bash3.375
zsh3.625
fish5.375
nu24.875
nift5.875

PTY RSS is omitted because prompt timing stops before oracle/teardown accounting. Parallel job-control and personal/default-dotfile distributions remain outside this series. The additive workload layer below covers longer pipelines, traversal and practical tasks.

Measurement boundaries

Different architectures. Equivalent tasks.

Runtime-native cases execute shell arithmetic, functions and strings. Orchestration cases coordinate the same absolute GNU executables. End-to-end filesystem cases allow each shell’s normal APIs: Bash/Zsh/Fish use batching/redirection; Nushell and Nift use native operations. Direct GNU xargs baselines exclude shell launch. These are user-task comparisons, not five equivalent filesystem engines. Added tasks run as bare, non-interactive invocations: elapsed time includes launch and program work, while fixture setup and complete validation remain outside timing.

100,000 targets + 20,000 keepers

Selected files. Nothing else.

Deterministic target and keeper names are interleaved. Flat cases share one directory; the tree variant distributes both sets over 100 directories. Removing a target-only parent or the entire workspace fails validation. Selected deletion reads an exact manifest; batching avoids ARG_MAX. Nift/Nushell have native selected deletion; Bash/Zsh/Fish have no native deletion result, and their end-to-end GNU rm results remain visible.

Empty creation measures inode creation; small creation writes 128 bytes per target. Nift’s file save uses temporary-file replacement, while other implementations have different write paths. We disclose that extra atomic-save work rather than claiming equivalent internals. All target bytes, all keeper bytes, keeper mode/mtime/inode, counts and unexpected files are checked outside timing.

Native selected-delete subset: the Nift and Nushell observations use their runtime filesystem APIs. Traditional shells have no native deletion primitive; their end-to-end timings below use batched GNU rm. The native subset reuses those exact checked observations, rather than timing an artificial second implementation.

Runtime-native selected deletion subset; identical samples to the end-to-end cases
Native deletionBashZshFishNushell sNift s
100k flat———6.7602.967
100k tree———7.3062.848

filesystem

Filesystem operations

create-empty · file-count scaling · shared zero-based axis: 0–5.681 s
Task sizeBashZshFishNushellNift
Elapsed time vs sizeLogarithmic task-size axis;
lines connect measured points.
1000: 0.034 s100010000: 0.331 s10000100000: 3.499 s1000001000: 0.052 s100010000: 0.516 s10000100000: 5.261 s1000001000: 0.051 s100010000: 0.496 s10000100000: 5.128 s1000001000: 0.050 s100010000: 0.358 s10000100000: 3.600 s1000001000: 0.038 s100010000: 0.368 s10000100000: 3.885 s100000
10000.0340.0520.0510.0500.038
100000.3310.5160.4960.3580.368
1000003.4995.2615.1283.6003.885
delete-selected · file-count scaling · shared zero-based axis: 0–7.301 s
Task sizeBashZshFishNushellNiftGNU baseline
Elapsed time vs sizeLogarithmic task-size axis;
lines connect measured points.
1000: 0.023 s100010000: 0.205 s10000100000: 2.218 s1000001000: 0.025 s100010000: 0.204 s10000100000: 2.648 s1000001000: 0.025 s100010000: 0.202 s10000100000: 2.670 s1000001000: 0.065 s100010000: 0.536 s10000100000: 6.760 s1000001000: 0.025 s100010000: 0.240 s10000100000: 2.967 s1000001000: 0.022 s100010000: 0.201 s10000100000: 2.279 s100000
10000.0230.0250.0250.0650.0250.022
100000.2050.2040.2020.5360.2400.201
1000002.2182.6482.6706.7602.9672.279

create-empty-1000

Implementations, invocations, tails and correctness
create-empty-1000 retained tails; no outliers removed
Distribution · secondsBashZshFishNushellNift
p950.0370.0550.0550.0560.042
Minimum0.0330.0500.0490.0460.036
Maximum0.0380.0550.0560.0580.042
create-empty-1000 implementation boundaries
SystemImplementation
Bashshell redirection
Zshshell redirection
Fishshell redirection
Nushellnative filesystem API
Niftnative filesystem API

Bash

while IFS= read -r p || [ -n "$p" ]; do : > "$p"; done < targets.txt; echo OK

Zsh

while IFS= read -r p || [ -n "$p" ]; do : > "$p"; done < targets.txt; echo OK

Fish

while read -l p; printf %s '' > "$p"; end < targets.txt; echo OK

Nushell

for p in (open --raw targets.txt | lines) { "" | save --raw $p }; print OK

Nift

paths := open("targets.txt").trim().split("\n"); for(p : paths) { touch(p) }; print("OK")

Every observation passed its output and filesystem oracle. Reconstructed fixture setup and verification are outside elapsed time. Exact source, manifest and oracle hashes, commands, samples, waited-child high-water RSS and validation records are preserved in shell-workloads.json.

delete-selected-1000

Implementations, invocations, tails and correctness
delete-selected-1000 retained tails; no outliers removed
Distribution · secondsBashZshFishNushellNiftGNU baseline
p950.0250.0260.0300.0680.0270.024
Minimum0.0220.0230.0230.0610.0250.021
Maximum0.0250.0260.0330.0690.0280.024
delete-selected-1000 implementation boundaries
SystemImplementation
Bashbatched GNU utilities
Zshbatched GNU utilities
Fishbatched GNU utilities
Nushellnative filesystem API
Niftnative filesystem API
GNU baselinedirect GNU xargs + /usr/bin/rm

Bash

/usr/bin/xargs -0 -a targets.nul /usr/bin/rm --; echo OK

Zsh

/usr/bin/xargs -0 -a targets.nul /usr/bin/rm --; echo OK

Fish

/usr/bin/xargs -0 -a targets.nul /usr/bin/rm --; echo OK

Nushell

let paths = (open --raw targets.txt | lines); rm ...$paths; print OK

Nift

paths := open("targets.txt").trim().split("\n"); remove(paths); print("OK")

GNU baseline

/usr/bin/xargs -0 -a targets.nul /usr/bin/rm --

Every observation passed its output and filesystem oracle. Reconstructed fixture setup and verification are outside elapsed time. Exact source, manifest and oracle hashes, commands, samples, waited-child high-water RSS and validation records are preserved in shell-workloads.json.

create-empty-10000

Implementations, invocations, tails and correctness
create-empty-10000 retained tails; no outliers removed
Distribution · secondsBashZshFishNushellNift
p950.3580.5530.5240.3930.421
Minimum0.3170.5070.4890.3470.344
Maximum0.3700.5740.5260.4000.429
create-empty-10000 implementation boundaries
SystemImplementation
Bashshell redirection
Zshshell redirection
Fishshell redirection
Nushellnative filesystem API
Niftnative filesystem API

Bash

while IFS= read -r p || [ -n "$p" ]; do : > "$p"; done < targets.txt; echo OK

Zsh

while IFS= read -r p || [ -n "$p" ]; do : > "$p"; done < targets.txt; echo OK

Fish

while read -l p; printf %s '' > "$p"; end < targets.txt; echo OK

Nushell

for p in (open --raw targets.txt | lines) { "" | save --raw $p }; print OK

Nift

paths := open("targets.txt").trim().split("\n"); for(p : paths) { touch(p) }; print("OK")

Every observation passed its output and filesystem oracle. Reconstructed fixture setup and verification are outside elapsed time. Exact source, manifest and oracle hashes, commands, samples, waited-child high-water RSS and validation records are preserved in shell-workloads.json.

delete-selected-10000

Implementations, invocations, tails and correctness
delete-selected-10000 retained tails; no outliers removed
Distribution · secondsBashZshFishNushellNiftGNU baseline
p950.2080.2330.2120.5660.2680.217
Minimum0.1970.1980.1950.5210.2330.194
Maximum0.2090.2410.2120.5700.2710.219
delete-selected-10000 implementation boundaries
SystemImplementation
Bashbatched GNU utilities
Zshbatched GNU utilities
Fishbatched GNU utilities
Nushellnative filesystem API
Niftnative filesystem API
GNU baselinedirect GNU xargs + /usr/bin/rm

Bash

/usr/bin/xargs -0 -a targets.nul /usr/bin/rm --; echo OK

Zsh

/usr/bin/xargs -0 -a targets.nul /usr/bin/rm --; echo OK

Fish

/usr/bin/xargs -0 -a targets.nul /usr/bin/rm --; echo OK

Nushell

let paths = (open --raw targets.txt | lines); rm ...$paths; print OK

Nift

paths := open("targets.txt").trim().split("\n"); remove(paths); print("OK")

GNU baseline

/usr/bin/xargs -0 -a targets.nul /usr/bin/rm --

Every observation passed its output and filesystem oracle. Reconstructed fixture setup and verification are outside elapsed time. Exact source, manifest and oracle hashes, commands, samples, waited-child high-water RSS and validation records are preserved in shell-workloads.json.

create-empty-100000

Implementations, invocations, tails and correctness
create-empty-100000 retained tails; no outliers removed
Distribution · secondsBashZshFishNushellNift
p953.6355.3925.1383.6763.889
Minimum3.3595.1735.0823.5773.772
Maximum3.6455.4115.1383.6853.889
create-empty-100000 implementation boundaries
SystemImplementation
Bashshell redirection
Zshshell redirection
Fishshell redirection
Nushellnative filesystem API
Niftnative filesystem API

Bash

while IFS= read -r p || [ -n "$p" ]; do : > "$p"; done < targets.txt; echo OK

Zsh

while IFS= read -r p || [ -n "$p" ]; do : > "$p"; done < targets.txt; echo OK

Fish

while read -l p; printf %s '' > "$p"; end < targets.txt; echo OK

Nushell

for p in (open --raw targets.txt | lines) { "" | save --raw $p }; print OK

Nift

paths := open("targets.txt").trim().split("\n"); for(p : paths) { touch(p) }; print("OK")

Every observation passed its output and filesystem oracle. Reconstructed fixture setup and verification are outside elapsed time. Exact source, manifest and oracle hashes, commands, samples, waited-child high-water RSS and validation records are preserved in shell-workloads.json.

delete-selected-100000

Implementations, invocations, tails and correctness
delete-selected-100000 retained tails; no outliers removed
Distribution · secondsBashZshFishNushellNiftGNU baseline
p952.5252.7372.7717.0303.1242.652
Minimum2.0952.1572.5066.5022.7232.119
Maximum2.5322.7522.7827.0563.1322.741
delete-selected-100000 implementation boundaries
SystemImplementation
Bashbatched GNU utilities
Zshbatched GNU utilities
Fishbatched GNU utilities
Nushellnative filesystem API
Niftnative filesystem API
GNU baselinedirect GNU xargs + /usr/bin/rm

Bash

/usr/bin/xargs -0 -a targets.nul /usr/bin/rm --; echo OK

Zsh

/usr/bin/xargs -0 -a targets.nul /usr/bin/rm --; echo OK

Fish

/usr/bin/xargs -0 -a targets.nul /usr/bin/rm --; echo OK

Nushell

let paths = (open --raw targets.txt | lines); rm ...$paths; print OK

Nift

paths := open("targets.txt").trim().split("\n"); remove(paths); print("OK")

GNU baseline

/usr/bin/xargs -0 -a targets.nul /usr/bin/rm --

Every observation passed its output and filesystem oracle. Reconstructed fixture setup and verification are outside elapsed time. Exact source, manifest and oracle hashes, commands, samples, waited-child high-water RSS and validation records are preserved in shell-workloads.json.

create-small-100000

end-to-end; 5 measured samples + 1 warmups per participant · common linear axis: 0–11.689 s
MeasurementBashZshFishNushellNift
Median elapsed time0–11.689 s
Median s4.9056.7638.1074.76910.824
p95 s4.9776.8828.2354.99410.925
Implementations, invocations, tails and correctness
create-small-100000 implementation boundaries
SystemImplementation
Bashshell redirection
Zshshell redirection
Fishshell redirection
Nushellnative filesystem API
Niftnative filesystem API

Bash

while IFS= read -r p || [ -n "$p" ]; do printf '%s' '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcde
' > "$p"; done < targets.txt; echo OK

Zsh

while IFS= read -r p || [ -n "$p" ]; do printf '%s' '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcde
' > "$p"; done < targets.txt; echo OK

Fish

while read -l p; printf %s '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcde
' > "$p"; end < targets.txt; echo OK

Nushell

for p in (open --raw targets.txt | lines) { "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcde\n" | save --raw $p }; print OK

Nift

paths := open("targets.txt").trim().split("\n"); for(p : paths) { f := file(p); f.open("w"); f.write("0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcde\n"); f.save(); f.close() }; print("OK")

Every observation passed its output and filesystem oracle. Reconstructed fixture setup and verification are outside elapsed time. Exact source, manifest and oracle hashes, commands, samples, waited-child high-water RSS and validation records are preserved in shell-workloads.json.

delete-tree-100000

end-to-end; 5 measured samples + 1 warmups per participant · common linear axis: 0–7.890 s
MeasurementBashZshFishNushellNiftGNU baseline
Median elapsed time0–7.890 s
Median s2.1992.4462.2647.3062.8482.167
p95 s2.7432.5752.3967.6083.1512.662
Implementations, invocations, tails and correctness
delete-tree-100000 implementation boundaries
SystemImplementation
Bashbatched GNU utilities
Zshbatched GNU utilities
Fishbatched GNU utilities
Nushellnative filesystem API
Niftnative filesystem API
GNU baselinedirect GNU xargs + /usr/bin/rm

Bash

/usr/bin/xargs -0 -a targets.nul /usr/bin/rm --; echo OK

Zsh

/usr/bin/xargs -0 -a targets.nul /usr/bin/rm --; echo OK

Fish

/usr/bin/xargs -0 -a targets.nul /usr/bin/rm --; echo OK

Nushell

let paths = (open --raw targets.txt | lines); rm ...$paths; print OK

Nift

paths := open("targets.txt").trim().split("\n"); remove(paths); print("OK")

GNU baseline

/usr/bin/xargs -0 -a targets.nul /usr/bin/rm --

Every observation passed its output and filesystem oracle. Reconstructed fixture setup and verification are outside elapsed time. Exact source, manifest and oracle hashes, commands, samples, waited-child high-water RSS and validation records are preserved in shell-workloads.json.

copy-small-10000

end-to-end; 10 measured samples + 2 warmups per participant · common linear axis: 0–1.812 s
MeasurementBashZshFishNushellNiftGNU baseline
Median elapsed time0–1.812 s
Median s0.5240.5230.5291.6780.7680.515
p95 s0.5410.5530.5391.7230.7850.546
Implementations, invocations, tails and correctness
copy-small-10000 implementation boundaries
SystemImplementation
Bashbatched GNU utilities
Zshbatched GNU utilities
Fishbatched GNU utilities
Nushellnative filesystem API
Niftnative filesystem API
GNU baselinedirect GNU xargs + /usr/bin/cp

Bash

/usr/bin/xargs -0 -a targets.nul /usr/bin/cp -t copied --; echo OK

Zsh

/usr/bin/xargs -0 -a targets.nul /usr/bin/cp -t copied --; echo OK

Fish

/usr/bin/xargs -0 -a targets.nul /usr/bin/cp -t copied --; echo OK

Nushell

for p in (open --raw targets.txt | lines) { cp $p ("copied/" + ($p | path basename)) }; print OK

Nift

paths := open("targets.txt").trim().split("\n"); for(p : paths) { copy(p, "copied/" + p.split("/").last()) }; print("OK")

GNU baseline

/usr/bin/xargs -0 -a targets.nul /usr/bin/cp -t copied --

Every observation passed its output and filesystem oracle. Reconstructed fixture setup and verification are outside elapsed time. Exact source, manifest and oracle hashes, commands, samples, waited-child high-water RSS and validation records are preserved in shell-workloads.json.

rename-selected-10000

end-to-end; 10 measured samples + 2 warmups per participant · common linear axis: 0–1.267 s
MeasurementBashZshFishNushellNiftGNU baseline
Median elapsed time0–1.267 s
Median s0.3550.3450.3461.1730.5470.343
p95 s0.3660.3560.3861.2690.5840.364
Implementations, invocations, tails and correctness
rename-selected-10000 implementation boundaries
SystemImplementation
Bashbatched GNU utilities
Zshbatched GNU utilities
Fishbatched GNU utilities
Nushellnative filesystem API
Niftnative filesystem API
GNU baselinedirect GNU xargs + /usr/bin/mv

Bash

/usr/bin/xargs -0 -a targets.nul /usr/bin/mv -t moved --; echo OK

Zsh

/usr/bin/xargs -0 -a targets.nul /usr/bin/mv -t moved --; echo OK

Fish

/usr/bin/xargs -0 -a targets.nul /usr/bin/mv -t moved --; echo OK

Nushell

for p in (open --raw targets.txt | lines) { mv $p ("moved/" + ($p | path basename)) }; print OK

Nift

paths := open("targets.txt").trim().split("\n"); for(p : paths) { move(p, "moved/" + p.split("/").last()) }; print("OK")

GNU baseline

/usr/bin/xargs -0 -a targets.nul /usr/bin/mv -t moved --

Every observation passed its output and filesystem oracle. Reconstructed fixture setup and verification are outside elapsed time. Exact source, manifest and oracle hashes, commands, samples, waited-child high-water RSS and validation records are preserved in shell-workloads.json.

concat-small-10000

end-to-end; 10 measured samples + 2 warmups per participant · common linear axis: 0–0.591 s
MeasurementBashZshFishNushellNift
Median elapsed time0–0.591 s
Median s0.1050.1050.1080.5480.253
p95 s0.1170.1120.1240.5730.275
Implementations, invocations, tails and correctness
concat-small-10000 implementation boundaries
SystemImplementation
Bashbatched GNU utilities
Zshbatched GNU utilities
Fishbatched GNU utilities
Nushellnative filesystem API
Niftnative filesystem API

Bash

/usr/bin/xargs -0 -a targets.nul /usr/bin/cat -- > output; echo OK

Zsh

/usr/bin/xargs -0 -a targets.nul /usr/bin/cat -- > output; echo OK

Fish

/usr/bin/xargs -0 -a targets.nul /usr/bin/cat -- > output; echo OK

Nushell

open --raw targets.txt | lines | each {|p| open --raw $p } | str join | save --raw output; print OK

Nift

paths := open("targets.txt").trim().split("\n"); dest := file("output"); dest.open("w"); for(p : paths) { dest.write(open(p)) }; dest.save(); dest.close(); print("OK")

Every observation passed its output and filesystem oracle. Reconstructed fixture setup and verification are outside elapsed time. Exact source, manifest and oracle hashes, commands, samples, waited-child high-water RSS and validation records are preserved in shell-workloads.json.

metadata-10000

end-to-end; 10 measured samples + 2 warmups per participant · common linear axis: 0–1.944 s
MeasurementBashZshFishNushellNift
Median elapsed time0–1.944 s
Median s0.0410.0410.0411.8000.119
p95 s0.0470.0440.0441.8470.130
Implementations, invocations, tails and correctness
metadata-10000 implementation boundaries
SystemImplementation
Bashbatched GNU utilities
Zshbatched GNU utilities
Fishbatched GNU utilities
Nushellnative filesystem API
Niftnative filesystem API

Bash

/usr/bin/xargs -0 -a targets.nul /usr/bin/stat --printf='%s\n' -- | /usr/bin/awk '{s+=$1} END{printf "%.0f\n",s}'

Zsh

/usr/bin/xargs -0 -a targets.nul /usr/bin/stat --printf='%s\n' -- | /usr/bin/awk '{s+=$1} END{printf "%.0f\n",s}'

Fish

/usr/bin/xargs -0 -a targets.nul /usr/bin/stat --printf='%s\n' -- | /usr/bin/awk '{s+=$1} END{printf "%.0f\n",s}'

Nushell

let total = (open --raw targets.txt | lines | each {|p| ls $p | get size | first | into int } | math sum); print $total

Nift

paths := open("targets.txt").trim().split("\n"); total := 0; for(p : paths) { total += stat(p).size }; print(total)

Every observation passed its output and filesystem oracle. Reconstructed fixture setup and verification are outside elapsed time. Exact source, manifest and oracle hashes, commands, samples, waited-child high-water RSS and validation records are preserved in shell-workloads.json.

traverse-100000

end-to-end; 5 measured samples + 1 warmups per participant · common linear axis: 0–1.116 s
MeasurementBashZshFishNushellNift
Median elapsed time0–1.116 s
Median s0.4830.4830.4860.2551.033
p95 s0.5120.5180.4980.2731.077
Implementations, invocations, tails and correctness
traverse-100000 implementation boundaries
SystemImplementation
Bashbatched GNU utilities
Zshbatched GNU utilities
Fishbatched GNU utilities
Nushellnative filesystem API
Niftnative filesystem API

Bash

/usr/bin/find files -type f -name '*.dat' -printf '%s\n' | /usr/bin/awk '{n++;s+=$1} END{print n}'

Zsh

/usr/bin/find files -type f -name '*.dat' -printf '%s\n' | /usr/bin/awk '{n++;s+=$1} END{print n}'

Fish

/usr/bin/find files -type f -name '*.dat' -printf '%s\n' | /usr/bin/awk '{n++;s+=$1} END{print n}'

Nushell

print (glob "files/**/*.dat" | length)

Nift

paths := ls("files/**/*.dat"); print(paths.size())

Every observation passed its output and filesystem oracle. Reconstructed fixture setup and verification are outside elapsed time. Exact source, manifest and oracle hashes, commands, samples, waited-child high-water RSS and validation records are preserved in shell-workloads.json.

processes

Process scaling: 1 → 10 → 100 → 1,000

Process scaling: 1 → 10 → 100 → 1,000 · shared zero-based axis: 0–1.051 s
Task sizeBashZshFishNushellNift
Elapsed time vs sizeLogarithmic task-size axis;
lines connect measured points.
1: 0.003 s110: 0.010 s10100: 0.084 s1001000: 0.850 s10001: 0.003 s110: 0.012 s10100: 0.100 s1001000: 0.973 s10001: 0.004 s110: 0.010 s10100: 0.073 s1001000: 0.685 s10001: 0.015 s110: 0.022 s10100: 0.095 s1001000: 0.819 s10001: 0.004 s110: 0.012 s10100: 0.094 s1001000: 0.910 s1000
10.0030.0030.0040.0150.004
100.0100.0120.0100.0220.012
1000.0840.1000.0730.0950.094
10000.8500.9730.6850.8190.910

processes-1

Implementations, invocations, tails and correctness
processes-1 retained tails; no outliers removed
Distribution · secondsBashZshFishNushellNift
p950.0030.0030.0040.0160.004
Minimum0.0030.0030.0030.0140.003
Maximum0.0030.0030.0040.0160.004
processes-1 implementation boundaries
SystemImplementation
Bashcommon external utilities
Zshcommon external utilities
Fishcommon external utilities
Nushellcommon external utilities
Niftcommon external utilities

Bash

for ((i=0;i<1;i++)); do /usr/bin/true || exit 1; done; echo 1

Zsh

for ((i=0;i<1;i++)); do /usr/bin/true || exit 1; done; echo 1

Fish

set i 0; while test $i -lt 1; /usr/bin/true; or exit 1; set i (math $i + 1); end; echo $i

Nushell

for i in 1..1 { ^/usr/bin/true; if $env.LAST_EXIT_CODE != 0 { exit 1 } }; print 1

Nift

i := 0; while(i < 1) { r := run("/usr/bin/true"); if(r.exit_code != 0) { print("FAIL") }; i += 1 }; print(i)

Every observation passed its output and filesystem oracle. Reconstructed fixture setup and verification are outside elapsed time. Exact source, manifest and oracle hashes, commands, samples, waited-child high-water RSS and validation records are preserved in shell-workloads.json.

processes-10

Implementations, invocations, tails and correctness
processes-10 retained tails; no outliers removed
Distribution · secondsBashZshFishNushellNift
p950.0110.0130.0110.0240.012
Minimum0.0100.0110.0090.0210.011
Maximum0.0120.0140.0110.0240.012
processes-10 implementation boundaries
SystemImplementation
Bashcommon external utilities
Zshcommon external utilities
Fishcommon external utilities
Nushellcommon external utilities
Niftcommon external utilities

Bash

for ((i=0;i<10;i++)); do /usr/bin/true || exit 1; done; echo 10

Zsh

for ((i=0;i<10;i++)); do /usr/bin/true || exit 1; done; echo 10

Fish

set i 0; while test $i -lt 10; /usr/bin/true; or exit 1; set i (math $i + 1); end; echo $i

Nushell

for i in 1..10 { ^/usr/bin/true; if $env.LAST_EXIT_CODE != 0 { exit 1 } }; print 10

Nift

i := 0; while(i < 10) { r := run("/usr/bin/true"); if(r.exit_code != 0) { print("FAIL") }; i += 1 }; print(i)

Every observation passed its output and filesystem oracle. Reconstructed fixture setup and verification are outside elapsed time. Exact source, manifest and oracle hashes, commands, samples, waited-child high-water RSS and validation records are preserved in shell-workloads.json.

processes-100

Implementations, invocations, tails and correctness
processes-100 retained tails; no outliers removed
Distribution · secondsBashZshFishNushellNift
p950.0900.1050.0790.1000.099
Minimum0.0820.0960.0710.0920.089
Maximum0.0910.1060.0800.1000.100
processes-100 implementation boundaries
SystemImplementation
Bashcommon external utilities
Zshcommon external utilities
Fishcommon external utilities
Nushellcommon external utilities
Niftcommon external utilities

Bash

for ((i=0;i<100;i++)); do /usr/bin/true || exit 1; done; echo 100

Zsh

for ((i=0;i<100;i++)); do /usr/bin/true || exit 1; done; echo 100

Fish

set i 0; while test $i -lt 100; /usr/bin/true; or exit 1; set i (math $i + 1); end; echo $i

Nushell

for i in 1..100 { ^/usr/bin/true; if $env.LAST_EXIT_CODE != 0 { exit 1 } }; print 100

Nift

i := 0; while(i < 100) { r := run("/usr/bin/true"); if(r.exit_code != 0) { print("FAIL") }; i += 1 }; print(i)

Every observation passed its output and filesystem oracle. Reconstructed fixture setup and verification are outside elapsed time. Exact source, manifest and oracle hashes, commands, samples, waited-child high-water RSS and validation records are preserved in shell-workloads.json.

processes-1000

Implementations, invocations, tails and correctness
processes-1000 retained tails; no outliers removed
Distribution · secondsBashZshFishNushellNift
p950.8791.0100.7100.8730.932
Minimum0.8040.9470.6740.7920.892
Maximum0.8921.0100.7150.8920.946
processes-1000 implementation boundaries
SystemImplementation
Bashcommon external utilities
Zshcommon external utilities
Fishcommon external utilities
Nushellcommon external utilities
Niftcommon external utilities

Bash

for ((i=0;i<1000;i++)); do /usr/bin/true || exit 1; done; echo 1000

Zsh

for ((i=0;i<1000;i++)); do /usr/bin/true || exit 1; done; echo 1000

Fish

set i 0; while test $i -lt 1000; /usr/bin/true; or exit 1; set i (math $i + 1); end; echo $i

Nushell

for i in 1..1000 { ^/usr/bin/true; if $env.LAST_EXIT_CODE != 0 { exit 1 } }; print 1000

Nift

i := 0; while(i < 1000) { r := run("/usr/bin/true"); if(r.exit_code != 0) { print("FAIL") }; i += 1 }; print(i)

Every observation passed its output and filesystem oracle. Reconstructed fixture setup and verification are outside elapsed time. Exact source, manifest and oracle hashes, commands, samples, waited-child high-water RSS and validation records are preserved in shell-workloads.json.

pipelines

Pipeline scaling: 2 → 4 → 8 stages

Pipeline scaling: 2 → 4 → 8 stages · shared zero-based axis: 0–0.025 s
Task sizeBashZshFishNushellNift
Elapsed time vs sizeLogarithmic task-size axis;
lines connect measured points.
2: 0.004 s24: 0.007 s48: 0.012 s82: 0.005 s24: 0.008 s48: 0.013 s82: 0.005 s24: 0.006 s48: 0.010 s82: 0.017 s24: 0.019 s48: 0.023 s82: 0.005 s24: 0.007 s48: 0.012 s8
20.0040.0050.0050.0170.005
40.0070.0080.0060.0190.007
80.0120.0130.0100.0230.012

pipeline-2

Implementations, invocations, tails and correctness
pipeline-2 retained tails; no outliers removed
Distribution · secondsBashZshFishNushellNift
p950.0050.0060.0060.0200.005
Minimum0.0040.0050.0040.0150.005
Maximum0.0060.0060.0060.0220.006
pipeline-2 implementation boundaries
SystemImplementation
Bashcommon external utilities
Zshcommon external utilities
Fishcommon external utilities
Nushellcommon external utilities
Niftcommon external utilities

Bash

/usr/bin/printf pipeline | /usr/bin/cat

Zsh

/usr/bin/printf pipeline | /usr/bin/cat

Fish

/usr/bin/printf pipeline | /usr/bin/cat

Nushell

^/usr/bin/printf pipeline | ^/usr/bin/cat

Nift

r := cmd("/usr/bin/printf", "pipeline").pipe(cmd("/usr/bin/cat")).run(); print(r.stdout)

Every observation passed its output and filesystem oracle. Reconstructed fixture setup and verification are outside elapsed time. Exact source, manifest and oracle hashes, commands, samples, waited-child high-water RSS and validation records are preserved in shell-workloads.json.

pipeline-4

Implementations, invocations, tails and correctness
pipeline-4 retained tails; no outliers removed
Distribution · secondsBashZshFishNushellNift
p950.0070.0090.0070.0200.008
Minimum0.0060.0070.0060.0180.007
Maximum0.0070.0090.0070.0210.008
pipeline-4 implementation boundaries
SystemImplementation
Bashcommon external utilities
Zshcommon external utilities
Fishcommon external utilities
Nushellcommon external utilities
Niftcommon external utilities

Bash

/usr/bin/printf pipeline | /usr/bin/cat | /usr/bin/cat | /usr/bin/cat

Zsh

/usr/bin/printf pipeline | /usr/bin/cat | /usr/bin/cat | /usr/bin/cat

Fish

/usr/bin/printf pipeline | /usr/bin/cat | /usr/bin/cat | /usr/bin/cat

Nushell

^/usr/bin/printf pipeline | ^/usr/bin/cat | ^/usr/bin/cat | ^/usr/bin/cat

Nift

r := cmd("/usr/bin/printf", "pipeline").pipe(cmd("/usr/bin/cat")).pipe(cmd("/usr/bin/cat")).pipe(cmd("/usr/bin/cat")).run(); print(r.stdout)

Every observation passed its output and filesystem oracle. Reconstructed fixture setup and verification are outside elapsed time. Exact source, manifest and oracle hashes, commands, samples, waited-child high-water RSS and validation records are preserved in shell-workloads.json.

pipeline-8

Implementations, invocations, tails and correctness
pipeline-8 retained tails; no outliers removed
Distribution · secondsBashZshFishNushellNift
p950.0140.0140.0140.0280.014
Minimum0.0110.0120.0100.0220.011
Maximum0.0150.0140.0140.0320.015
pipeline-8 implementation boundaries
SystemImplementation
Bashcommon external utilities
Zshcommon external utilities
Fishcommon external utilities
Nushellcommon external utilities
Niftcommon external utilities

Bash

/usr/bin/printf pipeline | /usr/bin/cat | /usr/bin/cat | /usr/bin/cat | /usr/bin/cat | /usr/bin/cat | /usr/bin/cat | /usr/bin/cat

Zsh

/usr/bin/printf pipeline | /usr/bin/cat | /usr/bin/cat | /usr/bin/cat | /usr/bin/cat | /usr/bin/cat | /usr/bin/cat | /usr/bin/cat

Fish

/usr/bin/printf pipeline | /usr/bin/cat | /usr/bin/cat | /usr/bin/cat | /usr/bin/cat | /usr/bin/cat | /usr/bin/cat | /usr/bin/cat

Nushell

^/usr/bin/printf pipeline | ^/usr/bin/cat | ^/usr/bin/cat | ^/usr/bin/cat | ^/usr/bin/cat | ^/usr/bin/cat | ^/usr/bin/cat | ^/usr/bin/cat

Nift

r := cmd("/usr/bin/printf", "pipeline").pipe(cmd("/usr/bin/cat")).pipe(cmd("/usr/bin/cat")).pipe(cmd("/usr/bin/cat")).pipe(cmd("/usr/bin/cat")).pipe(cmd("/usr/bin/cat")).pipe(cmd("/usr/bin/cat")).pipe(cmd("/usr/bin/cat")).run(); print(r.stdout)

Every observation passed its output and filesystem oracle. Reconstructed fixture setup and verification are outside elapsed time. Exact source, manifest and oracle hashes, commands, samples, waited-child high-water RSS and validation records are preserved in shell-workloads.json.

text

Text and Unix workflows

log-filter-group

orchestration; 10 measured samples + 2 warmups per participant · common linear axis: 0–0.064 s
MeasurementBashZshFishNushellNift
Median elapsed time0–0.064 s
Median s0.0460.0480.0460.0590.048
p95 s0.0500.0500.0480.0620.050
Implementations, invocations, tails and correctness
log-filter-group implementation boundaries
SystemImplementation
Bashcommon external utilities
Zshcommon external utilities
Fishcommon external utilities
Nushellcommon external utilities
Niftcommon external utilities

Bash

/usr/bin/grep '^ERROR' logs.txt | /usr/bin/awk '{print $2}' | /usr/bin/sort  | /usr/bin/uniq '-c'

Zsh

/usr/bin/grep '^ERROR' logs.txt | /usr/bin/awk '{print $2}' | /usr/bin/sort  | /usr/bin/uniq '-c'

Fish

/usr/bin/grep '^ERROR' logs.txt | /usr/bin/awk '{print $2}' | /usr/bin/sort  | /usr/bin/uniq '-c'

Nushell

^/usr/bin/grep '^ERROR' logs.txt | ^/usr/bin/awk '{print $2}' | ^/usr/bin/sort  | ^/usr/bin/uniq '-c'

Nift

r := cmd("/usr/bin/grep", "^ERROR", "logs.txt").pipe(cmd("/usr/bin/awk", "{print $2}").pipe(cmd("/usr/bin/sort").pipe(cmd("/usr/bin/uniq", "-c")))).run(); print(r.stdout)

Every observation passed its output and filesystem oracle. Reconstructed fixture setup and verification are outside elapsed time. Exact source, manifest and oracle hashes, commands, samples, waited-child high-water RSS and validation records are preserved in shell-workloads.json.

This log filter/group workload uses the same grep → awk → sort → uniq engines in all shells. Its timings include orchestration and utility work; it does not compare five native text engines.

algorithms

Substantial logic in the shell

arithmetic

runtime-native; 10 measured samples + 2 warmups per participant · common linear axis: 0–3.395 s
MeasurementBashZshFishNushellNift
Median elapsed time0–3.395 s
Median s0.0660.0263.1430.0310.017
p95 s0.0670.0373.4160.0360.018
Implementations, invocations, tails and correctness
arithmetic implementation boundaries
SystemImplementation
Bashnative shell code
Zshnative shell code
Fishnative shell code
Nushellnative shell code
Niftnative shell code

Bash

s=0; for ((i=1;i<=20000;i++)); do s=$((s+i)); done; echo $s

Zsh

s=0; for ((i=1;i<=20000;i++)); do s=$((s+i)); done; echo $s

Fish

set s 0; set i 1; while test $i -le 20000; set s (math $s + $i); set i (math $i + 1); end; echo $s

Nushell

mut s = 0; for i in 1..20000 { $s = $s + $i }; print $s

Nift

s := 0; i := 1; while(i <= 20000) { s += i; i += 1 }; print(s)

Every observation passed its output and filesystem oracle. Reconstructed fixture setup and verification are outside elapsed time. Exact source, manifest and oracle hashes, commands, samples, waited-child high-water RSS and validation records are preserved in shell-workloads.json.

function-calls

runtime-native; 10 measured samples + 2 warmups per participant · common linear axis: 0–1.462 s
MeasurementBashZshFishNushellNift
Median elapsed time0–1.462 s
Median s0.0530.1421.3540.0440.022
p95 s0.0600.1431.4010.0470.023
Implementations, invocations, tails and correctness
function-calls implementation boundaries
SystemImplementation
Bashnative shell code
Zshnative shell code
Fishnative shell code
Nushellnative shell code
Niftnative shell code

Bash

inc() { s=$((s+1)); }; s=0; for ((i=0;i<10000;i++)); do inc; done; echo $s

Zsh

inc() { s=$((s+1)); }; s=0; for ((i=0;i<10000;i++)); do inc; done; echo $s

Fish

function inc; set -g s (math $s + 1); end; set s 0; set i 0; while test $i -lt 10000; inc; set i (math $i + 1); end; echo $s

Nushell

def inc [x: int] { $x + 1 }; mut s = 0; for i in 1..10000 { $s = (inc $s) }; print $s

Nift

fn(inc(x)) { return x+1 }; s := 0; i := 0; while(i < 10000) { s = inc(s); i += 1 }; print(s)

Every observation passed its output and filesystem oracle. Reconstructed fixture setup and verification are outside elapsed time. Exact source, manifest and oracle hashes, commands, samples, waited-child high-water RSS and validation records are preserved in shell-workloads.json.

fibonacci-mod

runtime-native; 10 measured samples + 2 warmups per participant · common linear axis: 0–0.162 s
MeasurementBashZshFishNushellNift
Median elapsed time0–0.162 s
Median s0.0080.0050.1500.0160.004
p95 s0.0110.0050.1630.0170.006
Implementations, invocations, tails and correctness
fibonacci-mod implementation boundaries
SystemImplementation
Bashnative shell code
Zshnative shell code
Fishnative shell code
Nushellnative shell code
Niftnative shell code

Bash

a=0; b=1; for ((i=0;i<1000;i++)); do t=$(((a+b)%1000000)); a=$b; b=$t; done; echo $a

Zsh

a=0; b=1; for ((i=0;i<1000;i++)); do t=$(((a+b)%1000000)); a=$b; b=$t; done; echo $a

Fish

set a 0; set b 1; set i 0; while test $i -lt 1000; set t (math "($a + $b) % 1000000"); set a $b; set b $t; set i (math $i + 1); end; echo $a

Nushell

mut a = 0; mut b = 1; for i in 1..1000 { let t = (($a + $b) mod 1000000); $a = $b; $b = $t }; print $a

Nift

a := 0; b := 1; i := 0; while(i < 1000) { t := (a+b)%1000000; a=b; b=t; i+=1 }; print(a)

Every observation passed its output and filesystem oracle. Reconstructed fixture setup and verification are outside elapsed time. Exact source, manifest and oracle hashes, commands, samples, waited-child high-water RSS and validation records are preserved in shell-workloads.json.

string-transform

runtime-native; 10 measured samples + 2 warmups per participant · common linear axis: 0–0.899 s
MeasurementBashZshFishNushellNift
Median elapsed time0–0.899 s
Median s0.0360.0140.8320.0470.019
p95 s0.0410.0180.8730.0510.019
Implementations, invocations, tails and correctness
string-transform implementation boundaries
SystemImplementation
Bashnative shell code
Zshnative shell code
Fishnative shell code
Nushellnative shell code
Niftnative shell code

Bash

for ((i=0;i<5000;i++)); do s=alpha; s=${s^^}; s=${s//A/a}; done; echo $s

Zsh

for ((i=0;i<5000;i++)); do s=alpha; s=${(U)s}; s=${s//A/a}; done; echo $s

Fish

set i 0; while test $i -lt 5000; set s (string upper alpha | string replace -a A a); set i (math $i + 1); end; echo $s

Nushell

mut s = ""; for i in 1..5000 { $s = ("alpha" | str upcase | str replace -a A a) }; print $s

Nift

s := "alpha"; i := 0; while(i < 5000) { s="alpha".to_upper().replace("A","a"); i+=1 }; print(s)

Every observation passed its output and filesystem oracle. Reconstructed fixture setup and verification are outside elapsed time. Exact source, manifest and oracle hashes, commands, samples, waited-child high-water RSS and validation records are preserved in shell-workloads.json.

Four bounded native scripting cases cover arithmetic, calls, iterative modular Fibonacci and string transforms. Fish uses its builtin math/test/string operations; builtin pipelines and command substitutions still incur shell machinery. No deliberately pathological recursion or unsupported map API is forced onto a participant.

real-world

Mixed workflows

source-tree-report

orchestration; 10 measured samples + 2 warmups per participant · common linear axis: 0–0.258 s
MeasurementBashZshFishNushellNift
Median elapsed time0–0.258 s
Median s0.2200.2260.2290.2390.230
p95 s0.2330.2500.2360.2630.256
Implementations, invocations, tails and correctness
source-tree-report implementation boundaries
SystemImplementation
Bashcommon find → xargs/wc → awk pipeline
Zshcommon find → xargs/wc → awk pipeline
Fishcommon find → xargs/wc → awk pipeline
Nushellcommon find → xargs/wc → awk pipeline
Niftcommon find → xargs/wc → awk pipeline

Bash

/usr/bin/find files -type f -print0 | /usr/bin/xargs -0 /usr/bin/wc -lc | /usr/bin/awk '{e=$3; sub(/^.*[.]/,"",e); if($3!="total") {c[e]++;b[e]+=$2;l[e]+=$1}} END{print "cc",c["cc"],b["cc"],l["cc"];print "dat",c["dat"],b["dat"],l["dat"];print "md",c["md"],b["md"],l["md"];print "py",c["py"],b["py"],l["py"]}'

Zsh

/usr/bin/find files -type f -print0 | /usr/bin/xargs -0 /usr/bin/wc -lc | /usr/bin/awk '{e=$3; sub(/^.*[.]/,"",e); if($3!="total") {c[e]++;b[e]+=$2;l[e]+=$1}} END{print "cc",c["cc"],b["cc"],l["cc"];print "dat",c["dat"],b["dat"],l["dat"];print "md",c["md"],b["md"],l["md"];print "py",c["py"],b["py"],l["py"]}'

Fish

/usr/bin/find files -type f -print0 | /usr/bin/xargs -0 /usr/bin/wc -lc | /usr/bin/awk '{e=$3; sub(/^.*[.]/,"",e); if($3!="total") {c[e]++;b[e]+=$2;l[e]+=$1}} END{print "cc",c["cc"],b["cc"],l["cc"];print "dat",c["dat"],b["dat"],l["dat"];print "md",c["md"],b["md"],l["md"];print "py",c["py"],b["py"],l["py"]}'

Nushell

^/usr/bin/find files -type f -print0 | ^/usr/bin/xargs -0 /usr/bin/wc -lc | ^/usr/bin/awk '{e=$3; sub(/^.*[.]/,"",e); if($3!="total") {c[e]++;b[e]+=$2;l[e]+=$1}} END{print "cc",c["cc"],b["cc"],l["cc"];print "dat",c["dat"],b["dat"],l["dat"];print "md",c["md"],b["md"],l["md"];print "py",c["py"],b["py"],l["py"]}'

Nift

r := cmd("/usr/bin/find", "files", "-type", "f", "-print0").pipe(cmd("/usr/bin/xargs", "-0", "/usr/bin/wc", "-lc")).pipe(cmd("/usr/bin/awk", "{e=$3; sub(/^.*[.]/,\"\",e); if($3!=\"total\") {c[e]++;b[e]+=$2;l[e]+=$1}} END{print \"cc\",c[\"cc\"],b[\"cc\"],l[\"cc\"];print \"dat\",c[\"dat\"],b[\"dat\"],l[\"dat\"];print \"md\",c[\"md\"],b[\"md\"],l[\"md\"];print \"py\",c[\"py\"],b[\"py\"],l[\"py\"]}")).run(); print(r.stdout)

Every observation passed its output and filesystem oracle. Reconstructed fixture setup and verification are outside elapsed time. Exact source, manifest and oracle hashes, commands, samples, waited-child high-water RSS and validation records are preserved in shell-workloads.json.

selected-cleanup

end-to-end; 10 measured samples + 2 warmups per participant · common linear axis: 0–0.117 s
MeasurementBashZshFishNushellNift
Median elapsed time0–0.117 s
Median s0.0320.0330.0350.1090.045
p95 s0.0350.0360.0420.1150.049
Implementations, invocations, tails and correctness
selected-cleanup implementation boundaries
SystemImplementation
Bashbatched GNU utilities
Zshbatched GNU utilities
Fishbatched GNU utilities
Nushellnative filesystem API
Niftnative filesystem API

Bash

/usr/bin/xargs -0 -a targets.nul /usr/bin/rm --; /usr/bin/mkdir report; /usr/bin/xargs -0 -a outputs.nul /usr/bin/mv -t report --; printf "deleted=1000 archived=200" > report/summary; echo OK

Zsh

/usr/bin/xargs -0 -a targets.nul /usr/bin/rm --; /usr/bin/mkdir report; /usr/bin/xargs -0 -a outputs.nul /usr/bin/mv -t report --; printf "deleted=1000 archived=200" > report/summary; echo OK

Fish

/usr/bin/xargs -0 -a targets.nul /usr/bin/rm --; /usr/bin/mkdir report; /usr/bin/xargs -0 -a outputs.nul /usr/bin/mv -t report --; printf "deleted=1000 archived=200" > report/summary; echo OK

Nushell

for p in (open --raw targets.txt | lines) { rm $p }; mkdir report; let outputs = (open --raw outputs.txt | lines); mv ...$outputs report; "deleted=1000 archived=200" | save --raw report/summary; print OK

Nift

paths := open("targets.txt").trim().split("\n"); for(p : paths) { remove(p) }; make_dir("report"); for(p : open("outputs.txt").split("\n")) { move(p, "report/" + p.split("/").last()) }; f := file("report/summary"); f.open("w"); f.write("deleted=1000 archived=200"); f.save(); f.close(); print("OK")

Every observation passed its output and filesystem oracle. Reconstructed fixture setup and verification are outside elapsed time. Exact source, manifest and oracle hashes, commands, samples, waited-child high-water RSS and validation records are preserved in shell-workloads.json.

The common Unix report groups a synthetic .py/.cc/.md tree plus keepers by extension, counting files, bytes and lines. Cleanup deletes its exact temporary-file manifest, preserves keepers, moves 200 outputs into a report directory and writes a verified summary. These combine filesystem APIs and orchestration rather than pretending to isolate an interpreter.

Correctness / limits

Fast and wrong does not qualify.

The additive workload layer retains 1,275 measured observations and 255 warmups across 141 jobs. Ordinary cases use 10 + 2; heavyweight 100k cases use 5 + 1. Each sample reconstructs and checks its fixture before timing, then checks complete output and filesystem postconditions afterwards. Runtime-native, orchestration, end-to-end and direct GNU baselines stay separate. New case order and participant order within each case rotate. Waited-child RSS is retained in raw data but does not measure simultaneous aggregate process-tree memory.

The compiled PTY bridge avoids Python heap fork latency. Minimal probe measurements disclose remaining launch/forwarding/scheduling overhead; differences near that floor need care.

Complete-state certification before and after collection validates every synthetic variable/function, conditional and PATH prefix. These final startup results are direct measurements, with no subtraction of RC-body diagnostics.

Non-interactive invocations must exit successfully and yield expected output. PTY timing ends at prompt arrival, followed by its command/state oracle; the bridge then terminates the child process group, so a natural-exit status and teardown RSS are outside that boundary. Failures retain non-publishable evidence. Prepared startup cells contain 100 samples; fresh-state startup cells contain 30; both have 3 retained warmups. Configured fresh Zsh rebuilds system completion state, so its expensive series uses 30 samples, frozen before collection. No sample was excluded. Work cells contain 10 plus 3. Order rotates each round.

An allowlisted environment and job-specific HOME/XDG/ZDOTDIR prevent BASH_ENV, ENV, inherited functions, personal dotfiles or tokens from entering measured processes. Terminal queries receive documented xterm responses. OSC 133 prompt completion is used where available, otherwise prompt suffix detection; the oracle proves the shell is usable afterwards. This terminal model affects interactive startup and limits generalisation.

Configuration discovery, parsing, history and lazy initialization can interact. No additive RC decomposition is justified. Rich runtime features and low bare startup answer different engineering questions.

Separate recovery diagnostic

Same-node checks for the surprising changes.

Separate same-node diagnostic: exact clean source builds c8d9c266 (previous release), 7f7e487 (original candidate) and c14d068 (final), using the same GCC 13.3 / native Make -O2 configuration, CPU 0, ten measured samples plus two warmups per case/version, six-permutation adjacent ordering and unchanged source/output oracles. All 72 observations passed independent audit; these are not pooled into official peer tables.

Separate three-version recovery diagnostic; medians, 10 measured samples per cell
CaseRelease msOriginal candidate msFinal candidate ms
function-calls20.98944.97121.655
string-transform59.69666.95018.680

Calls improved 51.85% from the original candidate; final versus release differed by 0.666 ms (+3.17%), with overlapping ranges. Strings improved 72.10% versus the original and 68.71% versus release, with disjoint ranges and all ten paired final observations faster. These are fixed-specimen gains, not universal language-speed claims.

Findings and qualifications · All raw samples and build identities · Independent audit.

Practitioner judgement / AI-DX

Choose for the actual workflow.

For established POSIX shell compatibility I would retain Bash or Zsh; interactive preferences and structured-data workflows can favor Fish or Nushell. For authored Nift-owned automation, agent-maintained mixed projects and workflows needing programmable .f policy plus explicit artifact/input/lifecycle contracts, I would choose Nift. That is a contextual practitioner preference, not a claim of drop-in shell equivalence or universal speed leadership. Direct GNU helper-only baselines are excluded from shell peer rankings because their launch boundary differs.

Machine-readable inputs, ownership and dependencies can be useful explicitness rather than redundant ceremony. These qualitative judgements do not turn the harness’s golden-output/fixture checks into automatic product guarantees. Memory remains a separately qualified waited-child high-water measure, not aggregate process-tree usage or a combined performance score.

Frozen environment

Exact source, tools and boundaries.

Final candidate Nift 4.12.0, exact clean source c14d06835bca515a5281e41da0e40219c2d60ef0; CLI SHA-256 7dd42dcee5ca4a6965f0823c0ae59198282da1eb77e0fcd4cae93a537870a6fb. Native Make -O2, GCC 13.3; dedicated g6-standard-4 (8 GB / four vCPUs), Ubuntu 24.04, timed processes pinned to CPU 0. OS caches are uncontrolled; this is not machine-cold timing. Historical hosts and diagnostic cohorts are never pooled.

Detected on this suite’s final measurement host
SystemMeasured version
bashGNU bash, version 5.2.21(1)-release (x86_64-pc-linux-gnu)
zshzsh 5.9 (x86_64-ubuntu-linux-gnu)
fishfish, version 4.9.3
nu0.116.1
niftNift v4.12.0

Exact build identity · Frozen suite and tool pins · Actual compiler/package inventory.

Independent complete-count/distribution audit · Normalized measurements · Complete raw data and retained warmups. No failed or superseded attempt is substituted for this accepted series.

Reproduce / scrutinise

All observations are retained.

Complete accepted series; the frozen suite revision and exact invocation are recorded in its readiness and official controller files. Summaries are independently recomputed from raw observations.

Conclusion

Startup and substantial work, with boundaries.

These observations describe the frozen startup/configuration paths and checked filesystem, orchestration and native scripting tasks. It does not establish a universally fastest shell, feature parity, or machine-cold performance.

Nift Benchmarks

Three perspectives on one runtime.