管道把所有行跑完之后,最后还得把结果以某种形式“交出去”。
一个查询的入口长这样Copyinternal static class QueryProgramTRow, TPipeline, TRuntimeResult, TPublicResultwhere TPipeline : IQueryNodeTRow, TRuntimeResult, TRow{public static IReadOnlyList Execute(ReadOnlySpan rows){var runtime new QueryRuntime(rows.Length);TPipeline.Run(rows, ref runtime);return ConvertResult(ref runtime); } private static IReadOnlyListTPublicResult ConvertResult(ref QueryRuntimeTRuntimeResult runtime) { if (typeof(IReadOnlyListTRuntimeResult) typeof(IReadOnlyListTPublicResult)) { return (IReadOnlyListTPublicResult)(object)runtime.Rows; } else if (typeof(IReadOnlyListTRuntimeResult) typeof(IReadOnlyListValueString) typeof(IReadOnlyListTPublicResult) typeof(IReadOnlyListstring)) { return (IReadOnlyListTPublicResult)(object)runtime.AsStringRows(); } else if (RuntimeFeature.IsDynamicCodeSupported typeof(TRuntimeResult).IsGenericType typeof(TPublicResult).IsGenericType) { return runtime.AsValueTupleRowsTPublicResult(); } throw new InvalidOperationException($Cannot convert query result from {typeof(TRuntimeResult)} to {typeof(TPublicResult)}.); }}可以看到主要有三种情况运行时结果类型和公共结果类型一模一样→ 直接把 Rows 返回就行。运行时内部用的是 ValueString外面希望看到 string→ 调用 AsStringRows它会把内部的 ValueString[] 包装一下对外返回 string?靠隐式转换。两边都是某种 ValueTuple 形状→ 用 AsValueTupleRows()底层交给 ValueTupleConvertHelper 去做拷贝和字段转换。ValueTupleConvertHelper用动态 IL 在元组之间搬运字段#ValueTupleConvertHelperTPublicResult, TRuntimeResult 的职责是在两个兼容形状的 ValueTuple 之间搬运字段识别并处理 string ↔ ValueString 的转换如果 ValueTuple 有 Rest嵌套元组要递归下去做同样的事情。它在类型初始化时会生成一个 DynamicMethod 来做拷贝Copyinternal static class ValueTupleConvertHelperTPublicResult, TRuntimeResult{private delegate void CopyDelegate(ref TPublicResult dest, ref readonly TRuntimeResult source);private static readonly CopyDelegate _helper default!; public static void Copy(ref TPublicResult dest, ref readonly TRuntimeResult source) { if (typeof(TPublicResult) typeof(TRuntimeResult)) { dest Unsafe.AsTRuntimeResult, TPublicResult(ref Unsafe.AsRef(in source)); } else { _helper.Invoke(ref dest, in source); } } static ValueTupleConvertHelper() { // 构造 DynamicMethod 和 IL按字段复制 // 若发现 string - ValueString就做对应转换 // 遇到 Rest 字段时递归。 }}这样运行时内部可以用一个对自己更舒服的元组类型比如 (ValueString, int, ValueString, …)而外面看到的则是 (string, int, string, …)两者之间通过这一层帮助类桥接成本也很低。这使得查询过程可以最大化利用值类型的泛型特化优势同时对外还不需要暴露这些内部细节达到了性能和易用性的平衡。不过需要注意的是这一块用到了动态代码生成所以在一些受限环境比如 AOT下可能无法使用因此 TypedSql 会在编译阶段检查这一点确保只有在支持动态代码的环境下才允许使用这种元组转换。否则的话就只能退回到直接让运行时结果类型和公共结果类型一致的方式。整体流程编译并执行查询#站在使用者的角度入口一般会是这样的Copyvar compiled QueryEngine.CompilePerson, string(“SELECT Name FROM $ WHERE City ! ‘Seattle’”);CompileTRow, TResult 在内部会做这么几件事解析 SQL生成 ParsedQuery把 SQL 编译成管道类型 TPipelineTRuntimeResultTPublicResult检查 TPublicResult 是否和你指定的 TResult 一致构造 QueryProgramTRow, TPipeline, TRuntimeResult, TPublicResult 这个类型找到它的静态方法 Execute(ReadOnlySpan)把它变成一个委托塞进 CompiledQueryTRow, TResult。CompiledQueryTRow, TResult 本身只是包了一个委托Copyprivate readonly FuncReadOnlySpan, IReadOnlyList _entryPoint executeMethod.CreateDelegateFuncReadOnlySpan, IReadOnlyList();然后对外暴露Copypublic IReadOnlyList Execute(ReadOnlySpan rows) _entryPoint(rows);得益于 .NET 10 对委托的逃逸分析、去虚拟化和内联等优化这一层委托调用可以说几乎没有任何开销。在 JIT 看来一旦 Compile 做完这些准备工作以后每次 Execute 就只是一次直接的静态调用调入一个所有类型参数已经封死的泛型方法这个方法里面再调用一串全是 struct 和静态方法组成的管道。最终编译出来的类型你既可以直接拿去执行也可以把它输出到代码里然后通过 NativeAOT 编译成原生二进制文件一套代码同时支持 JIT 和 AOT使用和性能测试#快速上手#和很多轻量级查询库类似TypedSql 的打开方法是定义你的行类型例如Copypublic sealed record Person(int Id,string Name,int Age,string City,float Salary,string Department,bool IsManager,int YearsAtCompany,string Country,string? Team,string Level);为每一列实现一个 IColumnPerson, TValue把这些列注册到 Person 对应的 schema 里然后就可以编译并运行查询例如Copy// 编译一次var wellPaidManagers QueryEngine.CompilePerson, Person(“”SELECT * FROM $WHERE Department ‘Engineering’AND IsManager trueAND YearsAtCompany 5AND Salary 170000AND Country ‘US’“”);// 针对不同数据集多次执行var result wellPaidManagers.Execute(allPeople.AsSpan());要是你只需要一部分列也可以返回元组Copyvar seniorTitles QueryEngine.CompilePerson, (string Name, string City, string Level)(“”SELECT Name, City, Level FROM $WHERE Level ‘Senior’ AND City ‘Seattle’“”);foreach (var (name, city, level) in seniorTitles.Execute(allPeople.AsSpan())){Console.WriteLine($“{name} in {city} [{level}]”);}所有重活——解析 SQL、字面量编码、在类型系统里搭管道——都发生在编译查询这一步。之后每次 .Execute都只是跑一遍已经专门化好的静态管道没有任何的运行时分发没有任何的虚拟调用不存在任何的反射和装箱完全是 JIT 能看懂的强类型、零分配代码从而实现极高的性能。简单性能对比#TypedSql 的目标并不是炫技用类型而是想试试看在保持 SQL 风格外壳的情况下我们能让生成的代码离一个手写循环有多近。一个非常简单的 benchmark 就是拿三个方案做对比一条 TypedSql 查询一条等价的 LINQ 查询一段手写的 foreach 循环。任务内容过滤出 City “Seattle” 的行返回它们的 Id。TypedSql 编译出来的类型大概是这样CopyQueryProgramPerson,WhereSelectPerson,EqualsFilterPerson,ValueStringColumnPersonCityColumn, Person,‘Seattle’,ValueString,ColumnProjectionPersonIdColumn, Person, Int32,StopInt32, Person,Int32,Int32,Person,Int32,Int32让我们来看看 RyuJIT 为我们的查询方案生成了什么样的机器码CopyG_M000_IG01: ; prologuepush r15push r14push rdipush rsipush rbppush rbxsub rsp, 40mov rbx, rcxG_M000_IG02: ; 分配结果数组mov esi, dword ptr [rbx0x08]mov edx, esimov rcx, 0x7FFE71F29558call CORINFO_HELP_NEWARR_1_VCmov rdi, raxxor ebp, ebpmov rbx, bword ptr [rbx]test esi, esijle SHORT G_M000_IG06G_M000_IG03: ; 初始化循环变量xor r14d, r14dG_M000_IG04: ; 循环体lea r15, bword ptr [rbxr14]mov rcx, gword ptr [r150x08]mov rdx, 0x16EB0400D30mov rdx, gword ptr [rdx]mov rdx, gword ptr [rdx0x08]cmp rcx, rdxje G_M000_IG12test rcx, rcxje SHORT G_M000_IG05test rdx, rdxje SHORT G_M000_IG05mov r8d, dword ptr [rcx0x08]cmp r8d, dword ptr [rdx0x08]je SHORT G_M000_IG08G_M000_IG05: ; 更新循环计数器add r14, 72dec esijne SHORT G_M000_IG04G_M000_IG06: ; 产生结果对象mov rcx, 0x7FFE72227600call CORINFO_HELP_NEWSFASTmov rbx, raxlea rcx, bword ptr [rbx0x08]mov rdx, rdicall CORINFO_HELP_ASSIGN_REFmov dword ptr [rbx0x10], ebpmov rax, rbxG_M000_IG07: ; epilogueadd rsp, 40pop rbxpop rbppop rsipop rdipop r14pop r15retG_M000_IG08: ; 字符串长度比较lea rax, bword ptr [rcx0x0C]add rdx, 12mov ecx, dword ptr [rcx0x08]add ecx, ecxmov r8d, ecxcmp r8, 10je SHORT G_M000_IG10G_M000_IG09: ; 字符串内容慢速比较mov rcx, raxcall [System.SpanHelpers:SequenceEqual(byref,byref,nuint):bool]jmp SHORT G_M000_IG11G_M000_IG10: ; 字符串内容快速比较mov rcx, qword ptr [rax]mov rax, qword ptr [rax0x02]mov r8, qword ptr [rdx]xor rcx, r8xor rax, qword ptr [rdx0x02]or rcx, raxsete almovzx rax, alG_M000_IG11: ; 处理比较结果test eax, eaxje SHORT G_M000_IG05G_M000_IG12: ; 把匹配的 Id 写入结果数组mov ecx, dword ptr [r150x30]lea rax, bword ptr [rdi0x10]lea edx, [rbp0x01]mov r15d, edxmovsxd rdx, ebpmov dword ptr [rax4*rdx], ecxmov ebp, r15djmp G_M000_IG05注意看 G_M000_IG08 的 r8, 10这里的 10 就是字符串字面量 ‘Seattle’ 的长度JIT 直接把我们的字符串字面量的长度常量嵌进了机器码里进一步当长度匹配时JIT 又生成了代码跳转到 G_M000_IG10这段代码专门处理长度为 10 的字符串的快速比较路径。也就是说JIT 不仅把字面量的值嵌进去了还根据它生成了专门的代码路径再注意看循环计数器的更新部分G_M000_IG05 里的 add r14, 72这里的 72 就是 sizeof(Person)JIT 直接把行类型的大小常量也嵌进去了避免了运行时的计算而 dec esi 更是直接把递增的循环优化成了递减减少了一次比较指令。上述代码的逻辑等价于Copyint length elements.Length;Span values new int[length];int count 0;for (int i length - 1; i 0; i–){var elem elements[i];var city elem.City;if (city null)continue;if (city.Length 10 city Seattle) { values[length - 1 - count] elem.Id; count; }}return values[…count];看到了吗跟你手写的循环几乎一模一样我们的抽象完全被 JIT 优化的一干二净上个跑分结果Method Mean Error StdDev Gen0 Code Size AllocatedTypedSql 10.953 ns 0.0250 ns 0.0195 ns 0.0051 111 B 80 BLinq 27.030 ns 0.1277 ns 0.1067 ns 0.0148 3,943 B 232 BForeach 9.429 ns 0.0417 ns 0.0326 ns 0.0046 407 B 72 B可以看到TypedSql 在时间和分配上无限逼近 foreach远远超过即使是在 .NET 10 中已经被高度优化后的 LINQ 的性能。这也符合我们对它内部结构的预期

