我使用
根据Xcode中的内存监视器,iPhone X上的内存使用稳定,从不超过100mb,在像iPhone 6或iPhone 6s这样的设备上,内存使用情况会不断增长,直到最终系统关闭应用程序。 我使用Instruments检查了内存泄漏,但没有报告任何泄漏。通过Allocations运行应用程序也没有显示任何问题,并且应用程序不会被系统关闭。我还发现有趣的是,在新设备上内存使用稳定,但在旧设备上却不断增长。滤镜的复杂度并不重要,因为即使使用最简单的滤镜,问题仍然存在。以下是我的金属文件示例:
I wonder什么会导致旧设备出现问题,应该向哪个方向查找。
更新1:这里有两个1分钟的图表,一个来自Xcode,另一个来自Allocations,都使用相同的过滤器。Allocations图表是稳定的,而Xcode图表始终在增长。
Metal
和 CADisplayLink
实时过滤一个 CIImage
并将其渲染到 MTKView
中。// Starting display link
displayLink = CADisplayLink(target: self, selector: #selector(applyAnimatedFilter))
displayLink.preferredFramesPerSecond = 30
displayLink.add(to: .current, forMode: .default)
@objc func applyAnimatedFilter() {
...
metalView.image = filter.applyFilter(image: ciImage)
}
根据Xcode中的内存监视器,iPhone X上的内存使用稳定,从不超过100mb,在像iPhone 6或iPhone 6s这样的设备上,内存使用情况会不断增长,直到最终系统关闭应用程序。 我使用Instruments检查了内存泄漏,但没有报告任何泄漏。通过Allocations运行应用程序也没有显示任何问题,并且应用程序不会被系统关闭。我还发现有趣的是,在新设备上内存使用稳定,但在旧设备上却不断增长。滤镜的复杂度并不重要,因为即使使用最简单的滤镜,问题仍然存在。以下是我的金属文件示例:
extern "C" { namespace coreimage {
float4 applyColorFilter(sample_t s, float red, float green, float blue) {
float4 newPixel = s.rgba;
newPixel[0] = newPixel[0] + red;
newPixel[1] = newPixel[1] + green;
newPixel[2] = newPixel[2] + blue;
return newPixel;
}
}
I wonder什么会导致旧设备出现问题,应该向哪个方向查找。
更新1:这里有两个1分钟的图表,一个来自Xcode,另一个来自Allocations,都使用相同的过滤器。Allocations图表是稳定的,而Xcode图表始终在增长。
更新2: 附上一个已按大小排序的分配列表的截图,该应用程序运行了16分钟,不停地应用过滤器:
更新3: 关于applyAnimatedFilter()
中正在发生的事情,我有更多信息:
我将一个经过滤镜处理的图像渲染到一个MTKView
中。我从filter.applyFilter(image: ciImage)
接收到经过滤镜处理的图像,接下来在Filter
类中进行处理。
func applyFilter(image: ciImage) -> CIImage {
...
var colorMix = ColorMix()
return colorMix.use(image: ciImage, time: filterTime)
}
其中filterTime
只是一个Double变量。最后,这是完整的ColorMix类:
import UIKit
class ColorMix: CIFilter {
private let kernel: CIKernel
@objc dynamic var inputImage: CIImage?
@objc dynamic var inputTime: CGFloat = 0
override init() {
let url = Bundle.main.url(forResource: "default", withExtension: "metallib")!
let data = try! Data(contentsOf: url)
kernel = try! CIKernel(functionName: "colorMix", fromMetalLibraryData: data)
super.init()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func outputImage() -> CIImage? {
guard let inputImage = inputImage else {return nil}
return kernel.apply(extent: inputImage.extent, roiCallback: {
(index, rect) in
return rect.insetBy(dx: -1, dy: -1)
}, arguments: [inputImage, CIVector(x: inputImage.extent.width, y: inputImage.extent.height), inputTime])
}
func use(image: CIImage, time: Double) -> CIImage {
var resultImage = image
// 1. Apply filter
let filter = ColorMix()
filter.setValue(resultImage, forKey: "inputImage")
filter.setValue(NSNumber(floatLiteral: time), forKey: "inputTime")
resultImage = filter.outputImage()!
return resultImage
}
}
applyAnimatedFilter
的整个内部包装在一个autoreleasepool
块中,看看是否有任何区别。 - matt