Modular, context-aware and aspect-oriented dendritic Nix configurations. Discussions: https://oeiuwq.zulipchat.com/join/nqp26cd4kngon6mo3ncgnuap/ den.oeiuwq.com
configurations den dendritic nix aspect oriented
8
fork

Configure Feed

Select the types of activity you want to include in your feed.

bench compares with same performance test suite

+566 -4
+5 -2
Justfile
··· 49 49 rm -rf "{{tmpdir}}/den-head" "{{tmpdir}}/den-base" 50 50 git clone --local --depth 1 --revision "$(git rev-list -n1 {{head}})" .git "{{tmpdir}}/den-head" 2>/dev/null 51 51 git clone --local --depth 1 --revision "$(git rev-list -n1 {{base}})" .git "{{tmpdir}}/den-base" 2>/dev/null 52 + rm -rf "{{tmpdir}}/den-base/templates/ci" 53 + cp -r "{{tmpdir}}/den-head/templates/ci" "{{tmpdir}}/den-base/templates/ci" 54 + pushd "{{tmpdir}}/den-base" && git add templates/ci && popd 52 55 hyperfine -m "{{runs}}" -w "{{warm}}" {{args}} \ 53 - -n head "cd {{tmpdir}}/den-head && nix-shell ./shell.nix --run 'just ci 2>&1 | grep successful'" \ 54 - -n base "cd {{tmpdir}}/den-base && nix-shell ./shell.nix --run 'just ci 2>&1 | grep successful'" 56 + -n head "nix-unit --override-input den {{tmpdir}}/den-head --flake {{tmpdir}}/den-head/templates/ci#.tests.performance 2>&1 | tail -1" \ 57 + -n base "nix-unit --override-input den {{tmpdir}}/den-base --flake {{tmpdir}}/den-base/templates/ci#.tests.performance 2>&1 | tail -1" 55 58 rm -rf "{{tmpdir}}/den-head" "{{tmpdir}}/den-base"
+1 -1
templates/ci/modules/features/perf/ctx-chain.nix
··· 30 30 ) n; 31 31 in 32 32 { 33 - flake.tests.perf-ctx = { 33 + flake.tests.performance.ctx-chain = { 34 34 35 35 test-ctx-chain-5 = denTest ( 36 36 { den, funnyNames, ... }:
+111
templates/ci/modules/features/perf/ctx-pipeline.nix
··· 1 + { denTest, lib, ... }: 2 + let 3 + mkCtxChain = 4 + n: 5 + lib.genList ( 6 + i: 7 + let 8 + name = "c${toString i}"; 9 + next = "c${toString (i + 1)}"; 10 + base = { 11 + _.${name} = 12 + { x }: 13 + { 14 + funny.names = [ "${name}-${x}" ]; 15 + }; 16 + }; 17 + withInto = 18 + if i + 1 < n then 19 + { into.${next} = { x }: [ { x = "${x}+${toString i}"; } ]; } 20 + else 21 + { }; 22 + in 23 + { den, ... }: 24 + { den.ctx.${name} = base // withInto; } 25 + ) n; 26 + 27 + mkFanOut = 28 + n: 29 + { den, ... }: 30 + { 31 + den.ctx.root = { 32 + _.root = 33 + { x }: 34 + { funny.names = [ "root-${x}" ]; }; 35 + into.leaf = { x }: lib.genList (i: { x = "${x}-${toString i}"; }) n; 36 + }; 37 + den.ctx.leaf._.leaf = 38 + { x }: 39 + { funny.names = [ "leaf-${x}" ]; }; 40 + }; 41 + 42 + mkCrossProviders = 43 + n: 44 + let 45 + srcMod = 46 + { den, ... }: 47 + { 48 + den.ctx.src = { 49 + _.src = 50 + { v }: 51 + { funny.names = [ "src-${v}" ]; }; 52 + into = lib.genAttrs (lib.genList (i: "t${toString i}") n) ( 53 + _: 54 + { v }: 55 + [ { v = "${v}!"; } ] 56 + ); 57 + provides = lib.genAttrs (lib.genList (i: "t${toString i}") n) ( 58 + name: 59 + { v }: 60 + { funny.names = [ "cross-${name}-${v}" ]; } 61 + ); 62 + }; 63 + }; 64 + targetMods = lib.genList ( 65 + i: 66 + let 67 + name = "t${toString i}"; 68 + in 69 + { den, ... }: 70 + { 71 + den.ctx.${name}._.${name} = 72 + { v }: 73 + { funny.names = [ "${name}-${v}" ]; }; 74 + } 75 + ) n; 76 + in 77 + [ srcMod ] ++ targetMods; 78 + 79 + in 80 + { 81 + flake.tests.performance.ctx = { 82 + 83 + test-chain-30 = denTest ( 84 + { den, funnyNames, ... }: 85 + { 86 + imports = mkCtxChain 30; 87 + expr = builtins.length (funnyNames (den.ctx.c0 { x = "v"; })); 88 + expected = 30; 89 + } 90 + ); 91 + 92 + test-fan-out-50 = denTest ( 93 + { den, funnyNames, ... }: 94 + { 95 + imports = [ (mkFanOut 50) ]; 96 + expr = builtins.length (funnyNames (den.ctx.root { x = "v"; })); 97 + expected = 51; 98 + } 99 + ); 100 + 101 + test-cross-providers-20 = denTest ( 102 + { den, funnyNames, ... }: 103 + { 104 + imports = mkCrossProviders 20; 105 + expr = builtins.length (funnyNames (den.ctx.src { v = "z"; })); 106 + expected = 41; 107 + } 108 + ); 109 + 110 + }; 111 + }
+1 -1
templates/ci/modules/features/perf/depth.nix
··· 39 39 go 0; 40 40 in 41 41 { 42 - flake.tests.perf-depth = { 42 + flake.tests.performance.depth = { 43 43 44 44 test-deep-10 = denTest ( 45 45 { den, funnyNames, ... }:
+60
templates/ci/modules/features/perf/forward.nix
··· 1 + { denTest, lib, ... }: 2 + { 3 + flake.tests.performance.forward = { 4 + 5 + test-forward-into-funny = denTest ( 6 + { den, funnyNames, ... }: 7 + let 8 + fwd = den._.forward { 9 + each = lib.singleton true; 10 + fromClass = _: "src"; 11 + intoClass = _: "funny"; 12 + intoPath = _: [ ]; 13 + fromAspect = 14 + _: 15 + { class, aspect-chain }: 16 + { src.names = [ "forwarded" ]; }; 17 + }; 18 + in 19 + { 20 + den.aspects.test = { 21 + funny.names = [ "direct" ]; 22 + includes = [ fwd ]; 23 + }; 24 + 25 + expr = funnyNames den.aspects.test; 26 + expected = [ 27 + "direct" 28 + "forwarded" 29 + ]; 30 + } 31 + ); 32 + 33 + test-forward-many-items = denTest ( 34 + { den, funnyNames, ... }: 35 + let 36 + items = lib.genList (i: "item${toString i}") 20; 37 + fwd = den._.forward { 38 + each = items; 39 + fromClass = _: "src"; 40 + intoClass = _: "target"; 41 + intoPath = _: [ "somewhere" ]; 42 + fromAspect = 43 + item: 44 + { class, aspect-chain }: 45 + { src.names = [ item ]; }; 46 + }; 47 + in 48 + { 49 + den.aspects.test = { 50 + funny.names = [ "root" ]; 51 + includes = [ fwd ]; 52 + }; 53 + 54 + expr = funnyNames den.aspects.test; 55 + expected = [ "root" ]; 56 + } 57 + ); 58 + 59 + }; 60 + }
+67
templates/ci/modules/features/perf/namespace.nix
··· 1 + { denTest, inputs, lib, ... }: 2 + { 3 + flake.tests.performance.namespace = { 4 + 5 + test-namespace-many-aspects = denTest ( 6 + { den, ns, funnyNames, ... }: 7 + { 8 + imports = [ (inputs.den.namespace "ns" false) ]; 9 + ns = lib.genAttrs (lib.genList (i: "a${toString i}") 30) ( 10 + name: { funny.names = [ name ]; } 11 + ); 12 + den.aspects.root = { 13 + funny.names = [ "root" ]; 14 + includes = lib.genList (i: ns."a${toString i}") 30; 15 + }; 16 + 17 + expr = builtins.length (funnyNames den.aspects.root); 18 + expected = 31; 19 + } 20 + ); 21 + 22 + test-namespace-merged-sources = denTest ( 23 + { den, ns, funnyNames, ... }: 24 + let 25 + mkSrc = 26 + i: 27 + { 28 + denful.ns = lib.genAttrs (lib.genList (j: "x${toString j}") 10) ( 29 + name: { funny.names = [ "${name}-src${toString i}" ]; } 30 + ); 31 + }; 32 + sources = lib.genList mkSrc 5; 33 + in 34 + { 35 + imports = [ (inputs.den.namespace "ns" sources) ]; 36 + den.aspects.root = { 37 + funny.names = [ "root" ]; 38 + includes = lib.genList (i: ns."x${toString i}") 10; 39 + }; 40 + 41 + expr = builtins.length (funnyNames den.aspects.root); 42 + expected = 51; 43 + } 44 + ); 45 + 46 + test-namespace-with-providers = denTest ( 47 + { den, ns, funnyNames, ... }: 48 + { 49 + imports = [ (inputs.den.namespace "ns" false) ]; 50 + ns.parent = { 51 + funny.names = [ "parent" ]; 52 + provides = lib.genAttrs (lib.genList (i: "p${toString i}") 10) ( 53 + name: { funny.names = [ name ]; } 54 + ); 55 + }; 56 + den.aspects.root = { 57 + funny.names = [ "root" ]; 58 + includes = [ ns.parent ]; 59 + }; 60 + 61 + expr = builtins.length (funnyNames den.aspects.root); 62 + expected = 2; 63 + } 64 + ); 65 + 66 + }; 67 + }
+107
templates/ci/modules/features/perf/parametric.nix
··· 1 + { denTest, lib, ... }: 2 + { 3 + flake.tests.performance.parametric = { 4 + 5 + test-fixedTo-deep-chain = denTest ( 6 + { den, funnyNames, ... }: 7 + let 8 + leaf = den.lib.parametric { 9 + funny.names = [ "leaf" ]; 10 + }; 11 + mid = den.lib.parametric { 12 + funny.names = [ "mid" ]; 13 + includes = [ leaf ]; 14 + }; 15 + top = den.lib.parametric.fixedTo { level = "deep"; } { 16 + funny.names = [ "top" ]; 17 + includes = lib.genList (_: mid) 20; 18 + }; 19 + in 20 + { 21 + den.ctx.start = { 22 + _.start = { level }: { funny.names = [ level ]; }; 23 + includes = [ top ]; 24 + }; 25 + 26 + expr = builtins.length (funnyNames (den.ctx.start { level = "deep"; })); 27 + expected = 42; 28 + } 29 + ); 30 + 31 + test-atLeast-wide = denTest ( 32 + { den, funnyNames, ... }: 33 + let 34 + mkParam = 35 + i: 36 + den.lib.parametric { 37 + funny.names = [ "p${toString i}" ]; 38 + includes = [ 39 + ( 40 + { host, ... }: 41 + { funny.names = [ "i${toString i}-${host}" ]; } 42 + ) 43 + ]; 44 + }; 45 + aspects = lib.genList mkParam 30; 46 + in 47 + { 48 + den.ctx.start = { 49 + _.start = { host }: { funny.names = [ host ]; }; 50 + includes = aspects; 51 + }; 52 + 53 + expr = builtins.length (funnyNames (den.ctx.start { host = "h"; })); 54 + expected = 61; 55 + } 56 + ); 57 + 58 + test-expands-propagation = denTest ( 59 + { den, funnyNames, ... }: 60 + let 61 + inner = 62 + { host, planet, ... }: 63 + { funny.names = [ "${host}-${planet}" ]; }; 64 + expanded = den.lib.parametric.expands { planet = "mars"; } { 65 + funny.names = [ "exp" ]; 66 + includes = lib.genList (_: inner) 15; 67 + }; 68 + in 69 + { 70 + den.ctx.start = { 71 + _.start = { host }: { funny.names = [ host ]; }; 72 + includes = [ expanded ]; 73 + }; 74 + 75 + expr = builtins.length (funnyNames (den.ctx.start { host = "h"; })); 76 + expected = 17; 77 + } 78 + ); 79 + 80 + test-dedup-parametric = denTest ( 81 + { den, funnyNames, ... }: 82 + let 83 + shared = den.lib.parametric { 84 + funny.names = [ "shared" ]; 85 + includes = [ 86 + ({ host, ... }: { funny.names = [ "inner-${host}" ]; }) 87 + ]; 88 + }; 89 + in 90 + { 91 + den.ctx.a = { 92 + _.a = { host }: { funny.names = [ "a-${host}" ]; }; 93 + into.b = { host }: [ { host = "${host}!"; } ]; 94 + includes = [ shared ]; 95 + }; 96 + den.ctx.b = { 97 + _.b = { host }: { funny.names = [ "b-${host}" ]; }; 98 + includes = [ shared ]; 99 + }; 100 + 101 + expr = builtins.length (funnyNames (den.ctx.a { host = "v"; })); 102 + expected = 6; 103 + } 104 + ); 105 + 106 + }; 107 + }
+118
templates/ci/modules/features/perf/pure-eval.nix
··· 1 + { denTest, inputs, lib, ... }: 2 + let 3 + denModule = (import inputs.den.outPath).nixModule inputs; 4 + 5 + evalPure = 6 + module: 7 + lib.evalModules { 8 + modules = [ 9 + denModule 10 + module 11 + ]; 12 + }; 13 + in 14 + { 15 + flake.tests.performance.pure = { 16 + 17 + test-pure-aspects-50 = 18 + let 19 + ev = evalPure ( 20 + { den, ... }: 21 + { 22 + den.aspects = lib.genAttrs (lib.genList (i: "a${toString i}") 50) ( 23 + name: 24 + den.lib.parametric { 25 + my.val = [ name ]; 26 + } 27 + ); 28 + } 29 + ); 30 + expr = builtins.length (builtins.attrNames ev.config.den.aspects); 31 + expected = 50; 32 + in 33 + { inherit expr expected; }; 34 + 35 + test-pure-ctx-chain = 36 + let 37 + ev = evalPure ( 38 + { den, ... }: 39 + { 40 + den.ctx.a = { 41 + _.a = { v }: { my.val = [ v ]; }; 42 + into.b = { v }: [ { v = "${v}!"; } ]; 43 + }; 44 + den.ctx.b._.b = { v }: { my.val = [ v ]; }; 45 + } 46 + ); 47 + asp = ev.config.den.ctx.a { v = "x"; }; 48 + mod = ev.config.den.lib.aspects.resolve "my" asp; 49 + ev2 = lib.evalModules { 50 + modules = [ 51 + mod 52 + { options.val = lib.mkOption { type = lib.types.listOf lib.types.str; }; } 53 + ]; 54 + }; 55 + expr = lib.sort (a: b: a < b) ev2.config.val; 56 + expected = [ 57 + "x" 58 + "x!" 59 + ]; 60 + in 61 + { inherit expr expected; }; 62 + 63 + test-pure-resolve-100 = 64 + let 65 + ev = evalPure ( 66 + { den, ... }: 67 + { 68 + den.aspects.root = { 69 + my.val = [ "root" ]; 70 + includes = lib.genList ( 71 + i: 72 + { my.val = [ "i${toString i}" ]; } 73 + ) 100; 74 + }; 75 + } 76 + ); 77 + mod = ev.config.den.lib.aspects.resolve "my" ev.config.den.aspects.root; 78 + ev2 = lib.evalModules { 79 + modules = [ 80 + mod 81 + { options.val = lib.mkOption { type = lib.types.listOf lib.types.str; }; } 82 + ]; 83 + }; 84 + expr = builtins.length ev2.config.val; 85 + expected = 101; 86 + in 87 + { inherit expr expected; }; 88 + 89 + test-pure-statics = 90 + let 91 + ev = evalPure ( 92 + { den, ... }: 93 + { 94 + den.aspects.base = den.lib.parametric { 95 + my.val = [ "base" ]; 96 + includes = [ 97 + ({ class, ... }: { my.val = [ "static-${class}" ]; }) 98 + ]; 99 + }; 100 + } 101 + ); 102 + mod = ev.config.den.lib.aspects.resolve "my" ev.config.den.aspects.base; 103 + ev2 = lib.evalModules { 104 + modules = [ 105 + mod 106 + { options.val = lib.mkOption { type = lib.types.listOf lib.types.str; }; } 107 + ]; 108 + }; 109 + expr = lib.sort (a: b: a < b) ev2.config.val; 110 + expected = [ 111 + "base" 112 + "static-my" 113 + ]; 114 + in 115 + { inherit expr expected; }; 116 + 117 + }; 118 + }
+93
templates/ci/modules/features/perf/resolve.nix
··· 1 + { denTest, lib, ... }: 2 + let 3 + mkChain = 4 + n: 5 + let 6 + go = 7 + i: 8 + if i >= n then 9 + { funny.names = [ "leaf" ]; } 10 + else 11 + { 12 + funny.names = [ "n${toString i}" ]; 13 + includes = [ (go (i + 1)) ]; 14 + }; 15 + in 16 + go 0; 17 + 18 + mkWide = n: { 19 + funny.names = [ "root" ]; 20 + includes = lib.genList (i: { funny.names = [ "b${toString i}" ]; }) n; 21 + }; 22 + 23 + mkDeepWide = 24 + depth: width: 25 + let 26 + go = 27 + d: 28 + if d >= depth then 29 + { 30 + funny.names = [ "leaf" ]; 31 + includes = lib.genList (i: { funny.names = [ "w${toString i}" ]; }) width; 32 + } 33 + else 34 + { 35 + funny.names = [ "d${toString d}" ]; 36 + includes = [ (go (d + 1)) ]; 37 + }; 38 + in 39 + go 0; 40 + 41 + mkDiamond = n: { 42 + funny.names = [ "top" ]; 43 + includes = 44 + let 45 + shared = { funny.names = [ "shared" ]; }; 46 + in 47 + lib.genList (_: { 48 + funny.names = [ "mid" ]; 49 + includes = [ shared ]; 50 + }) n; 51 + }; 52 + in 53 + { 54 + flake.tests.performance.resolve = { 55 + 56 + test-chain-100 = denTest ( 57 + { den, funnyNames, ... }: 58 + { 59 + den.aspects.deep = mkChain 100; 60 + expr = builtins.length (funnyNames den.aspects.deep); 61 + expected = 101; 62 + } 63 + ); 64 + 65 + test-wide-200 = denTest ( 66 + { den, funnyNames, ... }: 67 + { 68 + den.aspects.wide = mkWide 200; 69 + expr = builtins.length (funnyNames den.aspects.wide); 70 + expected = 201; 71 + } 72 + ); 73 + 74 + test-deep-wide-20x20 = denTest ( 75 + { den, funnyNames, ... }: 76 + { 77 + den.aspects.dw = mkDeepWide 20 20; 78 + expr = builtins.length (funnyNames den.aspects.dw); 79 + expected = 41; 80 + } 81 + ); 82 + 83 + test-diamond-50 = denTest ( 84 + { den, funnyNames, ... }: 85 + { 86 + den.aspects.dia = mkDiamond 50; 87 + expr = builtins.length (funnyNames den.aspects.dia); 88 + expected = 101; 89 + } 90 + ); 91 + 92 + }; 93 + }
+3
templates/ci/modules/features/schema-base-modules.nix
··· 132 132 { den, lib, ... }: 133 133 { 134 134 den.schema.user = 135 + { user, host, ... }: 135 136 { 137 + options.main-group = lib.mkOption { default = user.name; }; 138 + options.description = lib.mkOption { default = "${user.name}@${host.name}"; }; 136 139 options.meta = lib.mkOption { 137 140 type = lib.types.submodule ({ ... }: { 138 141 options = {