Быстрое сохранение нескольких изображений в файловую систему одновременно, высокая загрузка процессора - PullRequest
0 голосов
/ 01 мая 2019

У меня есть следующая функция, мне нужно очистить все графические столбцы в БД и перейти к файловой системе.Когда я делал все это за один раз, памяти было слишком много, и она зависала.Я переключился на рекурсивную функцию и выполняю записи и пакеты по 20.

Есть около 6 таблиц, для которых мне нужно сделать это.В моей базе данных Realm есть 2 с половиной гигабайта данных.Это переключается на 40 Мб после того, как я вызываю свои 6 рекурсивных функций, снимая изображения и сжимая Realm.

Я вижу очень высокое использование памяти, так как мои функции вызываются, и телефоны с меньшим количеством ОЗУ не смогут с этим справиться.

Как я могу освободить память и ЦП между каждой функцией?

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 IS:

Мне нужно было избавиться от слабого я в моемрасширение, потому что я проходил через охрану, позволяя пропускать несколько элементов, а нагрузки пропускались

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)
            }

        }

    }
}

EDIT :

Я изменил свой writeToURL в цикле for наследующее:

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

Это помогло с памятью, но иногда я получаю Thread1: EXC_BAD_ACCESS, указывающий на строку, попробуйте proPicData.write ...

Все еще очень сильно загружается процессор.Есть ли в любом случае, чтобы очистить использование процессора между каждым вызовом функции?

1 Ответ

0 голосов
/ 01 мая 2019

Вы извлекаете все объекты из вашего Realm одновременно, это то, что использует так много памяти

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

Запись в файлы - это не то, что расходует память, хотя это может быть связано с использованием процессора.

Я бы порекомендовал поставить limit для выборки категорий, чтобы вы не загружали все категории и их изображения в память. В противном случае попробуйте найти предикат выборки, который в противном случае разумным образом ограничил бы данные.

...