Swift iOS - Class 对象类型比 "Primitive" 类型消耗更多内存吗?
Swift iOS -Does A Class Object Type Consume More Memory Then A "Primitive" Type?
我知道 Swift 原语不存在,但这是我能想到的最好的名字。
几周前我参加了一个聚会,演讲者说 Switch 语句比 If-Else 语句消耗的内存稍多。我不知道两者之间的内存消耗存在差异,如果我考虑过它,我会想到相反的情况。无论如何,它让我开始思考我的代码。
我正在将数据从一个 vc 发送到另一个 vc,我可以通过两种不同的方式进行。
我可以将 2 个变量的值从 ClassA 发送到 ClassB
我可以创建一个 class 或结构模型,它具有与属性相同的 2 个变量,然后将模型从 ClassA 传递到 ClassB
第一个例子:
ClassA:UIViewController{
var firstName: String?
var lastName: String?
viewDidLoad...{
self.firstName = "Veggie"
self.lastName = "Burger"
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "..."{
let classB = segue.destination...
classB.firstName = self.firstName
classB.lastName = self.lastName
}
}
ClassB:UIViewController{
var firstName: String?
var lastName: String?
viewDidLoad...{
self.firstName! ... //do something with it
self.lastName! ... //do something with it
}
}
第二个例子:
class: Person{
firstName: String?
lastName: String?
}
ClassA:UIViewController{
var person: Person?
viewDidLoad...{
self.person = Person()
self.person.firstName = "Veggie"
self.person.lastName = "Burger"
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "..."{
let classB = segue.destination...
classB.person = self.person
}
}
ClassB:UIViewController{
var person: Person?
viewDidLoad...{
self.person.firstName! ... //do something with it
self.person.lastName! ... //do something with it
}
}
我知道在第一个示例中我有 2 个不同的值位于 2 个不同的内存地址,但在第二个示例中我有 1 个值位于 1 个内存地址。我不确定它的属性是否也位于 2 个不同的内存地址或共享同一个。
第一个示例或第二个示例会占用更多内存吗?
内存使用情况应该相似,即使存在细微差别,也并不重要,除非您创建了数百万个实例。
我更喜欢第二个例子,因为相关字段(firstName,lastName)被封装了。这允许您向 Person 添加方法,否则这些方法将驻留在您的视图控制器代码中,导致神 类 并使您的代码更难测试。
对象(classes的实例)有两个机器字的开销。一个指向 meta class 对象(包含有关对象的实例变量、属性、方法等的所有各种信息),另一个包含对象的引用计数和其他记账数据。
这两个字段的开销通常不高。当然,如果您制作很多(100,000 个)小物件,惩罚就会增加。如果你的对象只包含一个机器字的真实数据,但有 2 个字的开销,你只能从内存中获得 33% 的利用率。更大的问题是对象是在堆上分配的,这是一个昂贵的过程。此外,创建对对象的销毁引用需要同步修改对象引用计数。
结构以内联方式存储它们的字段,结构的实例存储在堆栈中。它们非常高效并且可由编译器高度优化。在大多数情况下,启用整个模块优化后,大多数结构在运行时甚至不存在,因为编译器能够直接处理其中的数据。事实上,它们非常高效,以至于你可能认为是 "primitive"(来自 Java 之类的语言)的所有内容实际上都是作为结构(或者可能是 enum
实现的,它类似于).例如Int
(和(U)Int8/16/32/64
)、Character
等都是结构体。
但重要的是,none 这一点非常重要。在确定性能问题之前,让不相关的因素支配您的代码是在浪费时间,而牺牲其他可能更重要的因素(可读性、可维护性、简洁性等)。
如果您需要重复处理成对的名字和姓氏,一定要,请继续制作一个 Person
结构来存储名字和姓氏名字。那是类型的点。使您从位和字节中脱颖而出,使您对代码的思考达到更高、更简单的层次。
我强烈建议您查看 Do iOS 2016 - Rob Napier, Once more, with types, a great talk by @RobNapier
我知道 Swift 原语不存在,但这是我能想到的最好的名字。
几周前我参加了一个聚会,演讲者说 Switch 语句比 If-Else 语句消耗的内存稍多。我不知道两者之间的内存消耗存在差异,如果我考虑过它,我会想到相反的情况。无论如何,它让我开始思考我的代码。
我正在将数据从一个 vc 发送到另一个 vc,我可以通过两种不同的方式进行。
我可以将 2 个变量的值从 ClassA 发送到 ClassB
我可以创建一个 class 或结构模型,它具有与属性相同的 2 个变量,然后将模型从 ClassA 传递到 ClassB
第一个例子:
ClassA:UIViewController{
var firstName: String?
var lastName: String?
viewDidLoad...{
self.firstName = "Veggie"
self.lastName = "Burger"
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "..."{
let classB = segue.destination...
classB.firstName = self.firstName
classB.lastName = self.lastName
}
}
ClassB:UIViewController{
var firstName: String?
var lastName: String?
viewDidLoad...{
self.firstName! ... //do something with it
self.lastName! ... //do something with it
}
}
第二个例子:
class: Person{
firstName: String?
lastName: String?
}
ClassA:UIViewController{
var person: Person?
viewDidLoad...{
self.person = Person()
self.person.firstName = "Veggie"
self.person.lastName = "Burger"
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "..."{
let classB = segue.destination...
classB.person = self.person
}
}
ClassB:UIViewController{
var person: Person?
viewDidLoad...{
self.person.firstName! ... //do something with it
self.person.lastName! ... //do something with it
}
}
我知道在第一个示例中我有 2 个不同的值位于 2 个不同的内存地址,但在第二个示例中我有 1 个值位于 1 个内存地址。我不确定它的属性是否也位于 2 个不同的内存地址或共享同一个。
第一个示例或第二个示例会占用更多内存吗?
内存使用情况应该相似,即使存在细微差别,也并不重要,除非您创建了数百万个实例。
我更喜欢第二个例子,因为相关字段(firstName,lastName)被封装了。这允许您向 Person 添加方法,否则这些方法将驻留在您的视图控制器代码中,导致神 类 并使您的代码更难测试。
对象(classes的实例)有两个机器字的开销。一个指向 meta class 对象(包含有关对象的实例变量、属性、方法等的所有各种信息),另一个包含对象的引用计数和其他记账数据。
这两个字段的开销通常不高。当然,如果您制作很多(100,000 个)小物件,惩罚就会增加。如果你的对象只包含一个机器字的真实数据,但有 2 个字的开销,你只能从内存中获得 33% 的利用率。更大的问题是对象是在堆上分配的,这是一个昂贵的过程。此外,创建对对象的销毁引用需要同步修改对象引用计数。
结构以内联方式存储它们的字段,结构的实例存储在堆栈中。它们非常高效并且可由编译器高度优化。在大多数情况下,启用整个模块优化后,大多数结构在运行时甚至不存在,因为编译器能够直接处理其中的数据。事实上,它们非常高效,以至于你可能认为是 "primitive"(来自 Java 之类的语言)的所有内容实际上都是作为结构(或者可能是 enum
实现的,它类似于).例如Int
(和(U)Int8/16/32/64
)、Character
等都是结构体。
但重要的是,none 这一点非常重要。在确定性能问题之前,让不相关的因素支配您的代码是在浪费时间,而牺牲其他可能更重要的因素(可读性、可维护性、简洁性等)。
如果您需要重复处理成对的名字和姓氏,一定要,请继续制作一个 Person
结构来存储名字和姓氏名字。那是类型的点。使您从位和字节中脱颖而出,使您对代码的思考达到更高、更简单的层次。
我强烈建议您查看 Do iOS 2016 - Rob Napier, Once more, with types, a great talk by @RobNapier