内联函数什么时候展开

You know all of those Util files you create with all sorts of small functions that you end up using a lot throughout your app? If your utility functions get other functions as parameters, chances are you can improve the performance of your app by saving some extra object allocations, that you might not even know you’re making, with one keyword: inline. Let’s see what happens when you pass these short functions around, what inline does under the hood and what you should be aware of when working with inline functions.

您知道使用各种小功能创建的所有Util文件,最终在整个应用程序中大量使用这些文件吗? 如果您的实用程序函数将其他函数用作参数,则可以通过使用一个关键字inline来保存一些甚至可能不知道自己正在做的对象分配,从而提高应用程序的性能。 让我们看看当您传递这些短函数时会发生什么,内联在幕后做什么,以及在使用内联函数时应注意的事项。

函数调用-内幕 (Function call — under the hood)

Let’s say that you use SharedPreferences a lot in your app so you create this utility function to reduce the boilerplate every time you write something in your SharedPreferences:

假设您在应用程序中使用了很多SharedPreferences ,因此您创建此实用程序函数可以在每次在SharedPreferences编写内容时减少样板:

fun SharedPreferences.edit(    commit: Boolean = false,    action: SharedPreferences.Editor.() -> Unit) {    val editor = edit()    action(editor)    if (commit) {        editor.commit()    } else {        editor.apply()    }}

Then, you can use it to save a String token:

然后,您可以使用它保存String令牌:

private const val KEY_TOKEN = “token”class PreferencesManager(private val preferences: SharedPreferences){    fun saveToken(token: String) {        preferences.edit { putString(KEY_TOKEN, token) }    }}

Now let’s see what’s going on under the hood when preferences.edit is called. If we look at the Kotlin bytecode (Tools > Kotlin > Decompiled Kotlin to Java) we see that there’s a NEW called, so a new object is being created, even if in our code we didn’t call any object constructor:

现在,让我们看看调用preferences.edit情况。 如果查看Kotlin字节码(“工具”>“ Kotlin”>“将Kotlin编译为Java”),我们会看到有一个NEW调用,因此正在创建一个新对象,即使在我们的代码中我们没有调用任何对象构造函数:

NEW com/example/inlinefun/PreferencesManager$saveToken$1

Let’s check the decompiled code to make this a bit friendlier. Our saveToken decompiled function is as follows (comments and formatting mine):

让我们检查一下反编译的代码,以使其更加友好。 我们的saveToken反编译功能如下(注释和格式化我的代码):

Each high-order function we create leads to a Function object creation and memory allocation that introduces runtime overhead.

我们创建的每个高阶函数都会导致Function对象的创建和内存分配,从而引入运行时开销。

内联功能-引擎盖下 (Inline function — under the hood)

To improve the performance of our app we can avoid the new function object creation, by using the inline keyword:

为了提高应用程序的性能,我们可以使用inline关键字来避免创建新的函数对象:

inline fun SharedPreferences.edit(    commit: Boolean = false,    action: SharedPreferences.Editor.() -> Unit) { … }

Now the Kotlin bytecode doesn’t contain any NEW calls and here’s how the decompiled java code looks like for our saveToken method (comments and formatting mine):

现在Kotlin字节码不包含任何NEW调用,这是我们saveToken方法的反编译Java代码的样子(注释和格式化我的代码):

Because of the inline keyword, the compiler copies the content of the inline function to the call site, avoiding creating a new Function object.

由于使用inline关键字,编译器将inline函数的内容复制到调用站点,从而避免了创建新的Function对象。

标记为内联的内容 (What to mark as inline)

⚠️ If you’re trying to mark as inline a function that doesn’t accept another function as a parameter, you won’t get significant performance benefits and the IDE will even tell you that, suggesting you to remove it:

If️如果您尝试将不接受另一个函数作为参数的函数标记为内联函数,则不会获得明显的性能优势,IDE甚至会告诉您,建议您删除它:

⚠️ Because inlining may cause the generated code to grow, make sure that you avoid inlining large functions. For example, if you check the Kotlin Standard Library, you’ll see that most of the inlined functions have only 1–3 lines.

⚠️ 因为内联可能导致生成的代码增长,所以请确保您 避免内联大型函数 。 例如,如果您查看Kotlin标准库,您会看到大多数内联函数只有1-3行。

⚠️ Avoid inlining large functions!

Avoid️ 避免内联大型函数!

⚠️ When using inline functions, you’re not allowed to keep a reference to the functions passed as parameter or pass it to a different function — you’ll get a compiler error saying Illegal usage of inline-parameter.

