UIDocument & NSFileWrapper Architecture and Performance

We recently converted our code to use UIDocument, rather than directly manipulating files on the file system, and as a result we ran into some performance issues. We are wondering if we are using this class incorrectly if someone had these problems, and what are the common ways to fix them.

Our app

We have a โ€œshoe appโ€ that manages a bunch of documents, each of which consists of several image files that can be quite heavy, a small metadata file and a small preview image. A user can have many documents on his device (1000+ documents). Each document file is grouped into a directory, and we use NSFileWrapper for reading and writing.

When our application starts, it needs the metadata of all documents to show the document index and a subset of the preview images. Additional preview images are loaded as the user scrolls.

To get this information, we will open all the documents, read their metadata and the preview image, if necessary, close them, and then open them again on demand.

Problem # 1: Slow boot time

It takes a long time to open all documents and read their metadata. I think there are several factors contributing to this problem: - Each document opening action is relatively slow - Open document blocks and completion blocks are executed in one queue, which makes it very difficult to delay the operation (my document is open, but the completion block should wait for X open document blocks before its launch)

We decided to solve this problem with a separate index file, but this approach has the disadvantage that we will need to manage metadata in two places and that we will need to synchronize it with the file system in case iCloud modifies files.

Problem # 2: Threading

Each open document creates its own "File Access Thread". When we open many documents at the same time, overhead depresses the application.

We solved this problem by synchronizing open operations using a semaphore. This approach has the disadvantage that it slows down loading even more.

Questions

  • Is there any fundamental problem with the way we use UIDocument? If not:
  • Has anyone encountered a similar boot time issue? What is the general way to solve it? Do other applications have an index file?
  • Is there a way to force a UI document to use a thread pool? If not, how do you control the use of resources?

Thanks!

+7
performance multithreading ios uidocument
source share
3 answers

Well, there is no good news.

We tried to consult with friends in the industry, profile UIDocument and use modified implementations that change various aspects of its work to see if we can improve its performance, but to no avail.

My conclusion is that UIDocument is not suitable for such use - it is simply not designed to support the latency and throughput requirements that we have for open operations. UIDocument should only be used when you want to open a small number of files at any time (like word processors and drawing applications). Admittedly, this is exactly what the Apple documentation says, but I think we needed to find out how serious they were in a difficult way.

As a result, we used some "tricks" to improve the user interface, and as soon as possible we will get away from UIDocument.

So my recommendation is that only if:

  • Your application is similar to a document-based application in nature, that is, you will not have more than a few documents open at any time
  • You do not need the information inside the documents to โ€œdiscoverโ€ them and show them to the user, or you can afford the overhead of managing a separate index file.
  • You really need the auto save / cancel / sync / iCloud features of this class.

then use it. Otherwise, consider other solutions.

A side of the note, which is not directly related to the question, but I will add here as a public service: the asynchronous UIDocument model required major changes in the application architecture when we switched from direct file access. If you plan to take this step, evaluate the work that you will need to do carefully.

Good luck to future programmers.

+5
source share

Document classes have methods for reading asynchronously. Have you tried this?

0
source share

It really looks like it is more suitable for Core Data or SQLite for metadata. At the very least, cache metadata in Core Data (a single repository for the entire application, not one per document).

0
source share

All Articles