返回顶部
首页 > 资讯 > 精选 >Go中的内联优化方法是什么
  • 823
分享到

Go中的内联优化方法是什么

2023-06-16 13:06:20 823人浏览 八月长安
摘要

本篇内容主要讲解“Go中的内联优化方法是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Go中的内联优化方法是什么”吧!内联是什么?内联inlining就是把简短的函数在调用它的地方展开。在计

本篇内容主要讲解“Go中的内联优化方法是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Go中的内联优化方法是什么”吧!

内联是什么?

内联inlining就是把简短的函数在调用它的地方展开。在计算机发展历程的早期,这个优化是由程序员手动实现的。现在,内联已经成为编译过程中自动实现的基本优化过程的其中一步。

为什么内联很重要?

有两个原因。第一个是它消除了函数调用本身的开销。第二个是它使得编译器能更高效地执行其他的优化策略。

函数调用的开销

在任何语言中,调用一个函数 1 都会有消耗。把参数编组进寄存器或放入栈中(取决于 ABI),在返回结果时的逆反过程都会有开销。引入一次函数调用会导致程序计数器从指令流的一点跳到另一点,这可能导致管道滞后。函数内部通常有前置处理preamble,需要为函数执行准备新的栈帧,还有与前置相似的后续处理epilogue,需要在返回给调用方之前释放栈帧空间。

在 Go 中函数调用会消耗额外的资源来支持栈的动态增长。在进入函数时,goroutine 可用的栈空间与函数需要的空间大小进行比较。如果可用空间不同,前置处理就会跳到运行时runtime的逻辑中,通过把数据复制到一块新的、更大的空间的来增长栈空间。当这个复制完成后,运行时就会跳回到原来的函数入口,再执行栈空间检查,现在通过了检查,函数调用继续执行。这种方式下,goroutine 开始时可以申请很小的栈空间,在有需要时再申请更大的空间。2

这个检查消耗很小,只有几个指令,而且由于 goroutine  的栈是成几何级数增长的,因此这个检查很少失败。这样,现代处理器的分支预测单元可以通过假定检查肯定会成功来隐藏栈空间检查的消耗。当处理器预测错了栈空间检查,不得不放弃它在推测性执行所做的操作时,与为了增加  goroutine 的栈空间运行时所需的操作消耗的资源相比,管道滞后的代价更小。

虽然现代处理器可以用预测性执行技术优化每次函数调用中的泛型和 Go  特定的元素的开销,但那些开销不能被完全消除,因此在每次函数调用执行必要的工作过程中都会有性能消耗。一次函数调用本身的开销是固定的,与更大的函数相比,调用小函数的代价更大,因为在每次调用过程中它们做的有用的工作更少。

因此,消除这些开销的方法必须是要消除函数调用本身,Go 的编译器就是这么做的,在某些条件下通过用函数的内容来替换函数调用来实现。这个过程被称为内联,因为它在函数调用处把函数体展开了。

改进的优化机会

Cliff Click 博士把内联描述为现代编译器做的优化措施,像常量传播(LCTT 译注:此处作者笔误,原文为 constant  proportion,修正为 constant  propagation)和死代码消除一样,都是编译器的基本优化方法。实际上,内联可以让编译器看得更深,使编译器可以观察调用的特定函数的上下文内容,可以看到能继续简化或彻底消除的逻辑。由于可以递归地执行内联,因此不仅可以在每个独立的函数上下文处进行这种优化决策,也可以在整个函数调用链中进行。

实践中的内联

下面这个例子可以演示内联的影响:

package main import "testing" //go:noinlinefunc max(a, b int) int {    if a > b {        return a    }    return b} var Result int func BenchmarkMax(b *testing.B) {    var r int    for i := 0; i < b.N; i++ {        r = max(-1, i)    }    Result = r}

运行这个基准,会得到如下结果:3

% go test -bench=. BenchmarkMax-4   530687617         2.24 ns/op

在我的 2015 MacBook Air 上 max(-1, i) 的耗时约为 2.24 纳秒。现在去掉 //go:noinline 编译指令,再看下结果:

% go test -bench=. BenchmarkMax-4   1000000000         0.514 ns/op

从 2.24 纳秒降到了 0.51 纳秒,或者从 benchstat 的结果可以看出,有 78% 的提升。

% benchstat {old,new}.txtname   old time/op  new time/op  deltaMax-4  2.21ns &plusmn; 1%  0.49ns &plusmn; 6%  -77.96%  (p=0.000 n=18+19)

这个提升是从哪儿来的呢?

首先,移除掉函数调用以及与之关联的前置处理 4 是主要因素。把 max 函数的函数体在调用处展开,减少了处理器执行的指令数量并且消除了一些分支。

现在由于编译器优化了 BenchmarkMax,因此它可以看到 max 函数的内容,进而可以做更多的提升。当 max 被内联后,BenchmarkMax 呈现给编译器的样子,看起来是这样的:

func BenchmarkMax(b *testing.B) {    var r int    for i := 0; i < b.N; i++ {        if -1 > i {            r = -1        } else {            r = i        }    }    Result = r}

再运行一次基准,我们看一下手动内联的版本和编译器内联的版本的表现:

% benchstat {old,new}.txtname   old time/op  new time/op  deltaMax-4  2.21ns &plusmn; 1%  0.48ns &plusmn; 3%  -78.14%  (p=0.000 n=18+18)

现在编译器能看到在 BenchmarkMax 里内联 max 的结果,可以执行以前不能执行的优化措施。例如,编译器注意到 i 初始值为 0,仅做自增操作,因此所有与 i 的比较都可以假定 i 不是负值。这样条件表达式 -1 > i 永远不是 true5

证明了 -1 > i 永远不为 true 后,编译器可以把代码简化为:

func BenchmarkMax(b *testing.B) {    var r int    for i := 0; i < b.N; i++ {        if false {            r = -1        } else {            r = i        }    }    Result = r}

并且因为分支里是个常量,编译器可以通过下面的方式移除不会走到的分支:

func BenchmarkMax(b *testing.B) {    var r int    for i := 0; i < b.N; i++ {        r = i    }    Result = r}

这样,通过内联和由内联解的优化过程,编译器把表达式 r = max(-1, i)) 简化为 r = i

内联的限制

本文中我论述的内联称作叶子内联leaf inlining:把函数调用栈中最底层的函数在调用它的函数处展开的行为。内联是个递归的过程,当把函数内联到调用它的函数 A 处后,编译器会把内联后的结果代码再内联到 A 的调用方,这样持续内联下去。例如,下面的代码:

func BenchmarkMaxMaxMax(b *testing.B) {    var r int    for i := 0; i < b.N; i++ {        r = max(max(-1, i), max(0, i))    }    Result = r}

与之前的例子中的代码运行速度一样快,因为编译器可以对上面的代码重复地进行内联,也把代码简化到 r = i 表达式。

到此,相信大家对“Go中的内联优化方法是什么”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

--结束END--

本文标题: Go中的内联优化方法是什么

