Sunday, September 09, 2007

Performance Driven Refactoring

I have recently talked about how fun it is to refactor code in order to increase its testability. Similarly, I have discovered another kind of refactoring driver: performance.

Starting to load test and performance profile an application you have developed is always an exhilarating time: I compare this with the Whack-A-Mole game, where, instead of funny animal heads, you hammer your classes down the execution tree until most of the time gets spent in code that is not yours.

Interestingly, I have seen the design of my application evolve while optimizing the critical parts of it. It is truly refactoring, as no feature gets added, but the code gets better performance wise.

Consider the following example that has arisen. Here is the original application design:

Profiling shown that computing the values of the context was really expensive and that these values were not always used by the target object.

I refactored to the following design:

In this design, the context values are only computed when the target object requests them, using a simple callback mechanism.

One could wonder why I did not simply remove the original context object and made O2 call O1. This would work but would have several disadvantages:
  • unnecessarily increasing coupling between these two classes,
  • visible design change, while I wanted the refactoring to respect the existing contracts between objects (the context in that case).
In conclusion, there are many good reasons for refactoring: the quest for performance can be a very valid one!

4 comments:

Perrine said...

Just one word about the picture of yourself. It is better than the previous. ;-)
Performance quest is a very tricky one. There is the cpu(s), the memory, the I/O, the network, ... and the tools for measuring.
There is no tool easy to use for any developper to help in this quest. So the quest for performance focus on system tuning, not on code tuning. We are missing a great part in this case.

David Dossot said...

In this particular project, I used JMeter to load my application and YourKit to measure the CPU and memory usage.

As said, this did not cover all aspects of the problem: I/O and networking were left out...

(Thanks for the picture ;-)

landrain said...

> there are many good reasons for refactoring: the quest for performance can be a very valid one!

This is a very good one, David.
My experience tells me that performance is often the forgotten part in the IT projects. I'm always very frustrated when I propose an optimisation and hear a response like "no, it's fine for me like that. I don't really care about speed". What are the future users thinking about this ?Unfortunately, that position is often backed up by the project managers who think their only responsibility is to get the code working well, no matter how fast it is [this is with them that you really want to play the Whack-A-Mole game]. Of course, it's not possible to fully optimize all the parts of a project, but if you develop with a few best practices, and (good) design patterns are one of these, you can avoid most of the needs for optimisation at a later stage.

David Dossot said...

Maybe managers heard about premature optimization and now, erroneously, consider all sort of performance refactoring to be too early?

Next time, ask your manager to read this page about software quality attributes.

They will see that neglecting performance, like any of the other attributes, amounts to neglecting quality.

And managers love quality, right? ;-)