summary refs log tree commit diff
diff options
context:
space:
mode:
authorRory& <root@rory.gay>2026-08-14 13:26:59 +0200
committerRory& <root@rory.gay>2026-08-14 13:26:59 +0200
commit062b0d295675e5bf5129ea4a4a8f16ca4681e3dc (patch)
tree2529087a4be9c5e4fea66031092fc23444fadab5
parentDocument all public members of Rhea.Nar, some micro-optimisations (diff)
downloadRhea-062b0d295675e5bf5129ea4a4a8f16ca4681e3dc.tar.xz
Move validator to separate project
-rw-r--r--Rhea.Nar.Validator/Program.cs114
-rw-r--r--Rhea.Nar.Validator/Rhea.Nar.Validator.csproj20
-rw-r--r--Rhea.Nar/NarWriter.cs20
-rw-r--r--Rhea.slnx1
-rw-r--r--Rhea/Program.cs109
5 files changed, 153 insertions, 111 deletions
diff --git a/Rhea.Nar.Validator/Program.cs b/Rhea.Nar.Validator/Program.cs
new file mode 100644

index 0000000..14f9c22 --- /dev/null +++ b/Rhea.Nar.Validator/Program.cs
@@ -0,0 +1,114 @@ +using System.Diagnostics; +using ArcaneLibs; +using ArcaneLibs.Extensions; +using Rhea.Nar; + +// A simple app to compare output between cppnix/Lix and the NAR serializer +int maxVerifySize = 1024 * 1024 * 1024; + +// return; +// while (true) +// foreach (var srcPath in (string[])[ +// "/etc/nix/nix.conf", +// FileUtils.GetBinDir() + "/Rhea.runtimeconfig.json", +// "/etc/nix", +// ".", +// "/nix/store/06d2xkrl3h1pbyg3m1whz1mvhafqgsqq-source", +// "/nix/store/0l93s9x3z2s9p4r58jls0xiyk64hwkxz-source", +// "/nix/store/2g4sa9xcir93nckzib9iq1ky6ly6azgw-7j1q60m17gf95k3s0gk2qvjqygnp1q36-source" +// ]) +// foreach (var srcPath in (string[])["/nix/store/7j1q60m17gf95k3s0gk2qvjqygnp1q36-source"]) +Parallel.ForEach(FileUtils.EnumerateDirectory("/nix/store") + .Where(x => x is DirectoryInfo) + .Select(x => x.FullName), + new() { MaxDegreeOfParallelism = 64 }, + srcPath => + // foreach (var srcPath in FileUtils.EnumerateDirectory("/nix/store").Select(x=>x.FullName)) + { + var sw = Stopwatch.StartNew(); + TimeSpan oldTime, newTime; + var log = ""; + log += ($"\n - {srcPath}:"); + bool tooLarge = false; + // Console.WriteLine($"Original {srcPath}:"); + + var origBuf = new List<byte>(); + var nixProcess = Process.Start(new ProcessStartInfo("nix", ["nar", "dump-path", srcPath]) + { + RedirectStandardOutput = true + }); + int b; + byte[] oldBuf = new byte[16384]; + while ((b = nixProcess.StandardOutput.BaseStream.Read(oldBuf)) != 0) + { + if (!tooLarge) + { + if (origBuf.Count < maxVerifySize) + origBuf.AddRange(oldBuf[..b]); + else tooLarge = true; + } + // Console.WriteLine(b + " @ " + sw.Elapsed + " -> " + Util.BytesToString(origBuf.Count)); + // Thread.Sleep(1); + } + + // origBuf.ToArray().HexDump(64); + oldTime = sw.GetElapsedAndRestart(); + + // Console.WriteLine($"\nNew {srcPath}:"); + List<byte> tbuf = []; + // List<byte> buf = []; + foreach (var chunk in new NarWriter().GetNarStreamContents(srcPath)) + { + // Console.WriteLine($"ret Chunk({chunk.Length})"); + if (!tooLarge) + { + if (tbuf.Count < maxVerifySize) + tbuf.AddRange(chunk); + else tooLarge = true; + } + // buf.AddRange(chunk); + // while (buf.Count > 64) + // { + // byte[] data = buf[..64].ToArray(); + // buf = buf[64..]; + // data.HexDump(64); + // } + } + + // buf.ToArray().HexDump(64); + newTime = sw.GetElapsedAndRestart(); + + log += ($"\nOld time: {oldTime}, new time: {newTime}"); + if (!tooLarge) + { + log += ("\nIs equal: " + origBuf.SequenceEqual(tbuf)); + if (!origBuf.SequenceEqual(tbuf)) + { + // File.WriteAllBytes("a", origBuf.ToArray().AsHexString().AsBytes().ToArray()); + // File.WriteAllBytes("b", tbuf.ToArray().AsHexString().AsBytes().ToArray()); + var origStdout = Console.Out; + using (var fs = File.OpenWrite("a")) + { + using var fsw = new StreamWriter(fs); + Console.SetOut(fsw); + origBuf.HexDump(width: 16, colorize: false); + Console.SetOut(origStdout); + } + + using (var fs = File.OpenWrite("b")) + { + using var fsw = new StreamWriter(fs); + Console.SetOut(fsw); + tbuf.HexDump(width: 16, colorize: false); + Console.SetOut(origStdout); + } + + Console.WriteLine(log); + Environment.Exit(0); + } + } + else log += "\nToo large to check consistency"; + + Console.WriteLine(log); + } +); \ No newline at end of file diff --git a/Rhea.Nar.Validator/Rhea.Nar.Validator.csproj b/Rhea.Nar.Validator/Rhea.Nar.Validator.csproj new file mode 100644
index 0000000..d63bef5 --- /dev/null +++ b/Rhea.Nar.Validator/Rhea.Nar.Validator.csproj
@@ -0,0 +1,20 @@ +<Project Sdk="Microsoft.NET.Sdk"> + + <PropertyGroup> + <OutputType>Exe</OutputType> + <TargetFramework>net10.0</TargetFramework> + <ImplicitUsings>enable</ImplicitUsings> + <Nullable>enable</Nullable> + <PublishAot>true</PublishAot> + <InvariantGlobalization>true</InvariantGlobalization> + </PropertyGroup> + + <ItemGroup> + <PackageReference Include="ArcaneLibs" Version="1.0.1-preview.20260812-173005" /> + </ItemGroup> + + <ItemGroup> + <ProjectReference Include="..\Rhea.Nar\Rhea.Nar.csproj" /> + </ItemGroup> + +</Project> diff --git a/Rhea.Nar/NarWriter.cs b/Rhea.Nar/NarWriter.cs
index 0ca2e85..52bbb0e 100644 --- a/Rhea.Nar/NarWriter.cs +++ b/Rhea.Nar/NarWriter.cs
@@ -31,6 +31,22 @@ public class NarWriter foreach (var chunk in GetNarSymlinkContents(fe)) yield return chunk; } + + private IEnumerable<byte[]> GetNarStreamContentsInner(FileSystemInfo fsi) + { + if (string.IsNullOrWhiteSpace(fsi.LinkTarget)) + { + if (fsi is DirectoryInfo di) + foreach (var chunk in GetNarDirectoryContents(di)) + yield return chunk; + else + foreach (var chunk in GetNarFileContents(fsi as FileInfo ?? throw new Exception(fsi.GetType().Name +" != FileInfo"))) + yield return chunk; + } + else + foreach (var chunk in GetNarSymlinkContents(fsi)) + yield return chunk; + } private IEnumerable<byte[]> GetNarDirectoryContents(DirectoryInfo de) { @@ -43,7 +59,7 @@ public class NarWriter yield return GetLengthPrefixedPadded(fe.Name.AsBytes().ToArray()); yield return NarConsts.Node; - foreach (var chunk in GetNarStreamContentsInner(fe.FullName)) + foreach (var chunk in GetNarStreamContentsInner(fe)) yield return chunk; yield return NarConsts.RightParen; @@ -52,7 +68,7 @@ public class NarWriter yield return NarConsts.RightParen; } - private IEnumerable<byte[]> GetNarSymlinkContents(FileInfo fe) + private IEnumerable<byte[]> GetNarSymlinkContents(FileSystemInfo fe) { // yield return NarConsts.LeftParen; // diff --git a/Rhea.slnx b/Rhea.slnx
index 8a1246f..ac81b67 100644 --- a/Rhea.slnx +++ b/Rhea.slnx
@@ -1,4 +1,5 @@ <Solution> + <Project Path="Rhea.Nar.Validator/Rhea.Nar.Validator.csproj" /> <Project Path="Rhea.Nar/Rhea.Nar.csproj" /> <Project Path="Rhea/Rhea.csproj" /> </Solution> diff --git a/Rhea/Program.cs b/Rhea/Program.cs
index 78fa787..3d12b02 100644 --- a/Rhea/Program.cs +++ b/Rhea/Program.cs
@@ -26,115 +26,6 @@ foreach (var fieldInfo in typeof(NarConsts).GetFields()) ); } -int maxVerifySize = 8_192_000; - -// return; -// while (true) -// foreach (var srcPath in (string[])[ -// "/etc/nix/nix.conf", -// FileUtils.GetBinDir() + "/Rhea.runtimeconfig.json", -// "/etc/nix", -// ".", -// "/nix/store/06d2xkrl3h1pbyg3m1whz1mvhafqgsqq-source", -// "/nix/store/0l93s9x3z2s9p4r58jls0xiyk64hwkxz-source", -// "/nix/store/2g4sa9xcir93nckzib9iq1ky6ly6azgw-7j1q60m17gf95k3s0gk2qvjqygnp1q36-source" -// ]) -// foreach (var srcPath in (string[])["/nix/store/7j1q60m17gf95k3s0gk2qvjqygnp1q36-source"]) -Parallel.ForEach(FileUtils.EnumerateDirectory("/nix/store") - // .Where(x => x is not DirectoryInfo) - .Select(x => x.FullName), - new() { MaxDegreeOfParallelism = 32 }, - srcPath => - // foreach (var srcPath in FileUtils.EnumerateDirectory("/nix/store").Select(x=>x.FullName)) - { - var sw = Stopwatch.StartNew(); - TimeSpan oldTime, newTime; - var log = ""; - log += ($"\n - {srcPath}:"); - bool tooLarge = false; - // Console.WriteLine($"Original {srcPath}:"); - - var origBuf = new List<byte>(); - var nixProcess = Process.Start(new ProcessStartInfo("nix", ["nar", "dump-path", srcPath]) - { - RedirectStandardOutput = true - }); - int b; - byte[] oldBuf = new byte[16384]; - while ((b = nixProcess.StandardOutput.BaseStream.Read(oldBuf)) != 0) - { - if (!tooLarge) - { - if (origBuf.Count < maxVerifySize) - origBuf.AddRange(oldBuf[..b]); - else tooLarge = true; - } - // Console.WriteLine(b + " @ " + sw.Elapsed + " -> " + Util.BytesToString(origBuf.Count)); - // Thread.Sleep(1); - } - - // origBuf.ToArray().HexDump(64); - oldTime = sw.GetElapsedAndRestart(); - - // Console.WriteLine($"\nNew {srcPath}:"); - List<byte> tbuf = []; - // List<byte> buf = []; - foreach (var chunk in new NarWriter().GetNarStreamContents(srcPath)) - { - // Console.WriteLine($"ret Chunk({chunk.Length})"); - if (!tooLarge) - { - if (tbuf.Count < maxVerifySize) - tbuf.AddRange(chunk); - else tooLarge = true; - } - // buf.AddRange(chunk); - // while (buf.Count > 64) - // { - // byte[] data = buf[..64].ToArray(); - // buf = buf[64..]; - // data.HexDump(64); - // } - } - - // buf.ToArray().HexDump(64); - newTime = sw.GetElapsedAndRestart(); - - log += ($"\nOld time: {oldTime}, new time: {newTime}"); - if (!tooLarge) - { - log += ("\nIs equal: " + origBuf.SequenceEqual(tbuf)); - if (!origBuf.SequenceEqual(tbuf)) - { - // File.WriteAllBytes("a", origBuf.ToArray().AsHexString().AsBytes().ToArray()); - // File.WriteAllBytes("b", tbuf.ToArray().AsHexString().AsBytes().ToArray()); - var origStdout = Console.Out; - using (var fs = File.OpenWrite("a")) - { - using var fsw = new StreamWriter(fs); - Console.SetOut(fsw); - origBuf.HexDump(width: 16, colorize: false); - Console.SetOut(origStdout); - } - - using (var fs = File.OpenWrite("b")) - { - using var fsw = new StreamWriter(fs); - Console.SetOut(fsw); - tbuf.HexDump(width: 16, colorize: false); - Console.SetOut(origStdout); - } - - Console.WriteLine(log); - Environment.Exit(0); - } - } - else log += "\nToo large to check consistency"; - - Console.WriteLine(log); - } -); - return; var builder = WebApplication.CreateBuilder(args);