阅读更多

0顶
0踩

移动开发

转载新闻 Swift如何优化性能?

2015-03-06 10:49 by 副主编 mengyidan1988 评论(0) 有4295人浏览
Swift在内存管理上使用的是自动引用计数(ARC)的一套方法,在ARC中虽然不需要手动地调用像是retain,release或者是autorelease这样的方法来管理引用计数,但是这些方法还是都会被调用的——只不过是编译器在编译时在合适的地方帮我们加入了而已。其中retain和release都很直接,就是将对象的引用计数加一或者减一。但是autorelease就比较特殊一些,它会将接受该消息的对象放到一个预先建立的自动释放池 (auto release pool)中,并在自动释放池收到drain消息时将这些对象的引用计数减一,然后将它们从池子中移除(这一过程形象地称为“抽干池子”)。



在App中,整个主线程其实是跑在一个自动释放池里的,并且在每个主Runloop结束时进行drain操作。这是一种必要的延迟释放的方式,因为我们有时候需要确保在方法内部初始化的生成的对象在被返回后别人还能使用,而不是立即被释放掉。

在Objective-C中,建立一个自动释放池的语法很简单,使用@autoreleasepool就行了。如果你新建一个Objective-C项目,可以看到main.m中就有我们刚才说到的整个项目的autoreleasepool:
int main(int argc, char *argv[]) {
    @autoreleasepool {
        int retVal = UIApplicationMain(
            argc, 
            argv, 
            nil, 
            NSStringFromClass([AppDelegate class]));
        return retVal;
    }
}

更进一步,其实@autoreleasepool在编译时会被展开为NSAutoreleasePool,并附带drain方法的调用。

而在Swift项目中,因为有了@UIApplicationMain,我们不再需要main文件和main函数,所以原来的整个程序的自动释放池就不存在了。即使我们使用main.swift来作为程序的入口时,也是不需要自己再添加自动释放池的。

但是在一种情况下我们还是希望自动释放,那就是在面对在一个方法作用域中要生成大量的autorelease对象的时候。在Swift 1.0时,我们可以写这样的代码:
func loadBigData() {
    if let path = NSBundle.mainBundle()
        .pathForResource("big", ofType: "jpg") {
        for i in 1...10000 {
            let data = NSData.dataWithContentsOfFile(
                path, options: nil, error: nil)
            NSThread.sleepForTimeInterval(0.5)
        }        
    }
}

dataWithContentsOfFile返回的是autorelease的对象,因为我们一直处在循环中,因此它们将一直没有机会被释放。如果数量太多而且数据太大的时候,很容易因为内存不足而崩溃。在Instruments下可以看到内存alloc的情况:



这显然是一幅很不妙的情景。在面对这种情况的时候,正确的处理方法是在其中加入一个自动释放池,这样我们就可以在循环进行到某个特定的时候施放内存,保证不会因为内存不足而导致应用崩溃。在Swift中我们也是能使用autoreleasepool的——虽然语法上略有不同。相比于原来在Objective-C中的关键字,现在它变成了一个接受闭包的方法:
func autoreleasepool(code: () -> ())

利用尾随闭包的写法,很容易就能在Swift中加入一个类似的自动释放池了:
func loadBigData() {
    if let path = NSBundle.mainBundle()
        .pathForResource("big", ofType: "jpg") {
        for i in 1...10000 {
            autoreleasepool {
                let data = NSData.dataWithContentsOfFile(
                    path, options: nil, error: nil)
                NSThread.sleepForTimeInterval(0.5)
            }
        }        
    }
} 

这样改动以后,内存分配就没有什么忧虑了:



这里我们每一次循环都生成了一个自动释放池,虽然可以保证内存使用达到最小,但是释放过于频繁也会带来潜在的性能忧虑。一个折中的方法是将循环分隔开加入自动释放池,比如每10次循环对应一次自动释放,这样能减少带来的性能损失。

其实对于这个特定的例子,我们并不一定需要加入自动释放。在Swift中更提倡的是用初始化方法而不是用像上面那样的类方法来生成对象,而且在Swift 1.1中,因为加入了可以返回nil的初始化方法,像上面例子中那样的工厂方法都已经从API中删除了。今后我们都应该这样写:
let data = NSData(contentsOfFile: path)

使用初始化方法的话,我们就不需要面临自动释放的问题了,每次在超过作用域后,自动内存管理都将为我们处理好内存相关的事情。

作者:王巍(@onevcat),iOS和Unity3D开发者。

本文转载自:Swifter
  • 大小: 10.4 KB
  • 大小: 10.3 KB
  • 大小: 11.5 KB
来自: Swifter
0
0
评论 共 0 条 请登录后发表评论

发表评论

您还没有登录,请您登录后再发表评论

