Hibernating Rhinos

Zero friction databases

Fixing memory leaks in RavenDB Management Studio - FluidMoveBehavior

Continuing on my last blog post in this series, which I talked about the WeakReference, that time I’ll talk about the FluidMoveBehavior.

The FluidMoveBehavior gives you a great transition effect to the items in your WrapPanel, which is in the Silverlight toolkit. The FluidMoveBehavior is part of the Expression Blend and it’s exists in the microsoft.expression.interactions.dll.

When I profiled the application with a memory profiler, I have some memory leaks that caused by the FluidMoveBehavior. Surprised I Googled the following “FluidMoveBehavior memory leak” and the first result was this thread, which effectively showed that this is a known issue with no fix yet.

So removing the FluidMoveBehavior from the Management Studio fixes a big source of memory leak. What’s interesting, that the visual effect itself of the FluidMoveBehaviour barley was needed, since we already populating the panel with items each time the panel size is changed.

Published at

Originally posted at

Fixing memory leaks in RavenDB Management Studio - WeakReference

Continue from the last blog post in this series, which I talked about the WeakEventListener, now I’m going to talk about using the WeakReference.

In the RavenDB Management Studio we have 4 pages that contains lots of data: the Home page, Collections page, Documents page and Indexes page. Once you enter to one of those pages, we’ll fetch the data from the RavenDB database but in order to avoid fetching it each time we navigate to that page the data is stored in a static variable. This way, if you re-navigate to a page, you will see the database immediately while we making a background request to RavenDB in order to give you more updated data.

You can look on this code for example:

public class HomeModel : ViewModel
{
    public static Observable<DocumentsModel> RecentDocuments { get; private set; }

    static HomeModel()
    {
        RecentDocuments = new Observable<DocumentsModel>
                          {
                            Value = new DocumentsModel
                                    {
                                        Header = "Recent Documents",
                                        Pager = {PageSize = 15},
                                    }
                          };
    }

    public HomeModel()
    {
        ModelUrl = "/home";
        RecentDocuments.Value.Pager.SetTotalResults(new Observable<long?>(ApplicationModel.Database.Value.Statistics, v => ((DatabaseStatistics)v).CountOfDocuments));
        ShowCreateSampleData = new Observable<bool>(RecentDocuments.Value.Pager.TotalResults, ShouldShowCreateSampleData);
    }

    public override Task TimerTickedAsync()
    {
        return RecentDocuments.Value.TimerTickedAsync();
    }
}

The problem is, what happening when the application consumes to much memory because of all of this static data? In that case there likely to be a performance issues. In order to avoid that, we used make static data to be a WeakReference type, so we basically say to the Silverlight GC engine: If you want to GC the data, please do so. And in this case we’ll just re-initialize it when we need the data again.

This had an huge impact of the memory consumption of the Management Studio application, but we still had some memory leaks which I’ll talk about in the next blog post.

Published at

Originally posted at

Why make WeakEventListener internal?

In the previous post I described how I used the WeakEventListener from the Silverlight Toolkit in order to solve a memory leak. This class is a very needed tool, and it’s something that is recommended to use in Silverlight applications, in order to avoid memory leaks.

Since this class is internal, you must copy the code from the source (thanks to the Microsoft Public License) to your Silverlight application. I’m not sure if this is still the case in the last version of the toolkit, which is compatible with Silverlight 5 (the source code for this is not public when I wrote this), but in any case, if you’re developing a Silverlight application, I’m pretty sure that you’ll need this class.

Tags:

Published at

Originally posted at

Fixing memory leaks in RavenDB Management Studio - WeakEventListener

After shipping the new version of the Management Studio for RavenDB, which was part of build #573, we got reports from our users that it have some memory leaks. This report indicated that we have an huge memory leak in the management studio. I started to investigate this and found a bunch problems with cause it. In this blog posts series I’ll share with you what it took to fix it.

RavenDB Management Studio is a Silverlight based application. One of the mistakes that can be done easily in a Silverlight application (as many other platforms for UI applications) is to attach an event to an object, than discard that object. The problem is that the object will never be cleaned up from the memory, since we have a reference for it – the event listener.

Consider the following code for example:

public static class ModelAttacher
{
    public static readonly DependencyProperty AttachObservableModelProperty =
        DependencyProperty.RegisterAttached("AttachObservableModel", typeof(string), typeof(ModelAttacher), new PropertyMetadata(null, AttachObservableModelCallback));
    
