Replies: 2 comments
-
这个特性依赖于组合特性,所以要等到组合特性实现之后才能开始 |
Beta Was this translation helpful? Give feedback.
0 replies
-
好吧,虽然组合还没有支持,但是我们支持了非组合的 unsafe 操作 |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
需求分析
大多数时候,我们并不会考虑使用 unsafe 来直接操作对象。因为正如
unsafe
这个名字所揭示的那样,unsafe
非常危险。unsafe
完全依赖于开发者对对象在内存中布局的理解,所以从代码看上去完全看不出来每一个unsafe
操作的目标。相比之下,虽然反射也同样晦涩难明,但是至少反射依旧保留了类型、值、字段之类的信息。使用
unsafe
不仅难懂,还极难维护。每次遇到 BUG 的时候都要仔细琢磨每一个unsafe
执行的效果。很多时候这还需要手动画出内存布局,手动计算字段偏移量才能理解unsafe
操作。但是
unsafe
操作虽然有非常多的缺点,但是无可否认的就是unsafe
非常的高效。和反射比起来,它的性能要好上至少一个数量级。这主要是因为unsafe
能够极大减少 CPU 和内存分配的开支,因此 GC 的压力也会变小。场景分析
unsafe
操作对象,无非就是读写对象字段。组合场景
同时因为我们计划支持组合,所以
unsafe
也要考虑到组合的效果。在组合设计文档里面我们列举了必须要考虑的组合情况:
同样地,
unsafe
在操作对象的时候也要考虑这些情况。好在于,组合设计文档里面明显提出来不支持指针类型组合,因为在读写字段的时候基本上不需要考虑组合的结构体是 nil 的情况。
类型场景
和反射比起来,
unsafe
会操作会更加琐碎。问题的关键就在于,unsafe
本身不具备任何信息,所以一般unsafe
都要结合反射的类型信息进行使用。反射的类型信息主要用于辅助unsafe
在读写字段的时候编解码。因此要充分考虑不同类型带来的影响,这些类型已经罗列在支持类型中
功能需求
可以默认组合不会有指针类型的组合,
eorm
的其它模块会确保这一点。unsafe
来读写字段unsafe
来读写组合内部字段unsafe
来读写支持类型中的所有类型非功能需求
设计
unsafe
操作主要影响两个地方。首先是在元数据解析那里,要计算字段的偏移量。这个偏移量是指针对最外面的一层的偏移量,例如:除此以外,另外一个要修改的地方就是
value
包,以及对不同类型的编解码。详细设计
元数据解析
类似地,我们在列元数据里面加一个字段
offset
,代表偏移量:Offset 的计算规则比较简单,例如:
那么
Field2
的偏移量为:offset = offset(B->A) + offset(C->B) + offset(Field2->C)即
Field2
的偏移量为 B 相对于 A 的偏移量,C 相对于 B 的偏移量,Field2
相对于 C 的偏移量三者之和。只需要在已有的逻辑基础上稍微做修改就可以。
Value
Value
的实现也是很简单。在已经计算出来偏移量的情况下,基本上就是直接读取:正如我们前面所说,
unsafe
本身没有任何类型信息,所以我们需要利用反射的Type
,并且结合switch-case
来处理不同类型。其次还要考虑:byte
,其它的都是非法的driver.Valuer
接口和sql.Scanner
接口,那么它们的处理会更加棘手测试
单元测试
单元测试要覆盖功能需求里面的场景:
同时要考虑这些场景混合在一起:
集成测试
N/A。
基准测试
提供
unsafe
在不同组合形态下的基准测试不同类型主要影响的是编解码过程,所以要对编解码进行基准测试。
模糊测试
unsafe
进行模糊测试Beta Was this translation helpful? Give feedback.
All reactions