Swift内存布局简介

在上一篇文章中,我们讨论了Swifts 值类型语义的一些功能。 今天,我们将看一下如何分配不同的Swift类型以及这对我们的应用程序性能意味着什么的基础知识。

一个简单的类是Reference Type ,就像上一篇文章中提到的那样。 它具有一些我们大多数人都很早就了解的功能。 例如,单个类对象可以被多个变量引用和操纵。 但是,当我们创建一个类的实例时会发生什么呢?

 类MyClass { 
var a:整数
init(a:Int){
self.a = a
}
} var A = MyClass(a:1)

上面的示例提供了一个简单的类,使我们可以开始研究创建引用类类型的变量A时发生的情况。

当我们调用MyClass初始化程序时,将进行一次调用以分配足够的内存以将我们的对象存储在内存中,在这里我们需要查看主内存的两个非常重要部分的第一个,即The Heap

是我们内存中用于动态分配的一部分。 这意味着如果在运行应用程序时需要即时创建一个新的引用类型对象,则需要在The Heap上请求空间。 由于内存的这一部分需要能够一次为多个线程提供服务而又不破坏任何数据,因此还需要一些机制来避免两次分配相同的内存块并处理并行分配调用。 在不详细介绍如何进行管理的情况下,让我们继续进行以下假设,即这实际上需要花费一些时间。

一旦找到足够的内存块并为我们分配了内存,我们的应用程序即可完成对对象的初始化。 除了初始化类中的实际值外,还需要初始化一些元数据值(其中包括类型数据和引用计数器)。 Swift使用一种称为自动引用计数(ARC)的方法来跟踪实际使用的对象。 如果某个对象未被任何变量引用,则可以安全地将其删除,并且可以将存储块返回以用于其他用途。 这是一个很棒的功能,但是它伴随着每次创建或共享对象时更新计数器的开销。

通常,如果您只是分配一个新对象,那么花费的时间就不会引起您的注意。 但是,如果您的程序不断创建这样的新对象,那么成本将会增加,并且您最终可能会浪费本来可以更好地用于其他用途的资源。

正如我在上一篇文章中提到的那样, structenum (以及其他)都是Value Types 。 我们需要问自己的问题是:将在哪里分配值类型? 这部分会有些棘手。 让我们首先看一下堆栈 -两个重要的主内存部分中的第二个。

堆栈是内存的一部分,它从其操作方式中获得名称-就像堆栈一样。 这个想法是,您有一堆数据,如果您添加任何新数据,它将被添加到顶部。 删除数据也被限制在内存空间的顶端,因此我们只能删除当前放置在顶部的数据。 系统使用一个简单的指针来跟踪当前堆栈内存顶部的位置。 这意味着分配和取消分配内存是通过简单的增量或减量操作完成的,因此非常快。 不利的一面是,这种结构与The Heap可以提供的动态分配类型不太兼容。

回到我们的“ 价值类型”及其最终结果的问题,答案是反气候的,至少可以这样说:“取决于”。

 结构点{ 
var x:Double
var y:Double
} var P =点(x:1,y:2)

假设我们具有上面的结构来表示2D坐标系中的点。 作为固定大小且相对较小的值类型 (并且仅由其他值类型组成),此结构将最终出现在The Stack上 ,这意味着分配是通过将堆栈指针减两步并将xy放入那里的价值。 指针会减少,因为按照惯例, 堆栈会“向下”增长。

数组类型呢? Swift数组被声明为结构,这意味着它也应该驻留在The Stack上 。 实际上不,这是不同值类型开始不同的地方。 数组是动态类型,这意味着它可以在运行时增大和缩小大小。 我们并不总是确切知道数组中将有多少个值,因此它需要能够自行调整大小以适应您的需求。 因此,在这方面,数组将更像是引用类型。 它将最终在The Heap上进行 ,这意味着它必须经历与我们的类相同的分配过程(有例外,但这些例外主要由非常无用的边缘情况组成)。 这对于这种特定的数据结构是有意义的,并且分配数组的成本由以下事实来弥补,即以后更容易调整其大小。 如果您确切知道一个数组将容纳多少个值,则可以使用.reserveCapacity(_:)方法来进一步降低分配它的成本。 这将从一开始就分配正确的内存大小,您将不会产生更多的分配成本。

使用引用类型的情况通常涉及以下情况:您需要能够在程序的不同部分之间共享可变状态,并且希望避免分配新的内存。 如果需要子类化外部框架的某些部分(就像UIKit那样),那么对引用类型的需求也很容易解释。

几乎所有其他情况都适合使用值类型 。 Swifts 值类型语义通常会由于其分配和管理方式而提高性能,并且它们几乎总是使跟踪错误更加容易。

本周就这样! 如果您想了解有关不同类型将如何影响您的应用程序性能的更多信息,可以查看此演示文稿,其中Mike Ash深入介绍了有关Swift如何处理内存布局的一些详细信息。

如果您有任何疑问,请随时发表评论,然后继续获取有关未来文章的通知。


要了解有关iOS开发的更多信息,请查看我以前的文章:

了解Swift价值语义学

即使您刚刚开始编程,也有可能偶然发现了Value Types。 你可能甚至没有…

medium.com

使用Swift设计多线程应用程序

作为汽车行业的iOS开发人员,我花了大量时间处理实时数据。 为了…

medium.com