相关推荐

  • 深入剖析Swift性能优化

    2014年,苹果公司在WWDC上发布Swift这一新的编程语言。...针对Swift性能提升这一问题,我们可以从概念上拆分为两个部分:编译器:Swift编译器进行的性能优化,从阶段分为编译期和运行期,内容分为时间优化和空

  • Swift性能优化

    Swift性能优化分析,Swift vs. Objective-C Program speed (higher is better)

  • swift-iOS性能优化总结

    关于iOS 性能优化梳理、内存泄露、卡顿、网络、GPU、电量、 App 包体积瘦身、启动速度优化等、Instruments 高级技巧、常见的优化技能- Get — Edit

  • swift ceph 性能对比

    采用 Cosbench工具做的 swift Ceph性能对比

  • java与swift性能,Swift语言性能分析

    一、两个疑惑OC 和 Swift 语言在 Richards 上评测的结果显示,Swift 比 OC 快了4倍,Swift同OC相比会更快,具体应归结在那些因素上面?通常一个 Swift 项目少则编译五六分钟,多则编译个半个小时也是不为过的事情,...

  • 技术学习-Swift子数组提取性能优化分析

    技术学习-Swift子数组提取性能优化分析前言问题1. for方法求解2. 数组内置的区间运算符求解3.方法三:while循环4.内存复制编译器优化取舍分析经验总结: 前言 公司大佬,经常会在群里发送一些认为比较有价值的技术...

  • Swift性能探索和优化分析

    Apple在推出Swift时就将其冠以先进、安全和高效的新一代编程语言之名。...在2014年WWDC大会上,Apple宣称Swift具有超越Objective-C的性能,甚至某些情况下可以媲美和超过C。但在正式发布后,很多开发者发现

  • swift python 性能_Swift 性能探索和优化分析

    Apple 在推出 Swift 时就将其冠以先进,安全和高效的新一代编程语言之名。前两点在 Swift 的语法和语言...在 2014 年 WWDC 大会上 Apple 宣称 Swift 具有超越 Objective-C 的性能,甚至某些情况下可以媲美和超过 ...

  • swift-UITableView的优化

    在iOS开发的过程中,UITableview是使用频率很高的控件之一,今天写的优化方法不是关于性能优化方面的,主要从为Controller瘦身方面考虑的。在使用tableView的时候不可避免的要谈到tableView的delegate和dataSource两...

  • Swift中的高性能JSON库-Swift开发

    从JSON解码类型时,它的性能比Foundation中的Foundation快4倍。 添加依赖项1.x版本依赖于SwiftNIO 1.x,对于SwiftN IkigaJSON IkigaJSON IkigaJSON是一个非常快速的JSON解析器。 从JSON解码类型时,它的性能比...

  • 高性能GIF引擎-Swift开发

    高性能和易于使用的Gif引擎功能基于UIImage和UIImageView扩展的远程Gif出色的CPU /内存性能控制回放通过使用'levelOf SwiftyGif来控制显示质量高性能和易于使用的Gif引擎功能基于UIImage和UIImageView扩展的远程GIF...

  • 【基本功】深入剖析Swift性能优化

    简介 2014年,苹果公司在WWDC上发布Swift这一新的编程语言。经过几年的发展,Swift已经成为iOS开发语言的“中流砥柱”,Swift提供了非常灵活的高级别特性,例如协议、闭包... 针对Swift性能提升这一问题,我们可以从..

  • swift-SurgeSwift高性能数字计算库

    Mattt 大神的新作,利用 Accelerate 框架实现了许多常用的数学运算、数字信号处理和图像计算。

  • swift-GifuiOS高性能GIF动画库

    Gifu 在内部维护一个 animator,用它跟踪和显示不同的帧。其优势是内存占用少,同一时间只会向内存中加载三帧(当前帧和预加载的两帧),释放之前展示过的内容,从而大幅减少内存占用。

  • Swift编译慢?教你如何10倍提速,全套开源

    鉴于目前市场上,Swift及Swift-OC混编项目流行,且Swift的编译项目过慢的问题,在业务繁忙之瑕,做了对Swift、Swift-OC项目的二进制组件化的支持。希望能给小伙伴们在iOS编译的问题上,提供帮助。 二、项目效果 直接...

  • Swift性能优化分析.pdf、Swift3.0中文版文档.pdf、swift4新功能.pdf

    Swift性能优化分析.pdf、Swift3.0中文版文档.pdf、swift4新功能.pdf

  • tornado-6.4.1-cp38-abi3-musllinux_1_2_i686.whl

    tornado-6.4.1-cp38-abi3-musllinux_1_2_i686.whl

  • tornado-6.1-cp36-cp36m-manylinux2014_aarch64.whl

    tornado-6.1-cp36-cp36m-manylinux2014_aarch64.whl

Global site tag (gtag.js) - Google Analytics