using️使用内联函数时, 不允许保留对作为参数传递的函数的引用或将其传递给其他函数—会出现编译器错误,指出Illegal usage of inline-parameter

So, for example, let’s modify the edit method and the saveToken method. edit method gets another parameter that is then passed to a different function. saveToken uses a dummy variable that gets updated in the new function:

因此,例如,让我们修改edit方法和saveToken方法。 edit方法获取另一个参数,然后将其传递给另一个函数。 saveToken使用一个虚拟变量,该变量在新函数中进行更新:

fun myFunction(importantAction: Int.() -> Unit) {    importantAction(-1)}inline fun SharedPreferences.edit(    commit: Boolean = false,importantAction: Int.() -> Unit = { },    action: SharedPreferences.Editor.() -> Unit) {myFunction(importantAction)    ...}...fun saveToken(token: String) {    var dummy = 3    preferences.edit(importantAction = { dummy = this}) {         putString(KEY_TOKEN, token)    }}

We can see that myFunction(importantAction) produces an error:

我们可以看到myFunction(importantAction)产生一个错误:

Here’s how you can solve this, depending on how your function looks like:

根据函数的外观,可以按照以下方法解决此问题:

Case 1: If you have multiple functions as parameters and you only need to keep a reference to one of them, then you can mark it as noinline.

情况1 :如果您有多个函数作为参数,而只需要保留对其中一个的引用,则可以将其标记为noinline

By using noinline, the compiler will create a new Function object only for that specific function, but the rest will be inlined.

通过使用noinline ,编译器将仅为该特定函数创建一个新的Function对象,而其余的将被内联。

Our edit function will now be:

现在,我们的edit功能将是:

inline fun SharedPreferences.edit(    commit: Boolean = false,noinline importantAction: Int.() -> Unit = { },    action: SharedPreferences.Editor.() -> Unit) {    myFunction(importantAction)    ...}

If we check the bytecode, we see that a NEW call appeared:

如果我们检查字节码,我们会看到出现了一个NEW调用:

NEW com/example/inlinefun/PreferencesManager$saveToken$1

In the decompiled code we can see the following (comments mine):

在反编译的代码中,我们可以看到以下内容(我的评论):

Case 2: If your function only has one function as a parameter, just prefer not using inline at all. If you do want to use inline, you’d have to mark your parameter with noinline, but like this you’ll have low performance benefits by inlining the method.

情况2 :如果您的函数只有一个函数作为参数,则只希望根本不使用inline 。 如果确实要使用内联,则必须用noinline标记参数,但是这样,通过内联该方法将降低性能。

To decrease the memory allocations caused by lambda expressions, use the inline keyword! Make sure you apply it to small functions that take a lambda as a parameter. If you need to keep a reference to a lambda or pass it as an argument to another function use the noinline keyword. Start inlining to start saving!

要减少由lambda表达式引起的内存分配,请使用inline关键字! 确保将其应用于以lambda作为参数的 小函数 。 如果您需要保留对lambda的引用或将其作为参数传递给另一个函数,请使用noinline关键字。 开始内联以开始保存!

翻译自: https://medium.com/androiddevelopers/inline-functions-under-the-hood-12ddcc0b3a56

内联函数什么时候展开


http://www.taodudu.cc/news/show-6170361.html

相关文章:

  • 块级、内联、内联块级
  • 内联模板
  • 什么是内联函数?
  • 什么内联函数?
  • 隐式内联函数和显式内联函数
  • 内联()
  • 内联(inlining)
  • 内联表达式
  • 内联的使用
  • C++的内联函数和非内联函数的区别
  • 内联函数:
  • 【C++】内联函数是什么?内联和宏有什么区别?
  • 内联
  • 内联的优缺点
  • 强制内联和强制不内联
  • 块、内联、内联块都有哪些及其特点
  • 什么是内联函数
  • 什么是方法内联?
  • 题目:什么是内联函数
  • C++ 内联函数详解(搞清内联的本质及用法)
  • java 内联_Java内联类初探
  • [C++] 内联函数inline 以及 auto关键字 -- C++入门(4)
  • Cadence 将原理图导出PDF格式
  • C#对图片进行马赛克处理,可控制模糊程度
  • Java实现给图片局部打马赛克(前提是知道坐标的情况下)
  • 最有用的p d f 格式转换软件
  • 各种格式文件转PDF的免费网站-转
  • 强大免费的在线格式转换工具,三步轻松完成。
  • 免费版软件文档文件格式转换
  • 微软下一代掌上操作系统Microsoft Windows Mobile Crossbow(ZT)

