我在应用程序中遇到了内存问题,我已经能够将其分解为 NSCalendar。
像这样一个简单的 View Controller :
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
while Calendar.current.component(.year, from: Date()) > 0
{
// why does the memory keep increasing?
}
}
}
似乎会导致内存泄漏。
这个例子显然会阻塞 UI 线程,但它不应该导致内存不断增加,或者至少在循环完成后被释放。好吧,至少根据我的理解,它不应该。我在这里误解了一些基本的东西吗?或者这是一个错误?
我该如何解决这个问题?
引自评论:
FYI - your issue has nothing to do with NSCalendar. Your issue is your while loop never allowing memory to be cleaned up
All of those Date instances are taking up memory too
好吧,但是如果我运行一个只有日期比较的循环,我就不会遇到同样的问题。这是因为优化器介入了吗?
while Date() > Date(timeIntervalSince1970: 200)
{
// no increase of memory here
}
最佳答案
正如其他人所指出的,问题在于 Calendar.current.component(_:from:) 在幕后引入了一个自动释放对象,该对象直到自动释放池被排空。
在引用计数 Objective-C 代码的早期,返回一个新分配的对象的常见方法是返回一个“autorelease”对象,该对象将在调用者完成使用后自动释放。这是一个只有当你回到运行循环时才会被释放的对象,这会耗尽 autorelease pool。 .您可以通过添加自己的手动自动释放池来控制重复创建自动释放对象的大循环的高水位线。
Swift 本身不会创建自动释放对象,因此这个问题有点像 Objective-C 的时代错误,我们在自己的 Swift 代码中通常不会遇到这种情况。但是,每当编写循环代码并调用可能在幕后使用自动释放对象的 Cocoa API 时,我们都必须对此保持敏感,例如在本例中。
在我深入研究解决方案之前,我将调整您的示例以确保最终退出。例如,让我们编写一个例程,该例程一直旋转直到与当前时间关联的 minute 发生变化(例如,当前分钟结束和下一分钟开始时)。我们假设 previousValue 包含当前的 minute 值。
诀窍是我们需要把autoreleasepool 在 循环中。在下面的示例中,我们利用了 autoreleasepool 是通用的这一事实,它返回其闭包内返回的任何内容:
while autoreleasepool(invoking: { Calendar.current.component(.minute, from: Date()) }) == previousValue {
// do something
}
请注意,如果您发现该模式难以阅读(需要一段时间才能习惯将闭包作为方法的参数),您可以使用 repeat-until循环,以完成大致相同的事情:
var minute: Int!
repeat {
minute = autoreleasepool {
Calendar.current.component(.minute, from: Date())
}
// do something
} while minute == previousValue
顺便说一句,这种让循环像这样快速旋转的过程效率非常低。当然,正如您提到的,您永远不会在主线程上执行此操作(因为我们永远不想阻塞主线程)。但是您通常不会在任何 线程上执行此操作,因为旋转的计算量非常大。有时你必须这样做(例如,无论如何在后台线程上做一些复杂的计算并且你希望它在某个特定时间停止),但十有八九是设计中更深层次问题的代码味道。通常明智地使用定时器等可以实现预期的效果,而无需计算开销。
很难就您的情况向您提供最佳解决方案建议,因为我们不知道您要解决的更广泛问题是什么。但请注意,在线程上自旋通常是不可取的。
你问:
Well but if I run a loop with just a date comparison im not running into the same issue. Is this because the optimiser steps in?
不,这仅仅是因为 Date() 根本没有像 Calendar.current.component(_:from:) 那样引入任何自动释放对象。 (顺便说一句,Apple 擅长在整个代码库中慢慢删除自动释放对象,因此您可能会在未来的某个时候发现,即使这可能不需要手动自动释放池。)
关于ios - Swift Calendar.current 内存泄漏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52047297/
作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代
这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下
ruby如何管理内存。例如:如果我们在执行过程中采用C程序,则以下是内存模型。类似于这个ruby如何处理内存。C:__________________|||stack|||------------------||||------------------|||||Heap|||||__________________|||data|__________________|text|__________________Ruby:? 最佳答案 Ruby中没有“内存”这样的东西。Class#allocate分配一个对象并返回该对象。这就是程序
我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的
1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里
你好,我无法成功如何在散列中删除key后释放内存。当我从哈希中删除键时,内存不会释放,也不会在手动调用GC.start后释放。当从Hash中删除键并且这些对象在某处泄漏时,这是预期的行为还是GC不释放内存?如何在Ruby中删除Hash中的键并在内存中取消分配它?例子:irb(main):001:0>`ps-orss=-p#{Process.pid}`.to_i=>4748irb(main):002:0>a={}=>{}irb(main):003:0>1000000.times{|i|a[i]="test#{i}"}=>1000000irb(main):004:0>`ps-orss=-p
print"Enteryourpassword:"pass=STDIN.noecho(&:gets)puts"Yourpasswordis#{pass}!"输出:Enteryourpassword:input.rb:2:in`':undefinedmethod`noecho'for#>(NoMethodError) 最佳答案 一开始require'io/console'后来的Ruby1.9.3 关于ruby-为什么不能使用类IO的实例方法noecho?,我们在StackOverflow上
这会导致Ruby出现内存问题吗?我知道如果大小超过10KB,Open-URI会写入TempFile。但是HTTParty会在写入TempFile之前尝试将整个PDF保存到内存吗?src=Tempfile.new("file.pdf")src.binmodesrc.writeHTTParty.get("large_file.pdf").parsed_response 最佳答案 您可以使用Net::HTTP。参见thedocumentation(特别是标题为“流媒体响应机构”的部分)。这是文档中的示例:uri=URI('http://e
我不想显示表单,但前提是当前页面不是主页这是我目前所拥有的...我有我的路线设置:root'projects#index'我的看法:'projects',:action=>'index'))%>showsomestuff如果url是localhost:3000/projects,则不会显示但是它显示了它的localhost:3000所以我需要以某种方式确保它不会显示主页。另外,我有主页的搜索参数,但我仍然不想显示它是否像localhost:3000/projects?search=blahblahblah 最佳答案 使用root_p
在部署在heroku上的Rails应用程序(v:3.1)中,我在内存中获得了更多具有相同ID的对象。我的heroku控制台日志:>>Project.find_all_by_id(92).size=>2>>ActiveRecord::Base.connection.execute('select*fromprojectswhereid=92').to_a.size=>1这怎么可能?可能是什么问题? 最佳答案 解决方案根据您的SQL查询,您的数据库中显然没有重复条目。也许您的类项目中的size或length方法已被覆盖。我试过find_