I'm struggling with memory management in iOS while downloading relatively large files from the web (such as videos with 350MB size).
The goal here is to download these kind of files and store it on CoreData on a Binary Data field.
At the moment I'm using NSURLSession.dataTaskWithUrl and NSURLSession.dataTaskWithRequest methods to retrieve these files, but it looks like these methods don't treat problems such as memory usage, they just keep on filling the memory until it reaches its maximum usage, leaving me with a memory warning when I reach 380MB~.
Initial Memory Usage
Memory Warning
What's the best strategy to perform this kind of large data retrieval from the web without reaching a memory warning? Does AlamoFire and other libs can deal with this problem?
It is better to use download task.
And save the video as a file to Document or Library directory.
Then save the relative path to CoreData
If you use download task
You can resume if last download fail
Need less memory
You can try AFNetworking to download large files.
Related
From current list of "Realm Limitations":
Any single Realm file cannot be larger than the amount of memory your
application would be allowed to map in iOS
Does this mean that if I check ProcessInfo.processInfo.physicalMemory and it is smaller than FileManager.default.attributesOfItem(atPath:realmPath)[FileAttributeKey.size] (plus a variable amount to account for fragmentation etc), I should not try to open the Realm?
If the Realm file is too big for mmap to map the file, you should get a Swift error. So all you really need to do is to try opening the Realm and catch any Realm.Error.addressSpaceExhausted errors.
The bigger problem is what to do once you know the file is too big. Our compaction on launch feature requires that the file be openable first, which rules it out (and is why we recommend that compact on launch be used to pre-empt this issue). We're working on ways to mitigate this problem.
mmap shouldn't depend upon the amount of free physical RAM you have (although some amount of RAM is required to map the file), nor is the limit that iOS imposes anywhere near the theoretical maximum. Finally, virtual memory limits operate on a per-process basis, meaning that the size of a Realm file you can open depends both on what other files have been mapped by that process and by how much memory that process is using for other things.
I'm wondering how costly are I/O operations in iOS.
Let's assume I have application that download images from urls and store it in device memory.
Downloading of course is made asynchronously, but I'm wondering about storing data in device memory and about receiving it from memory.
There are a lot of small images (thumbnails), but I'm also store big images (1-2 MB).
Should I make write and read operation asynchronously on background thread, or it will not have that much impact to performance if i make it on main thread.
Since you are already downloading the images asynchronously, it isn't much more difficult for you to also store them asynchronously. And I would say it is a best practice, because it has nothing to do with UI stuff so it shouldn't be on the main thread.
Check out this doc from Apple. They do not specifically say that storing files should be done on a background thread, however they acknowledge that it can be a pretty costly operation when you have a lot of files (and more so when we're talking about images...)
If your app works with a lot of files, the performance of its
file-related code is very important. Relative to other types of
operations, accessing files on disk is one of the slowest operations a
computer can perform. Depending on the size and number of files, it
can take anywhere from a few milliseconds to several minutes to read
files from a disk-based hard drive.
They also give you lots of nice tips to reduce I/O operations - like reusing the NSURL objects - that you can easily adopt in your coding.
In my app I am getting low memory warning after few files download.I stops current download process. Even after that also app crashes and I am assuming that app crashes due to low memory issue. Can any one please let me know how can I free up memory in running app.
It sounds like you're downloading the files straight to memory. That will be an issue because you wont have enough memory to download the entire file.
The strategy you need to take is, as you download the file continue to write chunks of it out to disk, freeing up memory in doing so.
If you are using NSURLSession there is a parameter you can use to do this for you with little effort. Please post your code for in depth help.
This is a rather simple question, but I haven't been able to pinpoint a clear answer in my searching.
If I have an NSArray, and add fifty 1MB UIImages to it, where does that 50MB get deducted from? Will the app be using 50MB more memory? Will it simply store it on the disk?
The same goes for Core Data where instead of using a persistent store I store it in memory. Would the size of the Core Data store take up exactly that much memory/RAM or would it live on the disk and be wiped when the app finishes executing?
I'm concerned whether or not I should be storing several dozen megabytes in UIImages in an NSArray, or if I should be using NSCache (I'd rather not as I'd prefer to never lose any of the images).
If I have an NSArray, and add fifty 1MB UIImages to it, where does
that 50MB get deducted from? Will the app be using 50MB more memory?
Yes.
Will it simply store it on the disk?
No. Arrays are stored in memory.
The same goes for Core Data where instead of using a persistent store
I store it in memory. Would the size of the Core Data store take up
exactly that much memory/RAM or would it live on the disk and be wiped
when the app finishes executing?
Yes, if you tell Core Data to story everything in memory, that's exactly what it'll do.
The line between "memory" and "disk" can get a little fuzzy if you consider that virtual memory systems can swap pages of real memory out to disk and read them back when they're needed. That's not an issue for iOS, however, as iOS doesn't provide a VM backing store and writeable memory is never swapped out.
I'm concerned whether or not I should be storing several dozen
megabytes in UIImages in an NSArray, or if I should be using NSCache
Those aren't your only options, of course. You could store the images in files and read them in as needed. You should be thoughtful about the way your app uses both memory and disk space, of course, but you also need to consider network use, battery use, and performance. Storing data on disk is often preferable to downloading it again because downloading takes time, may impact the user's data plan, and uses a lot more energy than just reading data from secondary storage.
I have got an iPhone application where I archive permanent data in the documents folder of the application (arrays, dictionaries). I read/write from and to the documents folder quite frequently and I would like to know whether this is considered a bad habit. Wouldn't it be better if I had a singleton class, read and write to arrays there and then, only when the application quits, write this data to the documents folder ? I do not see/feel any performance issues right now on my iPhone 5, but I wanted to know whether this is a bad practise.
FLASH memory has limited write capability - a long time ago it was rated in some increment of thousands. Not sure where it is today.
That said, if your app is using the standard file system APIs, then the system is using the file cache, and you might open a file, read it then change it many times without the file system ever writing to flash. The system may sync to flash occasionally, but that process is opaque - no way to really know when or why iOS does it.
The UNIX APIs allow for syncing the file system cache to the storage system (iOS this is FLASH), but if you are not using that then you are probably not doing much I/O at all given what you say above.
Given the lack of Apple discouraging developers from writing to the file system, I for sure would not worry about this.
But, if you said you were writing gigabytes of image data every few minutes - well - that might be a problem.