相关新闻

计算机毕业设计之众筹网站设计与实现

计算机毕业设计之众筹网站设计与实现

网络的广泛应用给生活带来了十分的便利。所以把众筹网站与现在网络相结合,利用JSP技术建设众筹网站设计与实现,实现用户信息的信息化。则对于进一步提高众筹网站发展,丰富众筹网站经验能起到不少的促进作用。众筹网站设计与实现能够通过互联网…

2026/7/23 10:50:13 阅读更多 →
bq40z60阻抗跟踪电量计IO配置与算法调试实战指南

bq40z60阻抗跟踪电量计IO配置与算法调试实战指南

1. 项目概述与核心价值在锂离子电池驱动的各类设备中,从我们每天不离手的笔记本电脑、智能手机,到专业级的电动工具、无人机,再到大型的储能系统,一个核心的挑战始终存在:如何让设备准确地“知道”自己还剩多少电&…

2026/7/23 10:49:13 阅读更多 →
机器码克隆与修改技术实战指南

机器码克隆与修改技术实战指南

1. 项目背景与核心概念在软件开发和系统管理领域,机器码(Machine Code)作为计算机能直接执行的底层指令集,一直扮演着关键角色。最近我在处理一个跨平台部署项目时,遇到了需要批量修改设备标识的场景,这促使…

