Over a million developers have joined DZone.

The Siren Song of the Framework

Between reinventing the wheel and cobbling together a system out of frameworks, there is the challenge to find the middle ground of low maintenance, low complexity, and high performance.

· Performance Zone

Evolve your approach to Application Performance Monitoring by adopting five best practices that are outlined and explored in this e-book, brought to you in partnership with BMC.

In a recent blog post, I talked about a problem we found in NLog with our usage scenario. I mentioned that we’ll probably have our own solution to fit our needs. Eric Smith replied with:

So I guess there is no chance of contributing to the NLog project to improve it instead of creating yet another logging framework?

And the short answer for that is that there is very little chance for that. Primarily because what we are doing is not really suitable for consumption elsewhere.

Let us consider something that we found to be very useful. Metrics.NET is a great way to get various metrics, and we have been using it (and contributed to it) for several years. But when looking at our 4.0 work, we also looked at what it would take to support metrics, and we had to flat out reject Metrics.NET for our use. Why is that?

Primarily because it is doing too much. It is extremely flexible and can do quite a lot, but we don’t need it to do a lot, and we don’t want to pay for the stuff we don’t use. For example, Histograms. The problematic issue for us was here:

public void Update(long value, string userValue = null)
{
    this.last = new UserValueWrapper(value, userValue);
    this.reservoir.Update(value, userValue);
}

Which ends up calling:

public void Update(long value, string userValue = null)
{
    long c = this.count.Increment();
    if (c <= this.values.Length)
    {
        values[(int)c - 1] = new UserValueWrapper(value, userValue);
    }
    else
    {
        long r = NextLong(c);
        if (r < values.Length)
        {
            values[(int)r] = new UserValueWrapper(value, userValue);
        }
    }
}

So that means that we’ll have two allocations for each time we update the histogram, which can happen a lot.  We don’t want to pay that price.

Now, we can certainly modify Metrics.NET to meet our needs, in fact, we have done just that, and ended up with about 6 files that we needed, after we cleaned them up according to our current requirements. Contributing them back wouldn’t make much sense, they are full of constraints that are meant to allow us to run a database server for months on end with predictable and reliable performance under very high load. They don’t make sense in many other scenarios, and it can be incredibly limiting.

For a logging framework, we can most certainly add another option to NLog to do what we consider the right thing, but at this point, that wouldn’t really make sense. We don’t use a lot of the features, and reduce the surface area would mean reducing complexities. We can target something very narrow and get very high performance (in both CPU utilization and memory costs) much more easily & cheaply than trying to convert an existing codebase.

This is not a new concept. There is a very real cost to making something reusable. And in our case, RavenDB doesn’t need frameworks internally, we have a very good grasp of what is going on, and we want to have full ownership of every bit that is executed.

Learn tips and best practices for optimizing your capacity management strategy with the Market Guide for Capacity Management, brought to you in partnership with BMC.

Topics:
.net ,framework ,frameworks ,performance

Published at DZone with permission of Ayende Rahien, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

SEE AN EXAMPLE
Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.
Subscribe

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}