Ios 减少发布100万+;弹出VC时的对象
当前的iOS应用程序需要从服务器上下载超过一百万个对象,并且出于某些目的,我们将其保存在一个阵列中。当用户完成此功能后,应用程序需要一段时间才能返回上一个屏幕(约15秒),因为100万个对象正在被释放。我们可以从仪器中看到,在这段时间(15秒)内,计数从100万变为0。是否有任何方法可以加快释放阵列中的这些1 mn对象的速度?与其尝试更快地释放这些对象,我建议您以更慢的速度释放它们Ios 减少发布100万+;弹出VC时的对象,ios,memory-management,automatic-ref-counting,dealloc,Ios,Memory Management,Automatic Ref Counting,Dealloc,当前的iOS应用程序需要从服务器上下载超过一百万个对象,并且出于某些目的,我们将其保存在一个阵列中。当用户完成此功能后,应用程序需要一段时间才能返回上一个屏幕(约15秒),因为100万个对象正在被释放。我们可以从仪器中看到,在这段时间(15秒)内,计数从100万变为0。是否有任何方法可以加快释放阵列中的这些1 mn对象的速度?与其尝试更快地释放这些对象,我建议您以更慢的速度释放它们 把这些东西都放在别的地方。创建一些singleton[ObjectsManager sharedInstance]
[ObjectsManager sharedInstance]
,它将负责下载所有这些对象并将其保存在一些NSMutableArray
中[[ObjectsManager sharedInstance]RemoveAllDownloadedObject]
,这将缓慢地从NSMutableArray中删除所有对象
[myArray removeAllObjects]
,而是一部分一部分地写--使用NSOperation
或GCD
每秒删除20000个对象在iphone6s上,我在大约1.5秒的时间内释放了约600 MB的100万个实例(选择了昂贵的
UIView
)。当使用普通类(~50MB)进行测试时,需要约0.2秒。尽管如此,如果您可以将数据保存在struct中,您将接近于零。我相信,你正在其他地方浪费时间
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
class C: UIView {
static var c = 0
deinit { C.c -= 1 }
init() { C.c += 1; super.init(frame: CGRect.zero) }
required init?(coder aDecoder: NSCoder) { fatalError() }
}
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
var a: [C]? = []
for i in 0..<1_000_000 {
a!.insert(C(), atIndex: i)
}
print(C.c) // We have 1_000_000 allocations.
let t1 = CFAbsoluteTimeGetCurrent()
a = nil
let t2 = CFAbsoluteTimeGetCurrent()
print(t2 - t1) // 1 milion instances of ~600 MB freed in ~1.5 seconds.
print(C.c) // ARC works!
return true
}
}
导入UIKit
@UIApplicationMain
类AppDelegate:UIResponder、UIApplicationLegate{
变量窗口:UIWindow?
C类:UIView{
静态变量c=0
脱硝{C.C-=1}
init(){C.C+=1;super.init(frame:CGRect.zero)}
必需的初始化?(编码器aDecoder:NSCoder){fatalError()}
}
func应用程序(应用程序:UIApplication,didFinishLaunchingWithOptions启动选项:[NSObject:AnyObject]?)->Bool{
变量a:[C]?=[]
对于0中的i.问题是堆碎片化
。用ie ObjC/C/C++等语言释放连续内存块速度很快。相比之下,释放碎片化内存速度很慢。这很难测试,因为分配和释放模式经常会影响您看到的碎片量。举个例子可能会有所帮助。
许多分配器使用大小混合的链表箱进行分配。当你在循环中分配一百万个链表时,你可能会有很多连续的内存块,当在循环中释放时,这些内存块会利用缓存等,看起来很快。当你在生产中测试它时,速度就不那么快了
避免它的唯一方法是避免堆碎片,这意味着
分配包含N个对象的块,并一次性取消分配每个块
理想情况下,为N个对象的整个集合分配一个连续内存区域,并在一次调用中取消分配
我希望这些对象中的每一个都只有几个字节。你在真正的设备上测试过吗?是的,它已经在设备上测试过了。对象数组本身大约需要15 MB的内存。你没有提供任何代码或信息,因此很难跟踪正在进行的操作。你有标签自动引用计数,所以我可以m假设您使用的是arc。返回上一个屏幕时您是否正在执行代码?dealloc方法中是否有代码?分配了多少次?释放15MB内存不应花费15秒,除非您为每个对象分配了一次。您是否可以为这些对象预分配空间?您是否尝试过@autorelease{}
pool.iOS会自动管理对象的解除分配。一旦VC不再使用,这将自动删除已创建对象的引用。当前的方法是在ViewWillEnglishe方法中将数组设置为nil。在仪器运行时,可以观察到设置为nil不会立即强制解除分配。虽然控制转到下一行,但解除分配继续并行进行,数组的大小变得越来越小。您确定viewwilldefine
是执行如此昂贵的操作的好地方吗?您可能想再次显示/显示它,此时您的数据将丢失。除非您有我对它进行了良好的设计,我会在deinit
中将它隐式释放。解除分配不立即的原因可能是存在对象的其他所有者(另一个数组、单元格等)。还要区分解除初始化和解除分配。一旦强制解除初始化(ARC发现对象的引用计数为零),你很好,让系统做dealloc(这不会立即发生).而且…这里我强烈建议考虑struct
s。好吧,在视图中设置它将消失是最早开始解除分配的地方。这没有问题,因为VC会弹出,底层VC会显示,在这段时间内,解除分配会继续发生。您不想过早地进行,但smoo第三,如果你没有理由在视图中这样做,那么就不要这样做。在考虑@OlDor的解决方案时也要小心。当你需要在完成“缓慢删除”之前插入新对象时,你可能会遇到赛车问题。设计这样的模式有点棘手。“每秒删除20000个对象”我的设计很有缺陷。很有意思。让我试一个例子,看看这对我们是否有效。我们将尝试这个选项。为什么要一部分一部分地删除它?