2026/7/23 10:49:13 阅读更多 →

最新新闻

Unity编辑器自动化实战:8个高频场景提升开发效率

Unity编辑器自动化实战:8个高频场景提升开发效率

1. 项目概述:为什么我们需要Unity Editor自动化? 如果你是一个Unity开发者,每天花在编辑器里的时间可能比写游戏逻辑本身还要多。我说的不是写代码,而是那些重复、琐碎、但又不得不做的“体力活”:批量重命名几百个资源…

2026/7/23 11:14:23 阅读更多 →
DB-AI:智能数据库助手的核心功能与应用场景

DB-AI:智能数据库助手的核心功能与应用场景

1. 项目概述:DB-AI的定位与核心价值DB-AI作为面向开发者的智能数据库助手,正在重新定义数据库交互方式。这个工具本质上是一个融合了AI能力的数据库工作流增强平台,它解决了开发者日常工作中最棘手的几个问题:跨数据库语法转换、查…

2026/7/23 11:14:23 阅读更多 →
AI Agent如何通过Skill库实现钉钉文档智能操作

AI Agent如何通过Skill库实现钉钉文档智能操作

1. 项目背景与核心价值钉钉作为国内领先的企业协同平台,其文档与表格功能已成为日常办公的重要载体。传统自动化工具对钉钉文档的操作往往停留在简单的API调用层面,而AI Agent技术的引入正在改变这一局面。这个Skill库的本质,是让AI Agent获得…

