Go-Five things that make Go fast-学习笔记

u012807459 · · 2245 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

Dave Cheney 写了一篇文章 Five things that make Go fast 

从 values, inline function, Escape analysis,Groutine,Segment And Copyings Stack
四个方面介绍了go中的go高性能的一些知识.
首先需要知道几个概念inline function 内联函数 本文会带一些相关讲解具体详情还请Google
变量
Go: var gocon int32 = 1024  占用四个字节
Python: gocon=2014 getsizeof(2014) ---> 24个字节
Java : int gocon = 2014 虽然是4个字节但是如果使用到List<Integer>时 Integer在32OS上16byte
64OS上24byte
去计算这样的开销有意义吗 文中指出是有意义的 --具体请看链接这里只做笔记
CPU之所以发展迅猛更多的是依赖与缓存 那么如果缓存的有用数据能更多那么缓存的性能也就能随之提高缓存的性能提高将会带来更佳的程序性能
通常动态类型的语言 数组中的所有元素类型各不相同 需要被单独的存放到堆中 而不是一个连续的存储数组这就使CPU缓存无用武之地 因为CPU缓存会把一片连续的内存空间读入 而这种分散在不同的内存地址中的数据缓存帮不上忙就CPU只能去读取内存  缓存读取一个数据实在3个CPU时钟周期 而从内存读取一个数据则需要100CPU时钟周期
所以程序性能降低也就是理所应当的了
关于CPU缓存方面的文章 这里给出一个链接 作为参考

内联函数
要知道什么是内联函数首先要知道函数调用是有开销的比如A()中调用了B()在调用B函数时又有开销--开销大致可分两部分 传递参数的开销和保存当前程序上下文信息所花费的开销。对于传递参数的开销而言,传递的参数越多开销就越大;对于保存当前程序上下文所花费的开销而言,函数越复杂需要花费的开销就越大。
如果一个很简单的函数其函数功能的开销甚至比函数调用的开销还要来的小的多,那就极其的不划算了。而内联函数的目的就在于在编译器会将一些功能极其简单的被调用函数代码内嵌到调用函数中。
如下代码所示
func Max(a, b int) int {
	if a>b {
	return a
	}
	return b
}
func Double(a, b int) int {
	return Max(a,b)
}
因为Max函数功能极其简单其功能的消耗远小于函数调用的消耗
所以就会把Max函数内嵌到Double函数中
而编译器会将上述代码转换为如下
func Double(a, b int) int {
	temp := b
	if a>b {
		temp = a
	}
	return 2 * temp
}
可能有人会有疑问把所有的代码都内嵌不就好了--但这其实是有问题的
在 five things thar make go fast 中有一段话讲述了原因 原文如下

The Go compiler inlines a function by treating the body of the function as if it were part of the caller.

Inlining has a cost; it increases binary size.

It only makes sense to inline when the overhead of calling a function is large relative to the work the function does, so only simple functions are candidates for inlining.

Complicated functions are usually not dominated by the overhead of calling them and are therefore not inlined.

大致的意思就是说
Go的编译器通过函数的主体内联一个函数就好像这个函数就是调用者的一部分
内联函数也是有开销的 他会增长二进制码的大小
调用一个函数的开销远大于该函数所做的工作时内联才有意义所以只有那些功能简单的函数才会被作为内敛的候选
一个复杂的函数函数的开销对其来说并不占据主导因此也就没必要内联这种负责的函数

总结上面的四段话就是如果复杂的函数也内联那么二进制码增加占用的内存大小也就更大了并且这种内联毫无意义因为相对于复杂的函数这点函数调用的开销基本可以忽略不计
而对于Go 文中也做了介绍
The Go compiler can automatically inline functions across files and even across packages. This includes code that calls inlinable functions from the standard library.
Go的编译器会自动的通过文件和包内敛那些简单的函数 这些函数包括标准库中的函数

Escape analysis (逃逸分析)

关于逃逸分析的文章请戳这篇链接什么是逃逸分析(Escape Analysis)

逃逸分析的优化原理:编译器在编译期间队未逃逸的对象进行标记运行期间并不是把对象扔到堆里而是直接扔到栈里这样当线程执行结束后栈的空间就被回收 站内的局部变量也被回收了 这远比GC来回收要有效率的多。并且栈分配页远比堆分配要来的快得多经过逃逸分析优化的程序性能必然提高不少

原文中的一段描述如下
Because escape analysis is performed at compile time, not run time, stack allocation will always be faster than heap allocation, no matter how efficient your garbage collector is.

Goroutine 这种从语言层面就支持并发的语言确实让人很欢喜 这比Java的线程池还要来的高端线程池也就只是控制线程
而Go不但控制线程还具体到控制协程之间的合作
文中提到的几点先记录在此

Places where Goroutines may yield to others are:

  • Channel send and receive operations, if those operations would block.
  • The Go statement, although there is no guarantee that new goroutine will be scheduled immediately.
  • Blocking syscalls like file and network operations.
  • After being stopped for a garbage collection cycle.
  • 可能产生 协程的地方有以下几种情况
  • 管道发送接收数据时如果操作是阻塞的就会有协程的产生
  • 使用go关键字的地方 并不能保证立即执行
  • 阻塞调用时 比如 文件操作和网络操作
  • 停止了垃圾回收之后

Segment And Copyings Stack 还没看完 以后再补上


有疑问加站长微信联系(非本文作者)

本文来自:CSDN博客

感谢作者:u012807459

查看原文:Go-Five things that make Go fast-学习笔记

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

2245 次点击  
加入收藏 微博
下一篇:[Go] --- map
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传