golang 接口动态派发性能问题
测试代码
package main
type Duck interface {
Quack()
}
type Cat struct {
Name string
}
//go:noinline
func (c Cat) Quack() {
println(c.Name + " meow")
}
func main() {
var c Duck = Cat{Name: "draven"}
c.Quack()
}
指针类型测试用例
func BenchmarkDirectCall(b *testing.B) {
c := &Cat{Name: "draven"}
for n := 0; n < b.N; n++ {
// MOVQ AX, "".c+24(SP)
// MOVQ AX, (SP)
// CALL "".(*Cat).Quack(SB)
c.Quack()
}
}
func BenchmarkDynamicDispatch(b *testing.B) {
c := Duck(&Cat{Name: "draven"})
for n := 0; n < b.N; n++ {
// MOVQ "".d+56(SP), AX
// MOVQ 24(AX), AX
// MOVQ "".d+64(SP), CX
// MOVQ CX, (SP)
// CALL AX
c.Quack()
}
}
结构体类型测试用例
func BenchmarkDirectCall(b *testing.B) {
c := Cat{Name: "draven"}
for n := 0; n < b.N; n++ {
// MOVQ AX, (SP)
// MOVQ $6, 8(SP)
// CALL "".Cat.Quack(SB)
c.Quack()
}
}
func BenchmarkDynamicDispatch(b *testing.B) {
c := Duck(Cat{Name: "draven"})
for n := 0; n < b.N; n++ {
// MOVQ 16(SP), AX
// MOVQ 24(SP), CX
// MOVQ AX, "".d+32(SP)
// MOVQ CX, "".d+40(SP)
// MOVQ "".d+32(SP), AX
// MOVQ 24(AX), AX
// MOVQ "".d+40(SP), CX
// MOVQ CX, (SP)
// CALL AX
c.Quack()
}
}
可以很明显得到如下性能对比图
| 直接调用 | 动态派发 | |
|---|---|---|
| 指针 | ~3.03ns | ~3.58ns |
| 结构体 | ~3.09ns | ~6.98ns |
可以很明显看到使用结构体会带来巨大的性能差异。
在实际项目中如果对这方面有很大的性能需求可以去优化一下。
参考:https://draveness.me/golang/docs/part2-foundation/ch04-basic/golang-interface/#基准测试
golang 接口动态派发性能问题的更多相关文章
- 【Golang 接口自动化06】微信支付md5签名计算及其优化
前言 可能看过我博客的朋友知道我主要是做的支付这一块的测试工作.而我们都知道现在比较流行的支付方式就是微信支付和支付宝支付,当然最近在使用低手续费大力推广的京东金融(已改名为京东数科)以后也可能站到第 ...
- Golang 接口与反射知识要点
目录 Golang 接口与反射知识要点 1. 接口类型变量 2. 类型断言 3. 鸭子类型 4. 反射机制 5. reflect 包 TypeOf().ValueOf() Type().Kind() ...
- Golang 接口
1 接口是什么 Golang中没有像Python.Java拥有类和对象的概念,其封装对象或说明对象是通过接口来实现的.比如谁能够实现什么样的功能,便能够将其抽象化封装. 接口定义了一组方法(抽象方法集 ...
- swift protocol 见证容器 虚函数表 与 动态派发
一.测试代码: //protocol DiceGameDelegate: AnyObject { //} // //@objc protocol OcProtocol{ // @objc fun ...
- swift class的动态派发
一.测试代码 class BaseCallClass{ func NormalCall(){} @objc func OcCall(){} @objc dynamic func OcDynamicCa ...
- Swift 静态派发和动态派发
前言 方法是 Swift 中的一个重要概念,方法允许你把需要复用的代码封装进方法中,这样当你调用方法时,实际上你的想法是执行方法中的那些代码,方法的出现极大的提高了方法的复用性. Swift 工程的环 ...
- swift static与class修饰符:static不参与动态派发
static与class 都有类型成员的含义:相对于实例成员: static的另一个意思是静态派发:所以不能被继承. 要使用动态派发和继承的机制必须使用class继承. static的其它常见含义: ...
- 【Golang 接口自动化00】为什么要用Golang做自动化?
为什么使用Golang做自动化 顺应公司的趋势学习了Golang之后,因为没有开发那么多的时间和项目来实践,怕步此前学习Java缺少练习遗忘殆尽的后尘,决定利用工作之余的时间把此前用Python的写的 ...
- Mybatis学习系列(四)Mapper接口动态代理
实现原理及规范 Mapper接口动态代理的方式需要手动编写Mapper接口,Mybatis框架将根据接口定义创建接口的动态代理对象,代理对象的方法体实现Mapper接口中定义的方法. 使用Mapper ...
- swift派发机制的核心是确定一个函数能否进入动态派发列表
swift派发机制的核心是确定一个函数能否进入动态派发列表
随机推荐
- Linux(CentOS7.2)安装cnpm
1.安装cnpm npm install -g cnpm --registry=https://registry.npm.taobao.org 2.如下安装成功 /root/node-v10.16.3 ...
- RestfulApi 学习笔记——查询与过滤还有搜索(五)
前言 过滤和查询感觉是一个样子,实际上是不同含义.查询是查询一个主体,如果说要查询全部男职工但是名字中带良的,全部男职工 就是主体要查询的对象,然后名字中带良的表示的是过滤. 那么什么是搜索呢?搜索是 ...
- 剑指 Offer II 018(Java). 有效的回文(简单)
题目: 给定一个字符串 s ,验证 s 是否是 回文串 ,只考虑字母和数字字符,可以忽略字母的大小写. 本题中,将空字符串定义为有效的 回文串 . 示例 1: 输入: s = "A man, ...
- 云原生DevOps的5步升级路径
简介: 究竟什么是云原生DevOps呢?我们认为:云原生DevOps是充分利用云原生基础设施,基于微服务/无服务架构体系和开源标准,语言和框架无关,具备持续交付和智能自运维能力,从而做到比传统DevO ...
- Git 版本控制:构建高效协作和开发流程的最佳实践
引言 版本控制是开发中不可或缺的一部分,他允许多人同时协作,通过记录每一次代码的变更,帮助开发者理解何时.为什么以及谁做了修改.这不仅有助于错误追踪和功能回溯,还使得团队能够并行工作,通过分支管理实现 ...
- dotnet 警惕 ConcurrentDictionary 使用 FirstOrDefault 获取到非预期的首项
在 dotnet 里面的 ConcurrentDictionary 是一个支持并发读写的线程安全字典,在这个字典里面有一些行为会出现随机性,即多次执行相同的代码返回的结果可能不相同.本文记录在 Con ...
- UCenter 1.6 数据字典
uc_admins 管理员权限表 字段名 数据类型 默认值 允许非空 自动递增 备注 uid mediumint(8) unsigned NO 是 用户ID username char(15) ...
- 数据分析之pyecharts v1版本
维护人员,感谢他们 https://github.com/chenjiandongx https://github.com/chfw https://github.com/kinegratii中文文档 ...
- 《最新出炉》系列入门篇-Python+Playwright自动化测试-42-强大的可视化追踪利器Trace Viewer
1.简介 在我们日常执行自动化测试工作的过程中,经常会遇到一些偶发性的bug,但是因为bug是偶发性的,我们不一定每次执行都能复现,所以我们在测试执行的时候,追踪用例执行就变得非常重要了.playwr ...
- CPU是什么?
在程序是怎样跑起来的这本书中我们首先被询问的一个问题是"程序是什么?它是有什么组成的?而CPU又与程序有什么关系呢?",若我们能知道前两个,其实更容易将你带入讨论"CPU ...