2026/7/23 11:14:23 阅读更多 →
开源大模型到底“开“到哪了:拆 Llama、DeepSeek、Qwen 三张许可证

开源大模型到底“开“到哪了:拆 Llama、DeepSeek、Qwen 三张许可证

一、开源大模型这三个字,正在悄悄变质 开源大模型这四个字,我最近把它拆开揉碎看了一遍。我把 Llama 4、DeepSeek、Qwen 三家的许可证原文,还有 OSI 官方那份开源 AI 定义,逐字读了一遍。 读之前,我以为"开源&quo…

2026/7/23 11:14:23 阅读更多 →
2026年经典爬虫案例专栏|第20篇:招聘网站爬虫实战——职位信息采集

2026年经典爬虫案例专栏|第20篇:招聘网站爬虫实战——职位信息采集

20.1 招聘网站结构分析 20.1.1 招聘网站概述 招聘网站作为连接求职者与企业的桥梁,在人力资源市场中扮演着至关重要的角色。随着互联网技术的发展,招聘网站已从传统的信息发布平台演变为智能化、数据化的人才匹配系统。在2026年,中国主流的招聘网站包括智联招聘、前程无忧…

2026/7/23 11:14:23 阅读更多 →
Agent Skill 规范、构建与设计模式

Agent Skill 规范、构建与设计模式

Agent Skill 规范、构建与设计模式前言 Skill 不是 Prompt——它是围绕任务、工具、流程和输出边界的结构化行为设计。写好 Skill 的关键在于理解规范标准、掌握构建方法论、选择合适的设计模式。一、Skill 规范标准 1.1 什么是 Agent Skill 在 AI Agent 生态中,Ski…

2026/7/23 11:13:23 阅读更多 →

日新闻

从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表)

从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表)

更多请点击: https://intelliparadigm.com 第一章:从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表) 当AI副业主理人不再仅满足于单次服务交付,而是主动构建可复用、可裂变、可…

2026/7/23 0:00:25 阅读更多 →
AI写作开头钩子设计:为什么你的AI文案完读率不足18%?——基于2,346篇A/B测试报告的归因分析

AI写作开头钩子设计:为什么你的AI文案完读率不足18%?——基于2,346篇A/B测试报告的归因分析

更多请点击: https://codechina.net 第一章:AI写作开头钩子设计:为什么你的AI文案完读率不足18%?——基于2,346篇A/B测试报告的归因分析 在对2,346篇跨行业AI生成文案的A/B测试数据进行聚类分析后,我们发现&#xff1…

2026/7/23 0:01:26 阅读更多 →
Chitchatter完整指南:免费开源的终极点对点安全聊天工具

Chitchatter完整指南:免费开源的终极点对点安全聊天工具

Chitchatter完整指南:免费开源的终极点对点安全聊天工具 【免费下载链接】chitchatter Secure peer-to-peer chat that is serverless, decentralized, and ephemeral 项目地址: https://gitcode.com/gh_mirrors/ch/chitchatter Chitchatter是一款革命性的安…

2026/7/23 0:01:26 阅读更多 →

周新闻

Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/22 8:58:19 阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/22 19:43:43 阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/22 12:54:44 阅读更多 →

月新闻