Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fast Thumbnails Loading #7

Closed
BrightShadow opened this issue Aug 3, 2018 · 9 comments
Closed

Fast Thumbnails Loading #7

BrightShadow opened this issue Aug 3, 2018 · 9 comments

Comments

@BrightShadow
Copy link

Hi there!
Before I ask, the effort spent on that library is incredible, I respect it a lot.

I'm creating a photo explorer for MTP devices. The explorer must show image thumbnails as fast as possible. Currently I'm facing the biggest problem with performance. I'm trying to load images in explorer as fast as possible, but min time to get usable files tream is 70ms - 140ms. You can imagine that when loading e.g. 25 images it takes about 2.5s. It is a lot, when you have thousands of pictures on mobile phone, and you want to browse images. My target would be Windows Explorer loading performance. I cannot get, how they did it?

I wonder if this delay is because of .NET wrapper? C++ solutions are much faster, e.g. I saw pictures browser written in Qt where thumbnail were loaded as fast as in win. explorer.

I was checking you code, I see some small improvements, to skip some wrapping code of getting children objects without wrapping them up in Item etc. But I doubt it will help...

Did you have maybe similar situation, or have you some ideas how to load thumbnails of images AFAP?

Any help is welcome!

PS: You can close this issue if it breaks you issue statistics... It is not a bug or problem. Just another use case.

All best,
Paul

@Bassman2
Copy link
Owner

Bassman2 commented Sep 3, 2018

Hi Paul, In my experience, the first access to a device is the problem, because here everything is probably loaded into the cache. With further accesses it is much faster. This behavior is due to the internal Windows MTP implementation and has nothing to do with my API. You may be able to get an initial access to your app on startup so it will not be noticed.
Thanks Ralf

@BrightShadow
Copy link
Author

BrightShadow commented Sep 13, 2018

@Bassman2 thanks for hint. I didn't think about it in that way.
I see that the problem is not only for the first time. After I even enumerate all dircetories and files I have still quite long time stream loading. I know that there are libraries, that read only some part of files - e.g. some bytes to make loading faster but I found it not possible on MTP. Your solution use same approach as Microsoft proposes - with StreamWrapper. And that's the problem. I cannot transfer only some parts of file but only full stream. So that takes time.

But how Microsoft achieved it in Windows Explorer? They are generating thumbnails so fast. I saw also some C++/Qt implementations of browsers that have nearly the same loading speed as Microsoft Windows Explorer. And this is great unknown for me. I can just suppose, that the case can be in some wrappers implementations written by Microsoft as COM libraries (probably still in C++), for Qt/C++ there is e.g. mtplib library that is not based on Microsoft shell. And maybe that's the case... Maybe writing .NET wrapper for mtplib is the right way 😄

I will also try to run many processes in parallel that will read from device. One will enumerate files, but another e.g. 5 processes will read images. Maybe that can help to simulate parallel read. I think that parallel reading from separate processes of different MTP objects can be possible 🤔 ...

Nevertheless thanks!
Paul

@anothertal3
Copy link

@BrightShadow I'm also using Bassman's great library and I also stumbled about performance issues due to MTP restrictions. As far as I know it's not possible to process multiple accesses in parallel (such as copying to the target and reading).

However, if you've managed to find any possible performance improvements I'd appreciate your input very much!

@BrightShadow
Copy link
Author

@anothertal3 I will try :-) Hope to have a solution too, I need it very much in my commercial project.

@anothertal3
Copy link

I tried to learn some MTP some time ago by using this library to backup pictures from my phone.

Apparently, something has changed between 1.5 and > 1.6 as tests started to loose connection to the device during the process (connect, iterate through all folders looking for files to backup, copy those, disconnect).
I hesitate to file a bug as I've yet to determine the culprit (PC, Phone, Library, ...).

When I find the spare time I will try to get it to work again and if I stumple about any optimization ideas I'll let you know!

@Bassman2
Copy link
Owner

Bassman2 commented Oct 10, 2018 via email

@Bassman2
Copy link
Owner

Bassman2 commented Oct 10, 2018 via email

@anothertal3
Copy link

@Bassman2

thanks a ton for your hard work!

I don't have a dedicated test but I did a quick experiment using my phone (approx. 10.5 GB content, ~3.000 files):

  1. Enumerate all files using root.EnumerateFileSystemInfos("*", SearchOption.AllDirectories)
  2. Store MediaFileInfo handle for each file in a list
  3. Iterate over that list and copy everything to a folder on my PC using MediaFileInfo.CopyTo
    (I tried to only store the FullName once and use MediaDevice.DownloadFile but this seemed to be much slower)

Note: the device connection was left open during this process.

Results (all in release configuration):

  • v1.5.0 -> 1.) 7:51 min and 2.) 7:36 min
  • right before optimizations -> 7:13 min
  • after speed optimizations -> 1.) 6:39 min and 2.) 6:49 min

Apparently there's indeed some improvement visible :)
However, I didn't fiddle with Stream.CopyTo or Item.numObjectsToRequest yet. Will do so as soon as possible.

Regards,
tale

@anothertal3
Copy link

Alright, did some more testing.

I was able to further reduce the amount of time needed by around 50s using your recommended parameters.

numObjectsToRequest buffersize Duration
16 40960 00:07:38
32 81920 00:06:48
32 163840 00:06:14
32 327680 00:05:51
64 163840 00:05:54
128 163840 00:05:57
128 655360 00:05:59
256 81920 00:06:55
256 163840 00:05:54

Leaving numObjectsToRequest at 32 or increasing it up to around 128 seems to be useful. More is apparently counterproductive.

Increasing buffersize up to 163840 seems to be helpful as well. Performance doesn't really seem to improve much more afterwards.

Regards,
tale

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants