我在我的应用程序中遇到了内存问题,但我还没有找到一种方法来找出哪些对象/类正在使用该内存。
该应用程序很简单,是一个带有图片库 View 的 View Controller ( GridView 就像 Instagram Explore;带有 xib 单元格的 Collection View ),当您点击其中一个时,它会将您带到下一个屏幕,这是同一组图像,但作为垂直列表(带有 xib 单元格的 uitableview)。图像是从网络异步下载的。
当我在两个屏幕上滚动时,应用程序使用的内存不断增加,并且每次打开列表屏幕时速度也越来越快。然后,使用内存减少的唯一时刻(我的意思是急剧减少,比如从 1.8GB 到 200MB)是当它达到设备的限制时,然后问题一次又一次地出现。此外,有时系统无法减少使用的内存并且应用程序崩溃(“由于内存问题而终止的 iOS 应用程序”)。
我不认为这是布局问题,我已经检查了所有这些,还使用了内存图调试器,只发现了“malloc”问题,这让我无处可去,没有类,没有行,什么都没有。另外,Instruments 工具太复杂了,我还不知道怎么处理。
我已经阅读了一些教程并尝试了一些解决方案,但没有任何效果。其中包括:https://krakendev.io/blog/weak-and-unowned-references-in-swift , http://iosbrain.com/blog/2018/07/22/finding-memory-leaks-with-the-xcode-memory-graph-debugger-and-fixing-leaks-with-unowned/ , https://www.youtube.com/watch?v=1LnipXiSrSM&t=1697s , https://developer.apple.com/videos/play/wwdc2018/416/
有人可以给我一些关于如何正确调试内存问题以找出其确切来源的其他建议或教程吗?
最佳答案
大多数现代内存调试策略都适用于识别和解决强引用循环。但这不是你的问题。当您面临内存压力时,大部分内存都会恢复,这一事实表明存在缓存问题。无论您做什么进一步的诊断,都只能确认此行为。
要解决这个问题,请为您的缓存设置合理的限制并避免不给您控制权的缓存(例如 UIImage(named:)),问题可能会得到解决。如果没有看到图像是如何被检索的(例如确保 URLSession 的缓存是合理的)以及它们在下载后是如何被缓存的(例如第三方异步图像检索库通常给你控制缓存)。
并且,假设您(或您的第三方库)正在缓存,请确保:
在模拟器上测试您的应用,手动选择“调试”»“模拟内存警告”。这将有助于确认应用程序是否正在响应内存压力。根据您的描述,我认为我们已经知道是这种情况,但这是一个很好的诊断。
请注意,虽然我们始终希望确保我们的应用程序正确响应内存警告,但当您遇到内存警告时,可能已经太晚了(例如,应用程序可能正在进行一系列分配,并且可能在您的应用程序完成之前失败有机会对警告使用react)。在出现内存警告之前,您想尽一切努力管理缓存。
您正在缓存原始负载(包含压缩的 jpg/png Assets 的 Data 对象)而不是 UIImage 对象(一旦它们重新使用,未压缩,如果你不小心的话可能会很大),或者
如果您确实缓存了 UIImage 对象,请确保根据您的 UI 调整它们的大小。
例如 100x100 的图像在 3x 比例下将占用 120kb,但如果图像是 1000x1000px,即使 ImageView 只有 100x100pt,未压缩的图像将占用 4mb,即每个像素 4 字节,无论压缩 jpg 的大小如何/png 负载。
如果您正在使用 NSCache,请设置 countLimit或 totalCostLimit .
如果您要自己收集(数组或字典)下载的图像,请确保对内存压力做出响应。例如,在 Swift 中:
NotificationCenter.default.addObserver(forName: UIApplication.didReceiveMemoryWarningNotification, object: nil, queue: .main) { [weak self] _ in
// do whatever you need to remove your cached objects here
}
我不认为这是这里的问题(因为您的应用程序正在响应内存压力),但您可能想要检查您的应用程序是否有任何其他 (a) 大; (b) 自己下载并保存在内存中,并做出相应的响应。
FWIW,我认为你已经做了足够的诊断来确定问题的根源(它在内存压力下被清除的事实确实指向缓存问题),但如果你想学习“分配”工具仪器,查看这些旧的 WWDC 视频 Fixing memory issues和 iOS App Performance: Memory .它们很老并且专注于 Objective-C,但是如果您想加快使用 Instruments 的速度,那里概述的技术仍然适用。但是,正如我所说,我认为您已经确定了这个问题。
关于ios - 如何在简单的应用程序上调试严重的内存问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55007565/
出于纯粹的兴趣,我很好奇如何按顺序创建PI,而不是在过程结果之后生成数字,而是让数字在过程本身生成时显示。如果是这种情况,那么数字可以自行产生,我可以对以前看到的数字实现垃圾收集,从而创建一个无限系列。结果只是在Pi系列之后每秒生成一个数字。这是我通过互联网筛选的结果:这是流行的计算机友好算法,类机器算法:defarccot(x,unity)xpow=unity/xn=1sign=1sum=0loopdoterm=xpow/nbreakifterm==0sum+=sign*(xpow/n)xpow/=x*xn+=2sign=-signendsumenddefcalc_pi(digits
作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代
我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0
对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl
我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po
如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby
我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%
尝试通过RVM将RubyGems升级到版本1.8.10并出现此错误:$rvmrubygemslatestRemovingoldRubygemsfiles...Installingrubygems-1.8.10forruby-1.9.2-p180...ERROR:Errorrunning'GEM_PATH="/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/ruby-1.9.2-p180@global:/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/rub
Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack
我想用ruby编写一个小的命令行实用程序并将其作为gem分发。我知道安装后,Guard、Sass和Thor等某些gem可以从命令行自行运行。为了让gem像二进制文件一样可用,我需要在我的gemspec中指定什么。 最佳答案 Gem::Specification.newdo|s|...s.executable='name_of_executable'...endhttp://docs.rubygems.org/read/chapter/20 关于ruby-在Ruby中编写命令行实用程序