一次快速将多个图像保存到文件系统,高CPU

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一次快速将多个图像保存到文件系统,高CPU相关的知识,希望对你有一定的参考价值。

我有以下功能,我需要清除数据库中的所有图片列并移动到文件系统。当我一次性完成这一切时,内存太多而且会崩溃。我切换到递归函数并执行20次写入和批处理。

我需要大约6个表来执行此操作。我的Realm DB中有2个半的数据。在我调用我的6个递归函数,将图像输出并压缩Realm后,这将切换到40mb。

我可以看到非常高的内存使用量,因为我的函数被调用,而具有较少RAM的手机将无法处理它。

如何在每个功能之间释放内存和CPU?

public static func clearEqCatPics(){

        let docsDir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
        let eqcatPicDir = docsDir.appendingPathComponent(util_Constants.DIR_EQCAT_PICS)

        do {
            var realm : Realm? = try Realm()
            let predicate = NSPredicate(format: "icon != %@", "")
            let categories = realm!.objects(STD_EQ_category.self).filter(predicate).sorted( by: [SortDescriptor(keyPath: "displayorder", ascending: true), SortDescriptor(keyPath: "_id", ascending: true)] )

            if (categories.count > 0)
            {
                realm?.beginWrite()
                let upper = categories.count > 20 ? 20 : categories.count

                var actualCounter = upper
                for i in 0..<upper{
                    autoreleasepool{
                        if let proPicData = Data(base64Encoded: categories[actualCounter - 1].icon, options: .ignoreUnknownCharacters) {


                            let filename = eqcatPicDir.appendingPathComponent(categories[actualCounter - 1]._id.description+".jpg")

                            (proPicData as NSData).writeToURL2(named: filename, completion: { (result, url) -> Void in

                            })

                            categories[actualCounter - 1].icon = ""

                        }
                        else{
                            categories[actualCounter - 1].icon = ""
                        }
                    }

                    actualCounter = actualCounter - 1

                }

                try realm?.commitWrite()
                let eqcatNew = realm!.objects(STD_EQ_category.self).filter(predicate)
                print("$$$$$$$$$$$$$$$$$$$$ 2. eqcatNew COUNT : \(eqcatNew.count) $$$$$$$$$$$$$$$$$$$$")
                realm = nil
                if eqcatNew.count > 0 {
                    clearEqCatPics()
                }
            }
            realm = nil
        }
        catch let error as NSError {
            print("error realm \(error.localizedDescription)")

        }

    }

其中writeToURL2是:

我需要摆脱我的扩展中的弱自我,因为我越过了防守让多个项目和负载被跳过

extension NSData {

    func writeToURL2(named:URL, completion: @escaping (_ result: Bool, _ url:NSURL?) -> Void)  {


        let tmpURL = named as NSURL

        //[weak self]
        DispatchQueue.global(qos: .background).async {  () -> Void in

            //guard let strongSelf = self else { print("self was weak"); completion (false, tmpURL); return }

            self.write(to: tmpURL as URL, atomically: true)
            var error:NSError?
            if tmpURL.checkResourceIsReachableAndReturnError(&error) {
                print("We have it")
                completion(true, tmpURL)
            } else {
                print("We Don't have it\(error?.localizedDescription)")
                completion (false, tmpURL)
            }

        }

    }
}

编辑:

我将for循环中的writeToURL更改为以下内容:

do {
     try proPicData.write(to: filename, options: [.atomic])                               
}
catch let err as NSError{
     print("err : \(err.localizedDescription)")
}

它有助于内存,但有时我得到Thread1:EXC_BAD_ACCESS指向行试试proPicData.write ...

CPU使用率仍然很高。有没有在每个函数调用之间清除CPU使用情况?

答案

你正在同时获取Realm中的所有对象,这就是耗费大量内存的东西

let categories = realm!.objects(STD_EQ_category.self).filter(predicate).sorted( by: [SortDescriptor(keyPath: "displayorder", ascending: true), SortDescriptor(keyPath: "_id", ascending: true)] )

写入文件不是用尽内存,尽管这可能与CPU使用率有关。

我建议在获取类别上添加limit,这样就不会将所有类别及其图像加载到内存中。否则,尝试提出一个获取谓词,否则将以合理的方式限制数据。

以上是关于一次快速将多个图像保存到文件系统,高CPU的主要内容,如果未能解决你的问题,请参考以下文章

如何一次将多个 csv 文件读取到 Google Colab

将多个图像从asp.net中的文件夹保存到本地

将图像保存到文件系统

如何解决kswapd0高CPU占用问题

使用 mvc3 将图像保存到文件系统

CPU使用率高时OpenCV会堆积内存吗?