Listbox with images cause in the end OutOfMemoryException

16 posts, 0 answers
  1. Mateusz
    Mateusz avatar
    3 posts
    Member since:
    Feb 2012

    Posted 10 Dec 2012 Link to this post

    Hi.

    We have a problem with memory usage in our application that uses heavily(almost on all the pages there are 2 lists visible) RadDataBoundListBox in conjunction to a lot of images(about 150-200) in the application. Let me elaborate.

    Those pages are Pivot pages. So we have 1 main pivot with 5 pivot subpages, which contain those lists.

    We have simple datatemplates set for those lists, which contain (almost always) a 1 column grid, in which we display an image that we give by binding an uri source. We do not set itempanel ourselves, so the virtualization is on by default for RadDataBoundListBox, correct?

    Now the problem is, that the memory that is taken by creating those images is stacking up, and in the end it causes OutOfMemoryException (tested on 256MB Emulator). But how can it be with virtualization on?! Virtualization should release the BitmapImage objects that were created for the elements that were recycled, and afterwards these should be picked out by the GC when in need, but they are not.

    Instead what happens is that while the list is scrolling the bitmaps are stored localy. So although the virtualization for the UI elements is working(I assume so by the telerik api) the bitmap images that are created to store the images in the datatemplate are not recycled, but are created separately for each element in the list.

    The effect is, that while I'm scrolling the list, the memory is rising untill it reaches the threshold and the application crashes.

    What we expected:
    We expected that all would be handled by the virtualization with Garbage Collector. So if the list has for example 1000 elements and every one is displaying an image, those images would be created/destroyed depending on the memory situation.

    What we need/require:
    We need to make sure the memory of the application does not rise above some point, say 70-80MB. So while the bitmapimages are created, they can be stored localy(cached), but once the memory is starting to shrink, we need the images(some of them or all of them) that are not in the viewport to be released, so that there is again a free memory for the new images that will be downloaded from the internet.
  2. Deyan
    Admin
    Deyan avatar
    2041 posts

    Posted 12 Dec 2012 Link to this post

    Hi Mateusz,

    Thanks for writing.

    RadDataBoundListBox's virtualization mechanism does not know what type of ItemTemplate is defined, i.e. we are not aware of the visual structure of the items at the point where the developer's item template comes. What we do when we recycle the visual items is set their Content property to the specified data object from the source collection and update its ItemTemplate if needed.

    Obviously there is a memory leak that happens in your scenario. We have had similar customer scenarios before where the pictures remained in the memory because once downloaded a reference was made to them in the view models. This issue was solved by using weak references. Since based on the details you're sharing I understand that you're not storing references to the images in your view models but to URIs, I will need to directly take a look at the source and debug it on my side.

    Please note that you will have to open a new support ticket in order to be able to upload the sample project.

    All the best,
    Deyan
    the Telerik team
    Have a suggestion or face a problem - you can use the Ideas & Feedback portal to submit ideas, feedback and vote for them.
  3. DevCraft banner
  4. Mateusz
    Mateusz avatar
    3 posts
    Member since:
    Feb 2012

    Posted 12 Dec 2012 Link to this post

    Hi Deyan

    We were able to nullify the source of the bitmaps, when we used the custom dll for smoothing the UI while downloading images. In it, prior to creating new BitmapImage, we set the BitmapImage of the current Image control to null as well as UriSource.

    Just to clarify to make sure we understand the concept fully, it works like so:

    We have a list that is virtualized. Each element contains a Image control which has set Source to external Uri.

    Now default virtualization has the number of elements from UI created that are seen on the viewport + a few from above and below the viewport. When user scrolls down, the most top element that is above viewport is being moved bellow the most bottom created UI element below viewport. So in esence what happens is that BitmapImage is not created from the start again and again, but it's source is changed to the new Uri.

    Did we get it right?

    Thank you

    (This question is a general question, please do not tie it to the scenario through which we fixed our problem)
  5. Deyan
    Admin
    Deyan avatar
    2041 posts

    Posted 13 Dec 2012 Link to this post

    Hello Mateusz,

    Thanks for writing back.

    Yes, you have understood the UI virtualization mechanism correctly. Theoretically this should not cause memory leaks since Image elements are reused and remapped to new URIs to show new images. The old once should be freed from the memory as the Image element, once assigned a ne URI, cleans the memory of the old image.

    Regards,
    Deyan
    the Telerik team
    Have a suggestion or face a problem - you can use the Ideas & Feedback portal to submit ideas, feedback and vote for them.
  6. Mateusz
    Mateusz avatar
    3 posts
    Member since:
    Feb 2012

    Posted 13 Dec 2012 Link to this post

    Hi Deyan.

    Thanks for confirmation.

    There is known silverlight memory leak that has to do with BitmapImage. You can find about it on the web.
  7. Deyan
    Admin
    Deyan avatar
    2041 posts

    Posted 15 Dec 2012 Link to this post

    Hi Mateusz,

    Can you please send us a sample which reproduces this issue so that we can take a look and see whether we can help?

    Greetings,
    Deyan
    the Telerik team
    Have a suggestion or face a problem - you can use the Ideas & Feedback portal to submit ideas, feedback and vote for them.
  8. Frank
    Frank avatar
    2 posts
    Member since:
    Nov 2012

    Posted 17 Mar 2013 Link to this post

    Hi Deyan

    Was this issue resolved? Only I am having a similar issue with increasing memory usage as I scroll thru the image list

    Thanks
    Frank
  9. Deyan
    Admin
    Deyan avatar
    2041 posts

    Posted 18 Mar 2013 Link to this post

    Hi Frank,

    Can you please download our latest Internal Build and see if it addresses the issue?

    We're looking forward to receiving feedback on this.

    Regards,
    Deyan
    the Telerik team
    Have a suggestion or face a problem - you can use the Ideas & Feedback portal to submit ideas, feedback and vote for them.
  10. Frank
    Frank avatar
    2 posts
    Member since:
    Nov 2012

    Posted 18 Mar 2013 Link to this post

    Hi Deyan

    I tried version RadControls for Windows Phone 8 2013.1.0314, and although it seems better, I navigate through my image galleries a little longer, it will still eventually run out of memory.

    In my code I have an ObservableCollection containing all the URL for the images.

    I pass this to the ListBox and let it run!

    I do not load any extra urls they are all loaded when as the page is initialised

    Frank
  11. Deyan
    Admin
    Deyan avatar
    2041 posts

    Posted 18 Mar 2013 Link to this post

    Hi Frank,

    Will it be possible if you send us the project you're using to reproduce the issue for further investigation?
    This will help us debug it and see what causes the leak.

    You will have to open a new support ticket in order to be able to attach your project.

    Thanks for your time.

    Greetings,
    Deyan
    the Telerik team
    Have a suggestion or face a problem - you can use the Ideas & Feedback portal to submit ideas, feedback and vote for them.
  12. Michael
    Michael avatar
    7 posts
    Member since:
    Jul 2013

    Posted 23 Jul 2013 Link to this post

    Hi Frank/ Deyan,

    Has the been another outcome to this since the most recent post?

    I am seeing very similar things to Frank, in that I am getting OutOfMemoryException when binding to a collection with a lot of images, as well as in some scenarios when scrolling though that list after it has loaded.

    Many Thanks,

    Mike 
  13. Deyan
    Admin
    Deyan avatar
    2041 posts

    Posted 23 Jul 2013 Link to this post

    Hello Michael,

    Thanks for writing.

    We have observed similar behavior before and we think it is related to the internal Image element implementation rather than our DataBoundListBox. To make sure that this is the case I would like to ask you to implement the following code within your application by handling the ItemStateChanged event exposed by RadDataBoundListBox:

    void listBox_ItemStateChanged(object sender, ItemStateChangedEventArgs e)
    {
        if (e.State == ItemState.Recycling)
        {
            RadDataBoundListBoxItem container = this.listBox.GetContainerForItem(e.DataItem) as RadDataBoundListBoxItem;
     
            container.DataContext = null;
            container.Content = null;
            container.ContentTemplate = null;
        }
    }

    Let us know if the issue is resolved after integrating this code within your app.

    If the issue persists we would like to ask you to prepare a sample project that reproduces it and send it to us so that we can directly take a look and see how we can help.

    Thanks for your time.

    Regards,
    Deyan
    Telerik
    TRY TELERIK'S NEWEST PRODUCT - EQATEC APPLICATION ANALYTICS for WINDOWS PHONE 7.
    Learn what features your users use (or don't use) in your application. Know your audience. Target it better. Develop wisely.
    Sign up for Free application insights >>
  14. Michael
    Michael avatar
    7 posts
    Member since:
    Jul 2013

    Posted 23 Jul 2013 Link to this post

    Hi Deyan,

    Thanks for getting back to me. I tried the below but no luck I am afraid.

    However, I did modify it slightly to run a quick test. Please see below:

    int loaded = 0;
     
    void ListBox_ItemStateChanged(object sender, Telerik.Windows.Controls.ItemStateChangedEventArgs e)
    {
             if (e.State == ItemState.Recycling)
             {
                     RadDataBoundListBoxItem container = this.ListBox.GetContainerForItem(e.DataItem) as RadDataBoundListBoxItem;
     
                    container.DataContext = null;
                    container.Content = null;
                    container.ContentTemplate = null;
     
                    loaded--;
                }
                else if (e.State == ItemState.Realizing)
                {
                    loaded++;
                }
            }


    So what this made me notice is that when I got to 40 or so images in my list, as I scrolled up and down through that list, items were recycled as other items were being realized. Thus meaning the loaded value stayed at around 40 items, such that there was only ever 40 realized items in the list.

    However, when I then completed another update to get more items (which adds additional range to the ObservableCollection items source from a list which has all the items), the event fired all the realized items in a row before attempting to recycle other items, meaning that I then had about 60 items in the list, at which point it crashed before it could load all the newly added items.

    I imagine that this is probably the issue? It seems that when the item source is updated, all the newly added items are realized first before the list box attempts to recycle other items. Which would make sense why higher end devices are able to go a while longer before crashing, if not, not crashing at all.

    Could this be the reason?

    Many Thanks,

    Mike




  15. Michael
    Michael avatar
    7 posts
    Member since:
    Jul 2013

    Posted 23 Jul 2013 Link to this post

    Hi Deyan,

    In addition to my previous post, I tried another avenue:

    By setting the RealizedItemsBufferScale to 1.0 on the control, it appears to combat the issue stated in my previous reply. This setting limits the amount of realized items to about 25 in most cases in my solution.

    With this, it means that the pages seem to work fine and recycled/ realize items appropriately.
    However, I don't really like this as it purely means that it is stopping just short of the device or emulator memory capacity, such that on lower end devices, even this amount of realized items would be too much in my case. - seems like a fix for some devices but not others.

    In addition, another issue I am noticing is that if I proceed to scroll up and down a list of 100 plus images rather fast, not only does the realized item count fail to stay around 25 (reaching 40+ in some cases), but it also again leads to an OutOfMemoryException, seemingly as items cannot be recycled quickly enough?
    I don't know if this second point has ever been noticed?

    Many Thanks,

    Mike
  16. Michael
    Michael avatar
    7 posts
    Member since:
    Jul 2013

    Posted 23 Jul 2013 Link to this post

    Hi Deyan,

    In addition to my previous post, I tried another avenue:

    By setting the RealizedItemsBufferScale to 1.0 on the control, it appears to combat the issue stated in my previous reply. This setting limits the amount of realized items to about 25 in most cases in my solution.

    With this, it means that the pages seem to work fine and recycled/ realize items appropriately.
    However, I don't really like this as it purely means that it is stopping just short of the device or emulator memory capacity, such that on lower end devices, even this amount of realized items would be too much in my case. - seems like a fix for some devices but not others.

    In addition, another issue I am noticing is that if I proceed to scroll up and down a list of 100 plus images rather fast, not only does the realized item count fail to stay around 25 (reaching 40+ in some cases), but it also again leads to an OutOfMemoryException, seemingly as items cannot be recycled quickly enough?
    I don't know if this second point has ever been noticed?

    Many Thanks,

    Mike
  17. Deyan
    Admin
    Deyan avatar
    2041 posts

    Posted 26 Jul 2013 Link to this post

    Hello Mateusz,

    Thanks for writing back.

    There are a couple of reasons you might experience this behavior.

    One of the main reasons could be the size of the pictures you are downloading. If the pictures are with bigger resolution, once rendered they take up the memory needed for the same sized bitmap. You should keep in mind that a 500 KB picture encoded with JPEG will become several megabytes once rendered. This is because it is decoded to a bitmap and put into the memory for rendering.

    Please make sure that you have specialized thumbnails (smaller pictures) and render them instead. Once a bigger picture is needed (for example when tapping on one of the smaller thumbnails), you can download it with its full size.

    These are just my guesses so I really would like to take a look at your project to see what exactly happens. Is it possible for you to prepare a ZIP and send it to us for further investigation?

    Regards,
    Deyan
    Telerik
    TRY TELERIK'S NEWEST PRODUCT - EQATEC APPLICATION ANALYTICS for WINDOWS PHONE 7.
    Learn what features your users use (or don't use) in your application. Know your audience. Target it better. Develop wisely.
    Sign up for Free application insights >>
Back to Top
DevCraft banner