The CTR system supports access priority for the file system. When multiple threads are accessing multiple files, it coordinates the order of execution, giving precedence to the thread configured with the highest priority.
You can also minimize the latency of file access by configuring real-time priority. This is good when real-time performance is needed (when you need to perform a specific amount of processing every set period), such as for streaming playback.
Three access priorities can be set. They are as follows, from highest to lowest.
nn::fs::PRIORITY_APP_REALTIME)nn::fs::PRIORITY_APP_NORMAL)nn::fs::PRIORITY_APP_LOW)Use normal priority for general file access, such as loading model data and scene data, and accessing save data. Low priority is lower than normal priority. Use low priority for file access that can wait for execution until file access is at a relatively low level, such as auto-save. Real-time priority is a special priority level. Use it when delays in file access would impact the user experience, such as loading streaming data. However, there are some limitations on the use of real-time priority.
Consider the access priority for the following:
You can set the access priority for these by calling the corresponding SetPriority functions.
When calling these functions, pass as a parameter one of the constants specified in the nn::fs::PriorityForApplication enumerated type: nn::fs::PRIORITY_APP_REALTIME, nn::fs::PRIORITY_APP_NORMAL, or nn::fs::PRIORITY_APP_LOW. No values other than these constants can be specified.
Use the nn::fs::SetPriority function to set the priority for the entire file system.
The priority settings configured here impact the following:
fs functions that do not take a path name (such as the various mount functions, and the nn::fs::FormatSaveData and nn::fs::CreateExtSaveData functions).
The file system overall has the "normal" priority set by default.
Use the nn::fs::SetArchivePriority function to set the priority for individual archives. If this function is not used to explicitly set the priority of an archive, the priority of the file system as a whole is applied when it is mounted. (Changing the priority of the file system as a whole after the archive is mounted will not change the priority of the archive.)
The priority settings configured here impact the following:
nn::fs::CommitSaveData function).
You can set the access priority of file-stream and directory objects using the [Try]SetPriority member functions of the FileStream, FileInputStream, FileOutputStream, and Directory classes. If none of these functions is used to explicitly set the priority of an object, then the priority of its parent archive is applied when it is initialized. (Changing the priority of the parent archive after the object is initialized does not change the priority of the object.) The priority set here impacts the execution priority of all member functions of the object.
If you initialize another stream object using the same file path, the priority settings are handled separately. To read the same file using different priorities for separate uses, open the file multiple times and set a separate priority for each object.
Some file access requires real-time performance, such as the streaming playback of sound and movies. Although real-time priority should be used for such file access, there are many limitations to take note of.
The system completes file accesses with real-time priority as soon as possible. When the file-access load is heavy, the system gives highest priority to access having real-time priority. It will suspend any previously requested file accesses having lower priority, and give precedence to the file access having real-time priority. (Normal-priority access may also sometimes temporarily suspend low-priority access.) The system will not begin processing requests for file access having lower priority while it is processing a file access operation having real-time priority. (The system handles the suspension of processing and other actions automatically. There is no need to account for this in the program code.)
Use real-time priority only for operations, such as streaming, that require real-time performance. Excessive access with real-time priority (more than about 1 MB/s on average) could lower the performance of the system as a whole. Use normal or low priority for file access if a certain level of latency is tolerable, such as when there is a temporary fade to black or a loading screen. One example is when switching scenes.
If you access two or more files at the same time with real-time priority, the process itself will succeed, but it will not be possible to predict performance, because the accesses will interfere with each other.
Only access one file at a time with real-time priority. For example, if you stream a movie and sound while reading them from separate files, do not read them from two threads at the same time. Instead, read them alternately (in a single thread, or in two threads using mutual exclusion).
Priorities other than real time (normal and low) are general and do not represent absolute priority settings. It is possible that a low-priority file access will be executed even if a request for a normal-priority file access is being processed. When the file-access load is extremely heavy, access using normal priority may take considerable time.
Use real-time priority if you need file access to complete within a specific time.
The time required for file access is generally calculated as follows:
Ordinarily, the overhead is relatively low when access has real-time priority, or when using a priority other than real time and there are no other accesses. As an example, the overhead for reading a ROM file of a card application is only about 10 ms or less on average.
But because of the way the system is designed, on rare occasions the overhead time can be significant. To avoid unnecessary issues in your software, use real-time priority when you need real-time performance (such as streaming playback), and allow for worst-case overhead times.
Do not use measured performance data as the basis of your performance specifications for file loading that requires real-time responsiveness.
The list below provides a rule of thumb for overheads and speed (excluding overhead) for each archive type. Use these values to determine the buffer size and read period for streaming playback.
Note: Do not perform processing requiring real-time performance using archive types other than those listed above. Types other than those listed above may have unexpected overhead, even when using real-time priority.
The values above may change in a future firmware update.
Note: The values above represent the generally expected worst cases. They are not actual measurements. The average measured speeds are faster than those listed. It is fine to design performance using the values listed in the performance tips or other documentation, or using your own performance measurements, if your file access does not require real-time performance (if occasional slowdowns do not present a problem). One such example is loading scenes.
For example, assume that you must periodically read a movie file with a bitrate of 1 Mbps (128 KB/s) from a ROM file for card-based software. Assuming a buffer size of 32 KB, it will take about 207 ms to read one buffer's worth of data (200 ms + 32 KB ÷ 5 MB/s). Since you only need to make four reads per second (128 KB ÷ 32 KB), it will take 207 ms × 4, which equals 828 ms. You will thus be able to fit all the required reads within one second. If the bitrate is three times higher (3 Mbps, or 384 KB/s), then you would need to make 12 reads of a 32 KB buffer per second, which increases the calculation to greater than 2 seconds. It therefore would not be possible to read all of the data in 1 second.
If you quadruple the size of the buffer to 128 KB, it takes 226 milliseconds to read one buffer's worth of data, and all necessary data is read in one second using three read operations. The total time is then 678 milliseconds, which is less than 1 second.
The figures refer to the performance of accessing the file system. To estimate actual performance, you must separately estimate the time for any other processing, such as decoding video and audio. File access generally does not take up a great deal of CPU resources. So as long as you can stay within the figures above, you should be able to avoid most issues using, for example, double buffering for loading and processing. However, you must fully verify overall performance, even if your requirements fit within the range of file-access performance.
File-access priority specifies the priority of file-related access processed by the system. It does not regulate the priority of user threads that call fs functions. Even if you specify high priority for file access, if the priority of the thread that calls the fs function is low, then it may take a long time for the thread to issue the processing request to the system, and the end of the process could then be delayed. The priority of the thread calling the fs function must therefore be high enough for the purpose of the process.For example, if you are loading a file for audio streaming, before calling the fs functions, set the access priority to real-time and set the priority of the thread to roughly that of the sound-processing thread.
If there are multiple file accesses at the same time, the order of file accesses is not guaranteed, even if real-time priority is used. When possible, the system will process multiple file accesses in parallel. Consequently, it is possible for a low-priority file access that was started after a high-priority file access to finish before the high-priority one. If you will be performing multiple file accesses in parallel, ensure that your implementation does not depend on the order in which they finish.
Because the throughput and latency performance of SD Cards can vary greatly by manufacturer and model number, you must have performance specifications that allow for this variation when accessing SD Cards.
Although the access performance figures for SD Card data listed in Estimating File Access Time are extremely conservative, use these values when determining the performance specifications for accessing data on an SD Card when real-time performance is required.
Because the SD Cards that come with the system have relatively low overhead time, problems may arise, depending on the SD Card type, if performance specifications are based on these figures. Do not set performance specifications for file loading that requires real-time responsiveness based on measured performance data.
CONFIDENTIAL