Listbox, Why Art Thou Blanking?
    3

    One of the biggest performance changes for developers using Silverlight in Mango (WP 7.5) is off-thread input for ListBox. In a nutshell this basically means that all any flick or pan a user makes on a ListBox is handled by a dedicated thread, the Direct Manipulation (DM) thread, instead of the UI thread. By connecting the DM thread to the Compositor thread (that’s the one that does all the drawing to the screen independent of the UI thread) we have a ListBox that moves smoothly even when the UI thread is completely blocked.

    Unfortunately this also comes with a price – the ListBox is now so responsive and moves so fast that the Listbox can run out of content to display to the user as the user is flicking, and blank – basically drawing nothing except for an updated ScrollBar (so the user knows he’s still moving in the ListBox, but it doesn’t help much) and the background while the UI thread scrambles to bring in new items to fill up the holes.

    My ListBox isn’t blanking, why do I care about this blog post?

    You care because you care about your users. You’re the kind of dev who knows that even though he’s got a great, powerful phone, not everyone does. You care because you are proud to call yourself a developer. You care because… ok, back to reality.

    With the release of Tango, Windows Phone is now supported on lower powered machines which often have slower hardware and less memory, so even though your device shows no blanking, others may see blanking, especially if they’re rocking a new, lower powered, Tango phone. This post will help give you the tools that let your app run smooth, with hardly any blanks, even on those phones.

    My ListBox is not blanking, but it’s really jerky during scroll

    Holy Smokes Batman! Jerky scrolling is all but eliminated in the new ListBox, even for WP7 apps – are you sure you’re using it? There’s a good chance you’re using the original LongListSelector (LLS) from the toolkit, which doesn’t auto-update when you move your project to Mango. To take full advantage of the new ListBox improvements you need to download the latest toolkit from http://silverlight.codeplex.com and update to the new LLS which is based on the platform’s ListBox.

    Why does blanking occur: the nitty gritty

    There are a couple of common code / design reasons that cause a ListBox to blank, but in general it all boils down to the amount of time it takes to bring in a new item. The ListBox maintains a one screen buffer of items in each direction which moves with the user’s viewport as they scroll around. If the ListBox can’t fill that buffer in the direction of the scroll fast enough, you get blanking.

    clip_image002

    Diagram 1: In a stationary world, when there is no scrolling going on, the user will be looking at the center screen and there will be buffered items waiting to be shown in both directions

    Filling the buffer takes a few steps, namely creating an Item Container (if a suitable one from the excess buffer in the other direction doesn’t already exist) and Data Binding the new item’s content (which kicks off the Measure pass). All of these updates occur on the UI thread and they all happen at once (not item by item) so if a flick is fast and the ListBox realizes that it needs to draw a full screen worth’s of items it will block the UI thread while it does just that.

    clip_image004

    Diagram 2: As the user moves downwards we balance the buffers by transferring the excess buffer from the top buffer (red) to the bottom buffer and re-databind it to the new data, maintaining 1 screen of buffer in each direction.

    But if the user flicks again while the UI thread is blocked bringing in buffer items, we’ll get even more out of sync and move completely out of our buffer space – since there is nothing in the Control to draw (remember, the ListBox is still scrambling on the UI thread to bring the new items in, it’s just too slow) you just get the background, i.e blankness.

    If there’s nothing to draw, why is the ListBox still moving? Or, look at it from another angle:

    As we mentioned earlier, scrolling is now off-thread, so from the Compositor’s point of view it’s moving the ListBox and everything in it, the problem is that the UI thread hasn’t stuck anything in it (at that position) yet, so we blank.

    clip_image006

    Diagram 3: Fast flicking a few times get you into this situation, where we have excess buffer above which we are trying to move downwards, but because there is so much of it and the UI thread is blocked trying to bring these items in we don’t finish in time and the user sees blankness (black) until the items are ready, at which time they simply appear.

    So why is *my* ListBox blanking? And how do I fix it?

    Let’s run through a couple of common reasons why ListBoxes blank, with some proposed solutions to each one.

    1. Using ValueConverters in your template

    ValueConverters are great – they allow you to transform your data on the fly as they are being DataBound into your items. Unfortunately they incur a UI thread cost – we need to transition from Silverlight into User Code, run your converter and then return. If your converter is heavy or you’re using lots of them in your template, then this will introduce blanking.

    Question to ask yourself: does this code look like it can run in a trivial amount of time across all of the elements being brought in for a given frame? If not, you probably should explore a different way of doing the DataBinding. For example,you can have the object translate the values on population / property get time instead of using a converter - even though this may break your Data Model this can significantly reduce the DataBinding cost (and you could always wrap your object in a ViewModel).

    2. Complex DataTemplates

    When an item is moved from one buffer to another during a scroll, ListBox is usually smart enough to determine that this is the same kind of item and just update the data in the item. While this might sound cheap this dirties the item causing it to be remeasured. If your template is complex you will find that a lot of your time is wasted in Measure – remeasuring the layout of the control now that the data has been updated.

    Fixing this is very per-scenario. Some general guidelines are to make sure to only use a container if you really need the options it provides – do you have a Grid within a Grid? Could you replace all of your Grids with a simple Canvas or maybe a StackPanel?

    3. Decoding images on the UI thread

    By default all images are decoded synchronously on the UI thread, so if you have something like this:

    <Image Source=”{Binding ImageUrl}”/>

    you're going to block the UI thread for however long it takes to decode your image. Luckily there’s an easy fix for this, change your template to read as follows:

    <Image>
      <Image.Source>
        <BitmapImage UriSource="{Binding ImgUrl}" CreateOptions="BackgroundCreation"/>
      </Image.Source>
    </Image>

    Note that this does come with some caveats – older images will still show up until the new ones are loaded and the user may see a visual pop-in of the image when it is done loading, but these can all be worked around and massaged into a nice user experience that is not harmed by excessive image decode.

    For further details see this blog post.

    4. Using PrepareItemForContainerOverride to dynamically select a template

    A simple list item is often times just not good enough – your app has an image item, a text item, a video item, a link item etc. etc. and you have a different template for each one of them. A common pattern is to use the ListBox’s PrepareItemForContainerOverride callback to dynamically change the container’s template based on what item is being databound.

    Unfortunately, doing this can completely throw off the ListBox’s buffering technique – the ListBox sees that the container that it had in its buffer is not the type that you need and junks it, wasting even more time on the march to blankness.

    So how do I solve this? Surprisingly enough, it is often cheaper to have all of your template parts in one large template (yes, yes, I know about point 2 above – keep reading!) with each mini-template collapsed if it does not apply. Since collapsed template items incur next to no cost during layout, they have next to no impact on run time (though there is a slightly larger memory cost).

    And how do I get my different items to display on the different templates? Simple – databind to a new property on your classes which either has a type enumeration that runs through a value converter (ItemTypeToVisibility), these kinds of converters are often cheap, or wrap your class in a UI view model so that it has a property that returns the Visibility type directly.

    5. Pulling data from [favorite heavy source] as part of your binding

    The properties you bind to should have simple getters (setters is a different story) – always. If you have logic like this:

    public int Rating
    {
      get
      {
        <read from database>   
        - or -
        <read from IsoStore>
        - or -
        <parse out some XML>
        - etc -   
     
    }
    }


    then you’re doing something wrong. This kind of logic is fine for a property that you know is only read very rarely, if at all, but if it’s in a ListBox then it most likely is going to be seen and you should be initializing the data up front.

    Don’t get me wrong – you don’t need to load everything as you are pulling in 1000 items to your list, but you can certainly do it on a background thread as a deferred task kicked off in the constructor of your object. If your objects are really heavy and memory is becoming an issue then you have a few possible routes:

    • Implement a completely delayed load by hooking into the ListBox’s scroll amount or compression states and only loading more items when you get to the end of the list
    • Implement a DoubleLinkedObservableCollection, where each item in the collection knows about the next node (in each direction) and when it gets databound (based on one of the properties) it notifies X number of nodes on each side to make sure they all have their data ready to go. This should be done on a background thread, just don’t forget to Dispatch back to update any properties that raise a PropertyChanged event.

    6. Cut down background work

    With only one core any background thread can interfere with the smoothness of the UI thread. Although background threads get a much smaller time slice compared to the UI thread, enough of them vying for time will effectively starve the UI thread.
    clip_image008

    Diagram 4: Fictional time slice showing the effects of more background threads (not to scale)

    Across any given slice of time, the UI thread will be allowed to run longer than any other thread, but is effectively running at the same priority, hence it is forced to yield to the background threads when its time is up. The more background threads, the longer it is before you get back to the UI thread so that it can complete its task.

    Moral of the story? Be wise about the number of active background, especially in high stress scenarios. Stick to using a thread pool so that you can queue up your work without it all trying to run at the same time.

    I’ve tried all the above, it’s still blanking and I only have a couple of screens of data – help!

    If you find yourself blanking on a relative small set of data (approximately 3-5 screens), then it might be time for drastic measures. As mentioned above the cause for blanking is the amount of time it takes to bring in new items with new data as the user is scrolling, i.e. the virtualization overhead is the culprit. If you disable virtualization on your list, you’ll generate of all your items up front and scrolling will be blankless. To do this, add the following to your XAML:

    <ListBox.ItemsPanel>
    <ItemsPanelTemplate>
    <StackPanel>
    </StackPanel>
    </ItemsPanelTemplate>
    </ListBox.ItemsPanel>

    While making this change is relatively simple, the impact can be drastic – no more blanking, but it comes at a cost:

    1. Startup time for the Page increases – we now have to realize more items, so it’s going to take longer
    2. Memory – same as above, more items hanging around, larger memory cost

    If you give it a try on a low end device and startup and memory look acceptable – then this is your magic bullet!

    So what are we left with?

    Hopefully at this point you have a non to minimally blanking list, which scrolls smoothly and generally delights your users! Have you run into any other pitfalls that you think others should be warned of? Let us know below!

    Running into other, unrelated performance issues? Drop us a line and we'll see if we can focus on them in a future blog post (stay tuned for a "memory" series coming soon).

    Memory Profiling - The Heap Summary View
    2

    In an earlier post we looked at how we can gain broad insight into an application scenario’s memory characteristics and how the graph and markers drew our attention to ranges of execution for further analyses. Recall that in the memory leak diagnosis case we chose to analyze only the time range over which we observed the increase in memory usage. Indeed, that is a key first step to the analysis: filtering the memory activity data by a time range. The Heap Summary view is the result of such filtering, and represents the population of the heap during the chosen time range.

    Heap Summary View

    The Heap Summary view presents, in tabular form, a demographic analysis of the population of the heap.

    In human population demographics, data collection happens through a census as well as through a continuous update to registries that track births, deaths, migration of place of residence and the like. The data collection in the case of heap population demographics is no different. “Births” map to allocations, “deaths” map to objects’ memory collected by the GC, and “migration of place of residence” maps to the migration of objects between the Gen0 region of the heap and the Gen1 region. A census of the heap at the start of time range identifies all incumbent objects (i.e. that were in existence). Births, deaths, and migrations are updated continuously, and a final census at the end of the time range identifies all the objects that were retained. In order to have a consistent terminology, we refer to the incumbent objects at the start as objects that were “retained” at the start.

    Managed Silverlight Visual elements (i.e. objects that go into the Silverlight visual tree) are not just plain old managed objects. These might be facades with backing native-implementations holding native memory and during the course of execution might create and hold on to texture memory. Casual use of such elements in code can even lead to subtle leaks. From this perspective, subsequent analysis can be made easier if Silverlight Visual elements were tracked and reported separately from plain old managed objects. And this is precisely how they are tracked and reported through the Heap Summary view. Continuing with the demographic analogy, such classification has precedent in social demographics where human populations have been classified on ethnicity.

    Armed with this context, let us study the following Heap Summary view from the memory leak diagnosis case:

    image

    The shaded region across the graph and markers indicates the time range used as the filer.

    The census at the start reports 5576 instances of managed type objects accounting for about 283 KB and 26 instances of Silverlight Visual elements accounting for about 13 KB. In terms of incumbency the plain old managed objects dominate.

    The churn happening within the selected time range is reported as 10615 instances allocated (births) and 11590 instances collected (deaths), accounting for about 23 MB each. The counts and sizes are somewhat balanced and cancel each other out to an extent. And this is borne out by the census at the end for the managed objects; the census at the end reports 4601 instances of managed type objects accounting for about 223 KB, which is just a little lower than what we had at the start. However, it also reports 69 instances of Silverlight Visual elements accounting for about 4 MB now (up from 13KB at the start).

    When we correlate this table with the graph, our suspicion is drawn towards the Silverlight visuals. Why did their count go up, and why are they accounting for so much more memory? Within the filtered time range, memory usage has been steadily increasing too. Could we be leaking memory? Could we be leaking some part of visual tree itself? And there even seem to be images being loaded along the way; might we be leaking their texture memory too? We wonder.

    Clearly, the next lead to follow is to get more visibility into what are those “Retained Silverlight Visuals at End”.

    Summary

    The Heap Summary view presents, in tabular form, a demographic analysis of the population of the heap. Interpreting the data in the table and correlating it with the graph and markers by itself can be used to make educated guesses at what could potentially be the problem, but equally importantly it serves to inform the next step in the performance investigation, as we shall see.

    Delivering Rich Mobile Web Experiences in Windows Phone 7.5 (ESPN.com Case Study)
    7

    The Windows Phone Browser team has a goal of delivering the best web browsing experience on a smartphone. This goal has many components within our team: from the UI of the browser, compatibility with a wide array of website layouts, and of course buttery-smooth rendering performance. However, even if we execute flawlessly on our end, we are missing a crucial piece - delivering a great web experience is fundamentally a partnership between our team and web developers. Achieving this goal means working together to ensure that your content and services are delightful for users to consume on Windows Phone.

    We understand that web development resources are always limited as you keep up with the increasing traffic from mobile devices, and the elusive "write once, run everywhere" promise of web development has not perfectly materialized. However, with IE9 for Windows Phone 7.5, we took a big step in the direction of this promise. By sharing a codebase with IE9 for the PC, we achieved identical support for new web standards and pushed the envelope on real-world performance with industry-leading hardware acceleration. We wanted to hear about developing for IE9 on WP7.5 from web developers directly, so we decided to collect some feedback and share it on the blog.

    ESPN.com recently deployed their premium web experience to Windows Phone, and we thought it would be great to hear what they had to say about developing for IE9 on Windows Phone. As a side note, ESPN started looking into supporting Windows Phone because of a simple request I made on their support page. Lots of folks on my team are sports fans and were asking me about the site's experience on WP7.5, so I just dropped ESPN a note like any user would. The message was quickly routed to the mobile site team; I have immense respect for ESPN’s responsiveness and the system they have place to address user feedback. Here's what Mike Marrone, technical lead, had to say about developing for IE9 on WP7.5:

    Overall, it was an easy process. We support only WP7.5 and IE9 thanks to its very good CSS3/HTML5 support. We are in a convenient position of having an existing legacy mobile site that older devices can fallback to. Honestly, development for WP7.5 boiled down to a fairly basic process - IE9 on the PC, being nearly the same browser, was a great dev tool to get most of the way there before final QA on actual devices.

    Some other more specific development notes:

    • The "display: box" CSS style is not supported on WP7.5. We use this in carousel experiences to transition elements left or right 100% of the viewport without having to programmatically determine the viewport size (which means the browser automatically updates the positioning upon device rotation, etc.). On WP7.5, we actually used a better alternative thanks to it being the only browser that currently supports the CSS "vw" unit (VERY useful).
      [Amin] See here and here for more information on vw units.
    • The bulk of our CSS differences between WP7.5 and other supported devices was with gradients. WP7.5 has an easy fallback with filters so it was not a big development issue.
      [Amin] See here for information on using Gradient Filters in IE9.
    • JavaScript touch events would be a nice addition.
      [Amin] We hear you, stay tuned!

    We look forward to your continued great progress in mobile.

    As you can imagine, this was music to our ears! We often use IE on the PC to investigate bugs, and it was great to hear that the tools work well for web development outside of our offices too. We appreciate the feedback (it will inform our plans for future releases) and welcome additional feedback through the comments below.

    IE9 on Windows Phone is set up to support rich web experiences with great performance, and often all it takes is updating user-agent logic and using standards based (as opposed to vendor prefixed) HTML & CSS. ESPN invested a reasonable level of resources to do that and delivered a delightful experience to its users. I've definitely started to see the site pinned to Start around here, and I wouldn't be surprised if our senior managers are secretly checking ESPN during meetings.

    Here's a before (left) and after (right) screenshot of the ESPN.com experience on Windows Phone 7.5. We want to say thanks to ESPN, and we look forward to seeing more rich experiences light up!

    image     image

    Special thanks to Krys Krycinski, Mike Marrone, and James Ballow at ESPN.

    Amin Lakhani
    Program Manager, Windows Phone

    Four ways we’re improving Marketplace
    32

    Today I’ll outline the latest steps we’re taking in our ongoing effort to keep the quality bar high in our rapidly growing Marketplace. I know most of you share our goal of a great shopping experience and already go out of your way to follow our policies and guidance. For others, I hope this insight into a few near-term changes we’re putting in place helps save you time and reduces your risk of having apps pulled from the Marketplace.

    Avoiding trademark trouble

    When a trademark or copyright owner contacts us about a suspected violation, we investigate and pull apps when the complaint is valid. Lately we’ve been doing more of this, especially for trademark misuse. Sometimes the requests come from the owners of big, well-known brands. Other times they come from new brands. Either way, we often find trademark violations are unintentional: some developers just aren’t clear on what constitutes a violation. But these investigations—and the time and money they can cost—can be avoided by doing a little homework before submitting or updating your app.

    If you’re developing an app, please consult our content policy covering trademarks and this related Q&A. (The U.S. Trademark and Patent Office also has helpful background and a trademark search tool.) Our rules boil down to this: Your registered publisher name and everything about your app—name, logo, description, screenshots—must be unique and free of trademarked content unless (1) you own the trademark, (2) you’ve secured permission from the owner to use it, or (3) you’re using a trademarked name (not a logo) to describe your app’s features or functionality without suggesting that the app is actually published by the trademark owner.

    For example, using “Microsoft App Co.” as your publisher name would cause problems because “Microsoft” is a trademarked term. By the same logic, you couldn’t call your app “MSN” or “YouTube”. However, you may be able to make an app called “Reader for MSN,” as long as you don’t use the MSN logo or otherwise suggest that the app is published by Microsoft.

    Keeping the quality bar high

    I’ve posted before about our efforts to help ensure that apps in Marketplace offer clear value. One of those efforts concerns bulk publishing—developers who send us hundreds of similar apps simultaneously. Today I want to mention two related issues on our radar that could affect developers working on app genres that lend themselves to bulk publishing.

    First, we’re seeing developers submit the same app to multiple Marketplace categories, a violation of our policies. Instead, you should pick a single category that best reflects the content and function of your app. This not only helps customers find your app but gives all developers an equal opportunity to have their app discovered where people expect. Developers who submit the same app across multiple categories will have it removed from the catalog.

    Second, when you create multiple closely-related apps—say, a series of quote apps that vary by theme—the Marketplace tile images must reflect the unique features of each individual app. They cannot be duplicates or near duplicates of each other. Your branding also shouldn’t dominate the tile. Here are a few examples of dos and don’ts:

    image

    image

    Creating unique, easily distinguishable app tiles helps customers see at a glance what’s different about the apps you’re publishing, improving the shopping experience and potential for downloads.

    Cleaning up keywords

    Some developers have been violating Marketplace policy by entering more than the five allowed keywords for an app. A keyword is a word or short phrase that describes your app. Entered during the App Hub submission process, these words or phrases are always separated by commas.

    Starting this week, we’re going to start enforcing the five keyword rule for all current and future Marketplace apps. Any app that exceeds this number will have all its keywords deleted. Affected developers will be notified and can then enter five new keywords in App Hub. We’re taking this action to help ensure that customers are able to find the most relevant set of apps for their search—including yours.

    We’re also starting to examine app keywords for relevancy. We’ve noticed some developers have been entering keywords that are popular search terms—“Justin Bieber,” “YouTube”—but are totally unrelated to their app and what it does. If we find a keyword that’s not relevant to your app’s function or content, we’ll delete that keyword. Additionally, if you suspect that other developers are using high-impact keywords unrelated to their app— “Skype” for a tic-tac-toe game, for example—email reportapp@microsoft.com with the details and we’ll investigate.

    Refining our approach to content policy enforcement

    The final issue I want to discuss is one that affects all major app stores today: the treatment of apps that are “racy” or sexual in nature. We’re committed to offering a diverse selection of safe and quality apps that appeal to a wide range of customer interests. Items that some customers view as entertainment, others may consider inappropriate. This is a challenge for any big retailer, whether they operate online or down the street.

    We think the right solution is (a) to be transparent about what’s acceptable and (b) to show the right merchandise to the right customer in the right place. Our content policies are clearly spelled out: we don’t allow apps containing “sexually suggestive or provocative” images or content. What we do permit is the kind of content you occasionally see on prime-time TV or the pages of a magazine’s swimsuit issue.

    Admittedly, it’s tricky catering to such a wide range of people and markets. But we take this responsibility seriously and evaluate and discuss questionable cases. Recently we decided that we could improve the shopping experience for all our customers by a more stringent interpretation and enforcement of our existing content policy.

    Specifically, we will be paying more attention to the icons, titles, and content of these apps and expect them to be more subtle and modest in the imagery and terms used. Apps that don’t fit our standard will need to be updated to remain in the store. This is about presenting the right content to the right customer and ensuring that apps meet our standards. We will also monitor customer reaction to apps and reserve the right to remove ones that our customers find offensive

    While this change might require a little extra work on the part of a small number of developers, there are plenty of creative and appropriate ways to comply: showing male or female models in silhouette, for example, is one possible alternative. Here are a few other examples of app tiles that pass muster:

    image

    If you’re one of the handful of impacted developers, we will be reaching out to you within the next few days with more specific guidance on changes you need to make. If you don’t hear from us, there is no immediate action you need to take.

    I hope this post has provided some useful tips and helpful insight into our policies, and how they’re evolving to reflect both customer and developer feedback and the growing size and reach of the Windows Phone Marketplace. We’re committed to our developer community and appreciate your feedback on how we can make Marketplace better for you and your customers. I look forward to hearing your thoughts.

    Two Marketplace changes; An update on 9 new markets
    11

    I wanted to make sure you saw the Windows Phone consumer blog today, because my colleague Mazhar highlights two changes to the Marketplace shopping experience that developers should be aware of.

    First, we’re removing the option to browse and buy Windows Phone apps from the Zune PC software, a change that started rolling out this afternoon. Second, in the coming weeks we’ll also start requiring that customers have Windows Phone 7.5 installed on their phone to buy, download, update, or review apps in Marketplace.

    Mazhar’s post has more details and background. But I want to highlight one important way the removal of the Windows Phone store from Zune impacts developers.

    It’s important to make sure you’re using the correct protocol for direct links to your app in Marketplace. This “deep link,” as it’s also called, makes it easy for customers to pull up your app in the phone and web stores. The correct format is:

    http://windowsphone.com/s?appId={GUID}

    You’ll find more details on deep links here on MSDN. If you use the older zune:// format for links, customers will see an error message. Just something to keep in mind.

    One final update for today: We just released the OS software required to bring Marketplace to customers in Bahrain, Israel, Iraq, Kazakhstan, Qatar, Saudi Arabia, Thailand, UAE and Vietnam. These nine markets—which are already open for app submissions—were part of the larger Marketplace  expansion I outlined last month. Our hardware partners can now create phones for these markets and begin their final launch preparations.

    Mazhar will have more to say about these new storefronts in the weeks ahead.

Page 1 of 34 (168 items) 12345...Last