内联函数什么时候展开_内联函数相关推荐

  1. 内连级元素有哪些_内联元素和块级元素

    一.行内元素与块级元素的基本概念 1. 块元素 (block element) : 块级元素生成一个元素框, (默认地)它会填充其父级元素的内容,旁边不 能有其他元素.换句话说,他在元素框之前和之后生 ...

  2. 内网安装python第三方包_内网安装python第三方包

    内网快速安装python第三方包 内网安装包是一个很麻烦的问题,很多时候,内网的源会出现问题,导致无法安装. 这里给出一种快速在内网中安装第三方包,无需使用内网的源. 外网操作 1.根据开发环境下的所 ...

  3. 不是有效的函数或过程名_什么是函数?

    1.什么是函数? 1.函数是一个可以多次使用的功能代码块,一个封闭的(空间),它可以在代码里随意调用.利用函数的封装可以减少重复代码的开发,提高代码的利用率.函数可以传参,利用函数内预先定义的内容对传 ...

  4. matlab 函数句柄@的介绍_什么是函数句柄(转)

    http://blog.csdn.net/kevinhg/article/details/8861774 http://www.ilovematlab.cn/thread-30375-1-1.html ...

  5. 廖雪峰讲python高阶函数求导公式_高阶函数 - 廖雪峰 Python 2.7 中文教程

    高阶函数英文叫Higher-order function.什么是高阶函数?我们以实际代码为例子,一步一步深入概念. 变量可以指向函数 以Python内置的求绝对值的函数abs()为例,调用该函数用以下 ...

  6. 不是有效的函数或过程名_过程和函数

    VBA代码有两种组织形式,一种是过程,另一种就是函数.其实过程和函数有很多相同之处,除了使用的关键字不同之外,还有不同的是: 函数有返回值,过程没有. 函数可以在Access窗体,查询中像一般的Acc ...

  7. 函数对称性常见公式_知识点:函数的对称性总结

    知识点:函数的对称性总结 函数是中学数学教学的主线,是中学数学的核心内容, 也是整个高中数学的基础.函数的性质是竞赛和高考的重点 与热点,函数的对称性是函数的一个基本性质,对称关系不 仅广泛存在于数学 ...

  8. mysql 内联和外联的区别_内联查询与外联查询

    概述 在开发时,我们一般只进行单表查询,但有时候也会涉及到多表查询.内联查询和外联查询都是为了联合多张表进行信息查询.这里只是简单的说明几种联合查询如何使用,具体详细说明可以参看参考链接 联合查询 假 ...

  9. 内网https需要ssl证书_内网需要ssl证书吗

    {"moduleinfo":{"card_count":[{"count_phone":1,"count":1}],&q ...

最新文章

  1. windows 8 修改文件权限
  2. rp软件app流程图_如何开发app软件,流程怎样
  3. ms-sql是mysql吗_mssql和mysql有哪些区别?
  4. Chrome原生工具实现长截图
  5. javascript 浮点数加减乘除计算会有问题, 整理了以下代码来规避这个问题
  6. (二)Docker配置修改阿里云镜像仓库
  7. IBM® Bluemix 上运行ASP.NET Core
  8. flex3 接受外部参数
  9. 面试官 | 这位连单点登录都不知道,让他回家等通知去吧
  10. 计算机CAD作文,CAD:电脑系统字体和CAD字体的区别
  11. cad命令栏还原默认_将CAD恢复到默认界面的两种方法,来看看吧
  12. Pano2VR制作全景图缩略图导航
  13. 中国研修网计算机培训心得,网络研修培训心得体会
  14. 计算机毕业设计JAVA企业售后服务管理系统mybatis+源码+调试部署+系统+数据库+lw
  15. 怎么证明根号2是无理数,我们来推导和计算,还有逼格极高的算法
  16. 阿里云编码规范答案_令人沮丧的答案是“我如何开始学习编码?”
  17. 老鼠出迷宫问题(Java)(递归)
  18. Java Web高级面试题(二)
  19. RecyclerView的好朋友 — SnapHelpter
  20. hdu吃糖果解题报告

热门文章

  1. 戴尔电脑如何设置快速开机
  2. Mac端 淘宝买的廉价 Arduino Mega 2560 的驱动
  3. 输入身高体重测身材_Excel制作身高体重自测表
  4. 最值得推荐的6个物联网开发平台
  5. python录屏实现
  6. international journal of remote sensing投稿经历给我的感悟
  7. 尚硅谷大数据superset安装包冲突
  8. word中代码高亮加行号
  9. kali使用笔记本自带无线网卡_为什么你的无线网卡不好用?
  10. 基于51单片机的简易雷达定位装置