泛型#
Generics in General#
一般范型有三种实现方案:
- 泛型实例化:
Rust、C++采用这种方案。是一种静态派发,性能是最好的。存在的问题是实现难度很大,需要进行语法树的深拷贝和指针的重定向,很容易出现段错误。另外在跨包的时候相同的类型会出现相同代码生成的问题。这些问题都是可以解决的,只是需要时间。
- 字典:
Swift 采用这种方案。这种方案实现起来最大的好处就是不容易出错。但是性能会差一点,因为泛型变量必须分配到堆上,而且要生成很多字典数据,从产物上来说不一定比第一种少多少。
- 类型擦除:
Java 采用这种方案。将泛型出现的地方都用 Object 代替。这种最简单,但是不支持基础类型
int
、bool
等。Java 对于这些类型如果想要调用方法需要进行装箱—— from
ganbo.xiao
Go's Implementation#
GC Shape Stenciling = Stenciling + Dictionaries
- Stenciling
在编译期,据使用的类型为泛型函数生成多份代码
运行速度快,编译速度慢,产物臃肿
- Dictionaries
一个泛型函数只生成一份代码
在运行时传递一个包含类型参数信息的字典
编译速度快,运行速度慢,产物精简
- GC Shape of Type
类型的 GC 相关信息
和类型的大小 (size) 、内存对齐 (alignment) 以及指针成员的位置相关
- GC Shape Stenciling ⇒ 根据 GC Shape 生成模版
在编译期,根据不同的 GC Shape 生成多份代码(即,具有相同 GC Shape 的类型共享一份代码)
在编译期,为「相同 GC Shape 的不同类型」生成多个字典
在运行期,通过传递不同的字典处理「GC Shape 相同的不同类型」的差异
在编译速度和运行速度之间取得了平衡
评论
如果你有任何意见,请在此评论。 如果你留下了电子邮箱,我可能会通过 回复你。