本文链接: https://lsjlt.com/news/283642.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Go中的内联优化方法是什么
    本篇内容主要讲解“Go中的内联优化方法是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Go中的内联优化方法是什么”吧!内联是什么?内联inlining就是把简短的函数在调用它的地方展开。在计...
    99+
    2023-06-16
  • mysql多表关联优化的方法是什么
    优化多表关联的方法有以下几种: 使用索引:在关联字段上建立索引可以加快查询速度。确保每个表的关联字段都有索引,并且尽量使用覆盖索引...
    99+
    2024-03-06
    mysql
  • mysql多表关联查询优化的方法是什么
    在优化MySQL多表关联查询时,可以采取以下方法: 确保表中的相关字段有索引:在进行多表关联查询时,通常会使用到相关字段进行连接...
    99+
    2024-04-09
    mysql
  • 互联网中蝴蝶优化算法是什么
    这篇文章主要为大家展示了“互联网中蝴蝶优化算法是什么”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“互联网中蝴蝶优化算法是什么”这篇文章吧。算法简介蝴蝶优化算法(butterfly optimiz...
    99+
    2023-06-29
  • mysql中find_in_set优化的方法是什么
    在MySQL中,可以通过使用适当的索引来优化FIND_IN_SET()函数的性能。 FIND_IN_SET()函数用于在逗号分隔的字...
    99+
    2024-04-09
    mysql
  • MongoDB的内存管理与优化方法是什么
    MongoDB的内存管理与优化可以通过以下方法实现: 使用合理的索引:为经常查询的字段创建索引,可以加快查询速度,减少内存的占用...
    99+
    2024-05-07
    MongoDB
  • MySQL优化的方法是什么
    这篇文章主要介绍“MySQL优化的方法是什么”,在日常操作中,相信很多人在MySQL优化的方法是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”MySQL优化的方法是什么”...
    99+
    2024-04-02
  • sparksql优化的方法是什么
    SparkSQL优化的方法有以下几种: 数据分区:根据数据的特点和查询的需求,将数据划分成多个分区。这样可以提高查询的性能,因为...
    99+
    2023-10-22
    sparksql
  • Tomcat中性能优化的方法是什么
    调整JVM参数:通过调整JVM参数来优化Tomcat的性能,可以提高Tomcat的运行效率。例如增加堆内存大小、调整垃圾回收策略...
    99+
    2024-04-03
    Tomcat
  • 内联css的写法是什么
    本篇内容介绍了“内联css的写法是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!内联css写法如“<p style="c...
    99+
    2023-07-04
  • Go语言中数组在异步编程中的优化方法是什么?
    Go语言作为一门强大的编程语言,越来越受到开发者们的青睐。在异步编程中,数组的使用是非常常见的,但是如何对数组进行优化呢?本文将会介绍在Go语言中数组在异步编程中的优化方法。 一、为什么需要优化数组 在Go语言中,数组是一种非常常见的数据类...
    99+
    2023-08-08
    异步编程 数据类型 数组
  • mysql oom优化的方法是什么
    OOM(Out of Memory)是指MySQL在执行过程中耗尽了服务器的内存资源,导致MySQL服务异常退出。为了解决OOM问题...
    99+
    2024-04-12
    mysql
  • 数据库中优化SQL的方法是什么
    本篇内容介绍了“数据库中优化SQL的方法是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!判断问题SQL...
    99+
    2024-04-02
  • Spark内存调优的方法是什么
    这篇文章主要介绍“Spark内存调优的方法是什么”,在日常操作中,相信很多人在Spark内存调优的方法是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Spark内存调优的方法是什么”的疑惑有所帮助!接下来...
    99+
    2023-07-05
  • jvm内存调优的方法是什么
    JVM内存调优的方法有以下几种: 调整堆内存大小:可以通过设置-Xmx和-Xms参数来调整堆内存的大小。增大堆内存可以提高应用程...
    99+
    2023-10-27
    jvm
  • MySQL SQL优化方法是什么
    这篇文章主要讲解了“MySQL SQL优化方法是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“MySQL SQL优化方法是什么”吧!slowlog里查到...
    99+
    2024-04-02
  • 数据库优化的方法是什么
    数据库优化的方法是什么?这个问题可能是我们日常学习或工作经常见到的。希望通过这个问题能让你收获颇深。下面是小编给大家带来的参考内容,让我们一起来看看吧!数据库优化的方式有:1、选取最适用的字段属性;2、使用...
    99+
    2024-04-02
  • MySQL性能优化的方法是什么
    本篇内容主要讲解“MySQL性能优化的方法是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“MySQL性能优化的方法是什么”吧!一、优化思路数据查询慢,不代表...
    99+
    2024-04-02
  • Java代码优化的方法是什么
    这篇文章主要讲解了“Java代码优化的方法是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java代码优化的方法是什么”吧!一、代码优化的目标是:减小代码的体积提高代码运行的效率本文的内...
    99+
    2023-06-17
  • TOMCAT配置优化的方法是什么
    本篇内容主要讲解“TOMCAT配置优化的方法是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“TOMCAT配置优化的方法是什么”吧!Tomcat连接器协议优化Tomcat 连接器的三种方式: ...
    99+
    2023-06-27
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作