XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFESystem

【Rust】XFE系统,基于Rust和汇编

公开
关注 0 Fork 0 Star 0
UTF-8
using System.Diagnostics;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using XFESystem.Browser;
using XFESystem.Desktop;
using XFESystem.Documents;

// Same production engine, sources and private real-font canvas before/after.
// Synthetic CSS is explicitly a host CPU workload, never a network speed claim.
internal static class LoadingProfile
{
    public static void Run(string root, string label)
    {
        string output = Path.Combine(root, "build/BrowserLoadSpeed", label + "-" + DateTimeOffset.UtcNow.ToUnixTimeMilliseconds());
        Directory.CreateDirectory(output);
        var hashes = Directory.EnumerateFiles(Path.Combine(root, "Source/XFESystem.Browser"), "*.cs")
            .ToDictionary(path => Path.GetRelativePath(root, path).Replace('\\', '/'), Hash);
        var cases = new List<object>(); bool allPassed = true;
        string css = string.Concat(Enumerable.Range(0, 1800).Select(i => $".scope p.item{i}{{color:#{i % 0xffffff:x6}}}"));
        string fixture = "<!doctype html><style>body{margin:0}p{margin:0}" + css + "</style><main class=scope>" +
            string.Concat(Enumerable.Range(0, 100).Select(i => $"<p id=p{i} class=item{i * 17}>Row {i}</p>")) + "</main>";
        foreach (string kind in new[] { "IndexedCss", "PlainMarkdown", "WebsiteParity", "Monaco" })
        for (int attempt = 1; attempt <= 3; attempt++)
        {
            var trace = new List<object>();
            var timer = Stopwatch.StartNew();
            var page = new BrowserService(new FixtureTransport(fixture)) { Trace = line => trace.Add(new { Ticks = timer.ElapsedTicks, Line = line.TrimEnd() }) };
            using var canvas = new WindowsTextCanvas(Path.Combine(root, "assets/fonts/cascadia-mono-2407.24/CascadiaMono-Regular.ttf"), 796, 404);
            page.SetCanvas(canvas); page.ResizeViewport(796, 404);
            timer.Restart();
            if (kind == "Monaco") page.NavigateEditor("using System;\nnamespace XFE;\npublic class Test { int value = 42; }", "Test.cs");
            else if (kind == "IndexedCss") page.Navigate("https://fixture.test/");
            else page.BeginDocumentPreview(kind == "PlainMarkdown" ? "# Preview\n\nHello **XFEstudio**.\n\nSimple document without code or math." : WebsiteAssets.ReadText("Fixtures/WebsiteParity.md"), "Test.md");
            double navigation = timer.Elapsed.TotalMilliseconds;
            page.Paint(canvas, new(0, 0, 796, 404), 0); page.FramePresented();
            double firstPaint = timer.Elapsed.TotalMilliseconds;
            for (int pump = 1; pump <= 128; pump++)
            {
                page.AdvanceTime(pump * 20);
                if (!page.DocumentEnhancementsPending && pump >= 8) break;
            }
            double ready = timer.Elapsed.TotalMilliseconds;
            timer.Restart();
            var layout = page.Layout(new(796, 404));
            double layoutMs = timer.Elapsed.TotalMilliseconds;
            var engine = (BrowserLayoutEngine)typeof(BrowserService).GetField("layoutEngine", BindingFlags.NonPublic | BindingFlags.Instance)!.GetValue(page)!;
            string signature = JsonSerializer.Serialize(new
            {
                Commands = layout.Commands.Select(c => new { c.Kind, c.Bounds, c.Color, c.Text, c.Font, c.Opacity, c.Decoration, c.RoundedClip, c.ViewportPinned }),
                Boxes = layout.Boxes.Select(b => new { b.BorderBox, Properties = b.Style.Properties.OrderBy(p => p.Key, StringComparer.Ordinal) })
            });
            // Reflection lets the same probe also measure the frozen dev.3
            // engine, which predates the public selector-work diagnostic.
            object cascade = typeof(BrowserLayoutEngine).GetField("cascade", BindingFlags.NonPublic | BindingFlags.Instance)!.GetValue(engine)!;
            int selectorEvaluations = (int)cascade.GetType().GetField("comparisons", BindingFlags.NonPublic | BindingFlags.Instance)!.GetValue(cascade)!;
            bool passed = page.Document is not null && !page.DocumentEnhancementsPending &&
                (kind != "Monaco" || page.ReadEditorText() == "using System;\nnamespace XFE;\npublic class Test { int value = 42; }");
            allPassed &= passed;
            var row = new { Kind = kind, Attempt = attempt, Passed = passed, NavigationMilliseconds = navigation, FirstPaintMilliseconds = firstPaint,
                ReadyMilliseconds = ready, LayoutMilliseconds = layoutMs, CssSelectorEvaluations = selectorEvaluations, page.LayoutPassCount,
                page.PackagedScriptCacheHits, page.PackagedScriptPreparations, Commands = layout.Commands.Count,
                RenderSha256 = Convert.ToHexStringLower(SHA256.HashData(Encoding.UTF8.GetBytes(signature))),
                PageText = page.CurrentPage.Text, Trace = trace };
            cases.Add(row);
            Console.WriteLine(JsonSerializer.Serialize(new { kind, attempt, passed, navigation, firstPaint, ready, layoutMs, CssSelectorEvaluations = selectorEvaluations, row.RenderSha256 }));
            page.Release();
        }
        bool unchanged = hashes.All(p => Hash(Path.Combine(root, p.Key)) == p.Value);
        var result = new { Kind = "ProductionBrowserLoadingHostProfile", Passed = unchanged && allPassed, HostOnly = true, NativeAcceptance = false,
            Frequency = Stopwatch.Frequency, Sources = hashes, Cases = cases };
        string path = Path.Combine(output, "Result.json");
        File.WriteAllText(path, JsonSerializer.Serialize(result, new JsonSerializerOptions { WriteIndented = true }));
        Console.WriteLine(path);
        if (!unchanged) throw new IOException("Production sources changed during the loading profile.");
    }
    private static string Hash(string path) => Convert.ToHexStringLower(SHA256.HashData(File.ReadAllBytes(path)));
    private sealed class FixtureTransport(string html) : IWebTransport
    {
        public WebResponse Get(Uri uri, BrowserLimits limits) => new(uri, 200, "text/html", html, true);
    }
}