"Your feedback is important to us; please stay on the line…" [Improving Windows Phone 7 application performance is even easier with these LowProfileImageLoader and DeferredLoadListBox updates]


This blog has moved to a new location and comments have been disabled.

All old posts, new posts, and comments can be found on The blog of dlaa.me.

See you there!

Comments (21)
  1. Morten Nielsen says:

    I think this says it all about the issue with Silverlight and also WP7:

    "tuning phone applications for optimum performance is an important task – and a challenging one!"

    Why is it so hard? I don't have to sprinkle BitmapCache selectively and thoughtfully all over my HTML to make it perform in IE9. I don't have to worry about two different threads (UI and Composition), or worry about which properties I animate, or shouldn't animate.

    How many poor-performing scrolling listboxes have you seen on for instance iPhone? I don't recall seeing any. Don't tell me all iPhone developers are awesome devs who just knows how to make things perform (I seriously doubt that). I mean… not even the Silverlight Toolkit guys can make a universal listbox that performs well on the phone. Then there is the ProgressBar that now has a "PerformanceProgressBar" in toolkit to address its issues. And then once again there's what this entire blogpost is about.

    I pledge you to forward the following question to the Silverlight and WinPhone team: Why is performance so hard? Why are you parsing so much responsibility onto the developer?

  2. Colin E. says:

    Great updates David. Do you mind if I point your readers at a couple of WP7 performance posts that I wrote which might be of interest?

    The first one re-enforces the point you make about testing on _real_ hardware by showing the relative performance of the emulator and a real phone:

    http://www.scottlogic.co.uk/…/windows-phone-7-performance-measurements-emulator-vs-hardware

    The second is a DeferredLoadContentControl which displays a loading indicator before the actual content is rendered in order to improve page load times and give a more responsive experience:

    http://www.scottlogic.co.uk/…/windows-phone-7-deferredloadcontentcontrol

    Thanks David 🙂

    Regards, Colin E.

  3. Danijel says:

    I'm with Morten here and I have big problems with performances of rendering engine in Silverlight on desktop! Can't event think about phone scenario. Clearly, Silverlight (WPF) rendering engine needs lots of improvements. MS needs to take very seriously rendering problems described into detail here: jeremiahmorrill.com/…/a-critical-deep-dive-into-the-wpf-rendering-system

  4. David Anson says:

    Morten Nielsen and Danijel,

    I don't have sufficient experience with/knowledge of IE9 and iOS internals to provide a meaningful answer, but I'll definitely pass your feedback on to the appropriate folks. Thanks for sharing!

  5. David Anson says:

    Colin E,

    Nope, I don't mind if you share those links – please go right ahead! 🙂

    I read both posts when you originally published them, but I'm going to read them again right now to refresh my memory.

  6. Colin E. says:

    @Morten,

    "I don't have to sprinkle BitmapCache selectively and thoughtfully all over my HTML to make it perform in IE9"

    I would love to see your example of HTML animation performing well within IE9 on a mobile device! If you are talking about the desktop, I challenge you to create an application with the same user-experience as the WP7 metro using cross-platform HTML5 + JavaScript +CSS3 – it can be done, but boy is it hard work!

    Also, remember, WP7 is a mobile, it does not have the same power as your desktop. This is true of any mobile development.

    You do make a valid point that it is easier to develop a smooth and fluid UI on iPhone. And you are right that Silverlight on WP7 does have a few pretty nasty performance gotchas, however iPhone is a mature, four year old platform, whereas WP7 is barely into its second quarter!

    Give it a bit of time to mature – then look again.

    Colin E.

  7. leitning.de says:

    Lovely, Many thanks for this. I am using the LowProfileImageLoader quite a lot here: http://bit.ly/hkTkxK

  8. David Anson says:

    leitning.de,

    That looks *very* nice – thanks for sharing!

  9. Alex S says:

    David, thanks for your classes and for the update specially.

    We did a little modification to the LowProfileImageLoader – when we are refreshing list data (list with apps, basically), we cancel all pending downloads because we don't need the old images, we need to load new images now.

    So when user changes the filter, he receives new images as soon as possible.

  10. Morten Nielsen says:

    Colin E:

    IE9 and hardware accelleration is coming to WinPhone 7 as well. Besides by comment was minded on both Silverlight 4 as well as WinPhone. Using the argument "It's the first release" doesn't really work. Remember that WinPhone is based on Silverlight 3, so I could make the argument that this is NOT a new platform (just some new hardware). The complexities that Silverlight has with respect to performance are far harder than on other platforms, so it's really more of a comment in general towards the entire API design. iOS and HTML5+IE9 are only two examples of a simpler rendering model.

    I don't argue that it's more work to develop for IE9 with HTML5 than it is for Silverlight – but that's really only because Silverlight gives us cross platform support, better developer tools, a type-safe language and compile time errors. What I do argue is that there is put a lot more responsibility onto the developer wrt rendering performance, than for example HTML5 does. With Microsoft's advances on IE9 and hardware acceleration, it really puts Silverlight in a bad light.

    Silverlight has a UI thread and you can in addition do background processing in other threads. Windows Phone 7 makes this even more complex: It has BOTH a UI thread, as well as a composition thread. Granted its there to "help" us get better performance on windows phone. However I argue that the only thing this did was to increase the complexity for those people who really wants to push the envelope. And I wouldn't be one bit surprised if the upcoming Silverlight 5 feature announced: "Fluid user interface enables smoother animation within the UI" really means that they ported this "idea" of a separate composition thread back to Silverlight. If they did, I personally consider that a fail.

    Anyway, I'll stop here before I hijack David's amazing blogpost 🙂

  11. John Mitas says:

    Morten Nielsen, the composition offers us a way to perform UI bound tasks that we don't really want affecting critical UI tasks. Having worked in this space for over 3 years (since Silverlight 1) I can say with 100% confidence that there are UI tasks that you want to be completely fluid and non-blocked. This offers us that ability…

    And in the future when we start getting more complex UI's where there will be great potential for UI blocking, this composition thread will be a godsend!!!

    There are great benefits to the composition thread!!!! And I look forward to a future where we'll be able to build apps with MULTIPLE-UI THREADS!!! That is something RIA developers/designers we need to work towards!!!

  12. David Anson says:

    Alex S,

    Neat – thanks for sharing!

  13. David Anson says:

    Colin E. and Morten Nielsen and John Mitas,

    I think this is a good conversation to have; no worries about "hijacking". 🙂

  14. Sergey Zwezdin says:

    Thank you for your LowProfileImageLoader.

    But it is no way to remove image! It is no effect if I try to set null to LowProfileImageLoader.UriSource.

    Why you ignore this case (with null value property)?

  15. David Anson says:

    Sergey Zwezdin,

    Believe it or not, nobody's ever requested that before! 🙂 To be fair, the original scenario was for scrolling lists where image removal never happens. That said, what should work for you here is to set Image.Source to null (as I discuss doing above) whenever you want to clear out an image. Alternatively, you could just remove the Image element from the tree.

    However, this is a very reasonable thing to want to do, so I've added a note to look into this next time I do an update.

    Thanks for the feedback!

  16. Geoff says:

    Very nice! The only thing I'd like to add is a property for LowProfileImageLoader that specifies a default image to use in the event of an error. For example images downloaded from the web when there is no network connection, I'd like to display a default / unknown "facebook like" generic image. That looks easy enough for me to do with a modified copy but it'd be nice if it was baked in in the event of any future upgrades.

  17. David Anson says:

    Geoff,

    Thanks! And FYI that I've added your suggestion to my TODO list to consider for a future update. 🙂

  18. Geoff says:

    Welcome… thank you. Turns out making that change was harder than I thought, at least for me, but perhaps I'll come back to later.

    The other thing that crossed my mind as an enhancement was an optional caching ability. In many cases the images won't be changing often and perhaps sometimes reading and writing them to/from isolated storage (when not "expired") might be more efficient and would allow for offline use.

  19. David Anson says:

    Geoff,

    When you talk about caching, you start to get out of the simple scenario I was looking to help with. You might want to see if AgFx (http://agfx.codeplex.com/) would be relevant to what you're doing…

  20. Hello,

    Thanks for the great library!

    However, I wanted to read the images from my Isolated Storage. I couldn't get it working without editing the source code.

    This is the addition I made: (it expects isolated storage files to have this uri: "isostore:/exampledirectory/examplefile")

    (around line 152)

    if (pendingRequest.Uri.OriginalString.StartsWith("isostore:", StringComparison.CurrentCultureIgnoreCase))

    {

        var fileStorage = IsolatedStorageFile.GetUserStoreForApplication();

        IsolatedStorageFileStream fileStream = fileStorage.OpenFile(pendingRequest.Uri.LocalPath, FileMode.Open);

        fileStorage.Dispose();

        pendingCompletions.Enqueue(new PendingCompletion(pendingRequest.Image, pendingRequest.Uri, fileStream));

    }

    else if (pendingRequest.Uri.IsAbsoluteUri)

    {

  21. David Anson says:

    Raymen Scholten,

    Thanks for sharing!

Comments are closed.