Мы видим резкий скачок в использовании памяти при вставке большого количества данных (точнее, при совершении транзакции). Конечно, мы хотели бы избежать этого давления памяти. Вот быстрый скриншот, а более подробно ниже
- Используемая версия Realm swift: 3.11.0
- iOS: 12
- Количество данных для вставки: 200 мес., Более 270 тыс. Объектов
Плюс, у нас есть следующие требования:
- Загружаем данные с удаленного SQL Server
- Мы должны быть уверены, что все данные были правильно загружены, поскольку мы не хотим, чтобы в результате возникла ошибка в целостности нашей базы данных (пропущенные данные)
Итак, с этим мы решили следующие шаги:
- Хранение всех загруженных данных во временных отдельных файлах (на диске)
- Как только все загруженные данные завершены, мы заходим в определенную очередь операций
- Открываем транзакцию
- Открываем файл за файлом, сохраняем объекты, затем закрываем файл
- Если в процессе нет ошибок, подтвердите транзакцию
- И в этот момент мы видим всплеск памяти при совершении транзакции
Это переводится примерно так в терминах кода (упрощенно)
//We have a small helper, that is use also for other classes
static func getRealm() -> Realm {
do {
let realm = try Realm()
return realm
} catch let error as NSError {
//Log + error
}
}
// The code where the spike occurs
DispatchQueue.global(qos: .background).async {
do {
// opening transaction
RealmHelper.getRealm().beginWrite()
let filesURL = StorageHelper.retrieveFilesURL()
for fileURL in filesURL {
autoreleasepool { // to clear decoded data
//Retrieving data + Decoding objects
let objects = StorageHelper.retrieve(forURL: fileURL)
realm.add(objects.persons, update: true)
realm.add(objects.buildings, update: true)
// and so on (15 differents objects types)
}
}
RealmHelper.getRealm().commitWrite()
} catch let error as NSError {
RealmHelper.getRealm().cancelWrite()
}
}
Пока он работает, вы думаете, этот подход является лучшим? Есть ли способ уменьшить всплеск памяти? Сначала мы думали, что, сохраняя объекты по частям и пакетируя сохранение, это позволит избежать такого поведения, но это не так. И, как я уже говорил ранее, мы не можем разделить на несколько транзакций (плюс, согласно документации, это не рекомендуется для большого количества данных).