理解动态语言inline cache优化
首先我们理解Why?
Why
动态语言跟静态语言的一个区别就是类型是动态决定的,也就是在运行时才能知道类型。
这带来什么问题呢?
比如最简单的取值,table.height,静态语言,编译时就能知道offset_heigth,动态语言,编译时不知道offset_heigth,需要运行时获取。
class Thing { Thing(int) {height = 1} void get(); int height; } Thing table = new Thing(1); table.height;
如果是静态语言,取值非常快,因为height的索引在编译时就知道了,因此只需要一个load指令即可。
r0 = #table_ptr; $height = load(r0, #offset_height = 0)
如果时动态语言,取值非常慢,编译时不知道height的索引,需要进入运行时判断height的索引,因此会需要一个call runtime,然后一个map查找索引。
r0 = #table_ptr offset_height = call_runtime(table_ptr, "height") $height = load(r0, #offset_height) void call_runtime(table_ptr, "height") { if (table_ptr has no type of "height") { map, index = new_map("height") table_ptr.map = map; return index; } if (table_ptr has type of "height") { map = table_ptr.map index = map["height"] return index } }
可以看到,差了很多代码。
How
那么怎么改进呢?
引入fast path和slow path。非常经典。
因为第一次我们一定不知道类型,是必须进入runtime的,第一次是改进不了的。
但是第二次就可以。因为我们有了第一次运行,知道了第一次运行的结果,我们可以用这次结果设计为fast path。
这个改进的前提之一就是,动态类型对象的类型不会一直在改变,否则我们就一直进入不了fast path。
所以,假设第二次访问时,类型没有改变,因为我们在第一次存储了类型信息,即,我们知道了offset_height,因此,访问的代码如下:
int get_height() { r0 = #table_ptr; if ( no change of type ) // the same map { // fast path $height = load(r0, #offset_height = 0) // we know the offset_height from pre-run. return $height } else { // slow path return call_runtime_get_height(); } }
在假设类型不是经常变化成立的情况下,那么动态类型语言和静态类型语言在这里的差距就只有一个if语句的差距,而不是整个runtime了。
参考
https://en.wikipedia.org/wiki/Inline_caching
https://mrale.ph/blog/2012/06/03/explaining-js-vms-in-js-inline-caches.html
https://wingolog.org/archives/2018/02/07/design-notes-on-inline-caches-in-guile
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律