locked
Why is PathIO faster than FileIO ? RRS feed

  • Question

  • In my app I read 30 tiny files (each file is about 1 KB in size).

    On a Surface RT, this operation takes 470 ms (half a second!) if I use FileIO.ReadBufferAsync:

    IBuffer buffer = await FileIO.ReadBufferAsync(stfile);

    However, if I replace the above line by this:

    IBuffer buffer = await PathIO.ReadBufferAsync(stfile.Path);

    it "only" takes 120 ms.

    First question: Why is PathIO.ReadBufferAsync so much faster than FileIO.ReadBufferAsync?

    Second question: Anyway, why is reading in WinRT so extremely slow? (reading 30 files of 1 KB size takes 5 ms in a desktop application and not 120 or 470)


    • Edited by eikuh Monday, April 22, 2013 9:30 AM
    Monday, April 22, 2013 9:29 AM

Answers

  • PathIO is significantly simpler and more limited than FileIO: PathIO works in-proc only on files which the app has permission to read directly (see File access and permissions in Windows Store apps). FileIO works out-of-proc with a broker process to read files which the app has only indirect access to (e.g. via file pickers, capabilities, etc.)

    You'll get the same speeds in a desktop app as in a Windows Store app if you're doing the same thing. There is some overhead for the async process. It won't be significant for large files, but can be for small ones.

    If you are calling this in a background thread or if you know you have very small (and therefore quick) files you can p-invoke the allowed Win32 file system API. This isn't recommended for the general case though (potentially large files on the UI thread) since hanging the UI thread is one of the most unfriendly things you can do to your users.

    --Rob

    • Marked as answer by eikuh Monday, April 22, 2013 5:23 PM
    Monday, April 22, 2013 4:21 PM
    Moderator

All replies

  • Do you really want to know why or do you want a fix for this?  Asking why isn't really a fruitful thing unless you can act on that knowledge.  We can't fix any bugs on the forums, just report them.  If you really want to fix this, you can open a support case using one of the support incident you get with your Windows Store account and we can file for a hotfix which hopefully will be accepted.

    Matt Small - Microsoft Escalation Engineer - Forum Moderator
    If my reply answers your question, please mark this post as answered.

    NOTE: If I ask for code, please provide something that I can drop directly into a project and run (including XAML), or an actual application project. I'm trying to help a lot of people, so I don't have time to figure out weird snippets with undefined objects and unknown namespaces.


    Monday, April 22, 2013 2:54 PM
    Moderator
  • I would like to know the 'why' of what's going on here (links are ok).  Slow IO performance seems to be a common theme within many of my WinRT applications.  To me this doesn't make a whole lot of sense as the hardware targets and underlying architecture for WinRT is standardized, and thus hopefully optimized (unlike for example silverlight, or other cross platform libs).

    Those two functions in particular seem like they should be doing the same thing.  Also interesting is how much faster .Net 4.5 is doing the equivalent operations.

    Is the difference overhead with the Tasking / await paradigm when applied to a sequential file read?  

    Monday, April 22, 2013 3:14 PM
  • Kellen - please open a support case and we'll work on it.  You can likely imagine, getting to the root of a fundamental issue such as slow IO performance isn't as simple as telling someone how to change the offset of a scrollviewer. It requires in-depth research and talking with the stakeholders who work on these functions who can tell you why.  That's quite a bit beyond the scope of this forum.

    Matt Small - Microsoft Escalation Engineer - Forum Moderator
    If my reply answers your question, please mark this post as answered.

    NOTE: If I ask for code, please provide something that I can drop directly into a project and run (including XAML), or an actual application project. I'm trying to help a lot of people, so I don't have time to figure out weird snippets with undefined objects and unknown namespaces.

    Monday, April 22, 2013 3:34 PM
    Moderator
  • I really wanted to know why. I could image that it has something to do with the sandboxing etc. And maybe FileIO is more general. I have never read that this forum is only for the questions like "how do I change the color of the button?".

    Anyway: I have found functions that are really fast:

      [DllImport("kernel32.dll", SetLastError = true)]
            static extern bool ReadFile(
                IntPtr hFile, 
                [Out] byte[] lpBuffer,
                uint nNumberOfBytesToRead, 
                out uint lpNumberOfBytesRead, 
                IntPtr lpOverlapped
                );
    
    
            [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
            static extern IntPtr CreateFile2(
                string lpFileName,
                uint dwDesiredAccess,
                uint dwShareMode,
                uint dwCreationDisposition,
                IntPtr pCreateExParams
                );
    
    
            [DllImport("kernel32.dll", SetLastError = true)]
            static extern bool CloseHandle(
                IntPtr hObject
                );

    P/Invoke is our friend, Kellen!

    My app is now 30 times faster! Only 15 ms instead of 470!

    Monday, April 22, 2013 3:53 PM
  • You are correct, but there's only so much troubleshooting that *I* can do as part of a forum post response.  Some questions require more research than others.  If others have the answer and are willing to give them, well, that's what forums are about.

    Matt Small - Microsoft Escalation Engineer - Forum Moderator
    If my reply answers your question, please mark this post as answered.

    NOTE: If I ask for code, please provide something that I can drop directly into a project and run (including XAML), or an actual application project. I'm trying to help a lot of people, so I don't have time to figure out weird snippets with undefined objects and unknown namespaces.


    Monday, April 22, 2013 4:14 PM
    Moderator
  • PathIO is significantly simpler and more limited than FileIO: PathIO works in-proc only on files which the app has permission to read directly (see File access and permissions in Windows Store apps). FileIO works out-of-proc with a broker process to read files which the app has only indirect access to (e.g. via file pickers, capabilities, etc.)

    You'll get the same speeds in a desktop app as in a Windows Store app if you're doing the same thing. There is some overhead for the async process. It won't be significant for large files, but can be for small ones.

    If you are calling this in a background thread or if you know you have very small (and therefore quick) files you can p-invoke the allowed Win32 file system API. This isn't recommended for the general case though (potentially large files on the UI thread) since hanging the UI thread is one of the most unfriendly things you can do to your users.

    --Rob

    • Marked as answer by eikuh Monday, April 22, 2013 5:23 PM
    Monday, April 22, 2013 4:21 PM
    Moderator
  • Wow, thank you, Rob! This explains a lot!
    So, when reading and writing files to the LocalFolder of the App, one should never use FileIO because PathIO (in this case) can do the same but faster. And if PathIO is still too slow, use the Win32 API.

    The only sad thing is that one has to choose between easy-to-use and fast.

    I think it is because Microsoft thought: If we give easy-to-use synchronous IO functions to the developers, they will always use the synchronous over the asynchronous.

    Monday, April 22, 2013 4:48 PM