    private static void AttachObservableModelCallback(DependencyObject source, DependencyPropertyChangedEventArgs args)
    {
        var typeName = args.NewValue as string;
        var view = source as FrameworkElement;
        if (typeName == null || view == null)
            return;

        var modelType = Type.GetType("Raven.Studio.Models." + typeName) ?? Type.GetType(typeName);
        if (modelType == null)
            return;

        try
        {
            var modelInstance = Activator.CreateInstance(modelType);
            var observableType = typeof(Observable<>).MakeGenericType(modelType);
            var observable = Activator.CreateInstance(observableType) as IObservable;
            var piValue = observableType.GetProperty("Value");
            piValue.SetValue(observable, modelInstance, null);
            view.DataContext = observable;

            var model = modelInstance as Model;
            if (model == null) 
                return;
            model.ForceTimerTicked();

            SetPageTitle(modelType, modelInstance, view);
            
            view.Loaded += ViewOnLoaded;
        }
        catch (Exception ex)
        {
            throw new InvalidOperationException(string.Format("Cannot create instance of model type: {0}", modelType), ex);
        }
    }
    
    private static void ViewOnLoaded(object sender, RoutedEventArgs routedEventArgs)
    {
        var view = (FrameworkElement)sender;
        var observable = view.DataContext as IObservable;
        if (observable == null)
            return;
        var model = (Model)observable.Value;
        model.ForceTimerTicked();

        var viewModel = model as ViewModel;
        if (viewModel == null) return;
        viewModel.LoadModel(UrlUtil.Url);
    }

For information about the ModelAttacher pattern, take a look on this blog post.

What it means basically is that we creating a models for each page, but never dispose it. So basically each time you navigate to a page, a new view model is created for the page but the old one never got cleaned up.

There was more examples like that, where we have an event keeping a reference to a dead objects. You can look on the RavenDB commits log if you interested in the details. But what is the way to solve this?

In order to solve this I copy the WeakEventListener from the Silverlight Toolkit, which is internal class. Using the WeakEventListener in order to attach to objects solved the above memory issue since we don’t have a strong reference to the dead object anymore, and the GC can just clean them up.

Model Attacher pattern in Silverlight applications

A while ago, when we started to develop our next version of RavenDB Studio, one of our goals was to make its code as simple as possible. That way, we ensure that it is easy to understand what is going on, so making changes to the Studio should be a trivial task.

In order to achieve that, we decided to not use any MVVM toolkits, but simply use a simple pages (views) and attach a model to them. In this approach, every view (page) know how to resolve its view-model by itself. This makes the Silverlight code much more simple, since it let’s you open a specific view by just navigating to its relative URL.

In order to make this possible we have a ModelAttacher.AttachModel attached property on the page, which takes care of instantiating the view-model and attach it to the page’s DataContext property.

Take a look on the following tipical view (page) in order to see it in action:

<Infrastructure:View x:Class="Raven.Studio.Views.Home"
                     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                     xmlns:Infrastructure="clr-namespace:Raven.Studio.Infrastructure"
                     Title="Home"
                     Style="{StaticResource PageStyle}"
                     Infrastructure:ModelAttacher.AttachModel="HomeModel">

</Infrastructure:View>

In this example, we have an empty Home view, which is make a use of a HomeModel. The ModelAttacher’s job here is to create an instance of the HomeModel class and attach it to the View.DataContext property. (The view is a simple class that derives from Page.)

This is how ModelAttacher works, in order to achieve this:

namespace Raven.Studio.Infrastructure
{
    public static class ModelAttacher
    {
        public static readonly DependencyProperty AttachModelProperty =
            DependencyProperty.RegisterAttached("AttachModel", typeof(string), typeof(ModelAttacher), new PropertyMetadata(null, AttachModelCallback));
        
        private static void AttachModelCallback(DependencyObject source, DependencyPropertyChangedEventArgs args)
        {
            var typeName = args.NewValue as string;
            var view = source as FrameworkElement;
            if (typeName == null || view == null)
                return;

            var modelType = Type.GetType("Raven.Studio.Models." + typeName) ?? Type.GetType(typeName);
            if (modelType == null)
                return;

            try
            {
                var model = Activator.CreateInstance(modelType);
                view.DataContext = model;
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException(string.Format("Cannot create instance of model type: {0}", modelType), ex);
            }
        }

        public static string GetAttachModel(UIElement element)
        {
            return (string)element.GetValue(AttachModelProperty);
        }

        public static void SetAttachModel(UIElement element, string value)
        {
            element.SetValue(AttachModelProperty, value);
        }
    }
}

Now in order to attach a model to its view, we need to just add the attached property to the view element:  Infrastructure:ModelAttacher.AttachModel="HomeModel".

Please note that in this case any view-model has to have a default (parameters-less) constructor. In order to solve that, what we have done in RavenDB Studio is to have a ModelBase class for our view-models which make sure to expose all our common model dependencies.