Archive

I’m pleased to announce that the first Community Technical Preview of PostSharp 2.1 is available for download.  Note that you have to register to the Early Access Program before you can access download. Registration to the EAP is free for anybody.

As any CTP, this release is meant for testing and not for production use.

PostSharp 2.1 is a minor upgrade to PostSharp 2.0, which means that your existing license key should just work.

What’s New in PostSharp 2.1 CTP 1?

This first CTP is all about improving build-time performance, i.e. making PostSharp compile faster.

Much faster.

Here are the results measured by Bartek Legiędź and Remigiusz Cieślak, software engineers at Comarch in Poland. Their setup consists of a small number of very large projects (assemblies of several megabytes). As you can see, PostSharp 2.1 is more than five times faster than 2.0.

The next table compares the time taken by PostSharp while building the solution in two configurations (debug and release). Of course PostSharp itself ran in release mode both times.

Build Configuration2.0 2.1 Speedup
Debug Configuration 160,662 ms 21,293 ms 672%
Release Configuration 121,694 ms 23,897ms 571%

Thanks guys for your time doing this benchmark!

The performance improvement you will experience with your setup depends on several factors: size and number of projects, number of aspects, and hardware resources. Also, remember that PostSharp is only a part of the build process. After upgrading to PostSharp 2.1, the build time may be dominated by the C# compiler or by Code Contracts.

I would like to hear about your own experience of performance improvements.

Here is how to produce benchmark results:

  1. Wait until the system load is stably low (TortoiseSVNCache.exe and similar processes may load your processor)
  2. Execute: Msbuild /p:Configuration=Debug /clp:PerformanceSummary /t:rebuild > msbuild-2.0.log
  3. Upgrade your project to PostSharp 2.1 (see below)
  4. Execute: Msbuild /p:Configuration=Debug /clp:PerformanceSummary /t:rebuild > msbuild-2.1.log

The performance report lays near to the end of the log file, above the summary of warnings and errors. For greater accuracy, you should execute MSBuild three times with every version of PostSharp, and take the best results. Then you can send me both performance summaries by email (gael@sharpcrafters.com) so I can see how large are improvements with real-life projects. Frankly, I don’t expect 500% improvement for everybody.

What Changed in PostSharp 2.1 CTP

Most performance improvements were obtained by replacing the component that writes back the assembly to disk. Before version 2.1, PostSharp still used  our ol’ good text-based writer, backed by Microsoft’s ILASM. This required a lot of I/O just to create the text IL file (some customers reported files of several hundreds of megabytes), then ILASM required a lot of CPU and memory to process it. Fortunately, this was not that bad and there were excellent reasons to keep this writer. Now we have our own assembly writer, coded by your servant himself, and tuned with all the obsession and passion he is able of.

You should normally not observe any difference from PostSharp 2.0, except of compilation speed. Debugging support may be a little improved because I integrated some bits of the Microsoft CCI PDB reader/writer into PostSharp, but this debugging support is still to be fine-tuned.

So except this, there’s no change in this CTP, no addition of feature.

Redefinition of the Community Edition

The Community Edition is being renamed Starter Edition, because the former name did confuse many people.

We’re doing two little changes in the features available to the Starter Edition:

  • The Aspect Dependency Framework (PostSharp.Aspects.Dependencies) will not be available any more in the Starter Edition. Frankly, this feature was present by mistake, since it clearly supports “pro” scenarios. To order aspects, Starter users will have to use the AspectPriority attributes, i.e. they will have to assign an integer to every aspect.
  • The Starter Edition will not run from source control. It will have to be installed on the computer.
  • Yes, the new build-time performance enhancements are available to the Starter Edition!

So we add a lot and we remove a little in order to position the Starter Edition as a light tool for individuals, and the Professional Edition as – well -- a professional tool for teams. We do not push anyone in the corner. You all have workarounds: installing the product or using AspectPriority. We are just getting clearer about the positioning of each edition. We think we’re adding more comfort to the Starter Edition than we actually remove.

And remember: PostSharp is cheap (usually less than one day of bill), and we give a lot of discounts to students, Microsoft BizSparks members, or influencers.

Upgrade to PostSharp 2.1 CTP

PostSharp 2.1 CTP can be installed side-by-side with PostSharp 2.0 on the same machine. At build time, the correct version of PostSharp should kick in, according to the version of PostSharp.dll your project is referencing.

There is one exception to this rule. The Visual Studio Extensions (VSX) cannot be installed side-by-side, so the setup program of PostSharp 2.1 will remove the VSX of PostSharp 2.0 and replace it by the new version. Since it’s backward compatible, the VSX 2.1 will work with projects using PostSharp 2.0.

Once you’ve installed PostSharp 2.1 (or copied it to your source control), you can run the PostSharp 2.1 Conversion Utility (PostSharp.Convert.exe), a simple application that let you update your references from previous versions to the current one. The utility is also able to prepare your project to run PostSharp from source control, if you prefer not to install it using the setup program. Note that all this utility does is to edit your csproj or vbproj files.

Gotcha: When a project references both PostSharp 2.0 and 2.1

What happens if you have a project that has been migrated to PostSharp 2.1, but uses a component (such as Gibraltar aspects) that has not been? The project would have a direct reference to PostSharp.dll version 2.1, and an indirect reference to PostSharp.dll version 2.0.

  1. Make sure that the old PostSharp.dll dependency is not copied to your final bin directory. At run-time, you will need the version 2.1.
  2. Install the last hot fix of PostSharp 2.0.
  3. Add the following code to your application configuration file:
<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="PostSharp" publicKeyToken="b13fd38b8f9c99d7" 
culture="neutral" /> <bindingRedirect oldVersion="2.0.0.0" newVersion="2.1.0.0" /> </dependentAssembly> </assemblyBinding> </runtime> </configuration>

Therefore, our partners don’t need to recompile their product for every of our minor version, and you can always use the version of PostSharp you would like.

What’s Next?

We did our best to address the major painful point reported by users: building time. We tested the new PE writer on large and complex assemblies like those forming the .NET framework itself. Now we want to hear from you:

  • Does it work for your projects?
  • What are the performance gains?

In the mean time, we’ll be working on the next CTP, which should bring some minor new features. Then there’ll be the cycle of RC and finally the winner RC will be promoted RTM.

Happy PostSharping!

-gael

Marcus King recently released 3 screencasts showing how to address exception handling and caching.
We asked him to introduce his work in this guest post.

How often do I have to keep solving the same problem?  As developers we’ve all been there, each project we work on we have to do the same ole’ thing we’ve done a thousand times before.  Luckily in most cases there are good native features built into the language or third party frameworks that are available to reduce the tedious chore of writing basic code yet again.  However, there are a lot of times when OOP doesn’t provide us with a good way to solve a recurring problem.  I’m guessing since your reading the SharpCrafter’s Blog you see that this is the point where AOP steps in and fills the gap left by OOP.  I recently did a video tutorial on improving exception handing  using AOP via PostSharp.  Traditionally in applications we need to catch when certain exceptions are thrown and do something with the exception by either logging it, calling another workflow, wrapping the exception inside of another one, or simply swallowing the exception, or some combination of all.  Let’s say for example we have a class we use to call a remote web service to retrieve data for our application.

public class StockService
{
    public StockDetails GetStockDetails( string symbol )
    {
        try
        {
            //.... call to service
        }
        catch ( SoapException ex )
        {
            throw new StockServiceException( "Error Getting Details", ex );
        }
    }

    public decimal GetHistoricalPrice( string symbol )
    {
        try
        {
            //.... call to service
        }
        catch ( SoapException ex )
        {
            throw new StockServiceException( "Error Getting Historical Price", ex );
        }
    }

    public void AddToPortfolio( string symbol, int shares )
    {
        try
        {
            //.... call to service
        }

        catch ( SoapException ex )
        {
            throw new StockServiceException( "Error Adding to portfolio", ex );
        }
    }
}

Look how often we are repeating the same basic pattern.  We’re making our service call and wrapping any SoapException that is thrown in a custom StockServiceException.  Using PostSharp we are able to modularize our code and make the business logic of the StockService class look so much cleaner.

public class StockService
{
    [HandleException( SoapException, StockServiceException, 
"Error Getting Details" )] public StockDetails GetStockDetails( string symbol ) { //.... call to service } [HandleException( SoapException, StockServiceException,
"Error Getting Historical Price" )] public decimal GetHistoricalPrice( string symbol ) { //.... call to service } [HandleException( SoapException, StockServiceException,
"Error Adding To Portfolio" )] public void AddToPortfolio( string symbol, int shares ) { //.... call to service } }

All we need to do is create an attribute that derives from OnMethodBoundaryAspect that accepts three parameters in the constructor;  the type of exception to handle, the type of exception to wrap the caught exception in, and a message to give to the wrapped exception.

[Serializable]
public class HandleExceptionAttribute : OnExceptionAspect
{
    private Type _expectedException;
    private Type _wrapInException;
    private string _message;

    // Constructor that takes in variable parameters when the attribute is applied
    public HandleExceptionAttribute( Type expectedExeptionType, Type wrapInExceptionType, 
string message ) { _expectedException = expectedExceptionType; _wrapInException = wrapInExceptionType; _message = message; } // This method checks to see if the exception that was thrown from the method the // attribute was applied on matches the expected exception type we passed into the
// constructor of the attribute public override Type GetExceptionType( MethodBase targetMethod ) { return _expectedException; } // This method is called when we have guaranteed the exception type thrown matches the // expected exception type passed in the constructor. It wraps the thrown exception
// into a new exception and adds the custom message that was passed into the constructor public override void OnException( MethodExecutionArgs args ) { args.FlowBehavior = FlowBehavior.Continue; Exception newException = (Exception) Activator.CreateInstance(
_wrapInException, new object[] {_message, _expectedException} ); throw newException; } }

Another common problem set I solve with PostSharp is caching expensive method calls. I find myself repeating the same basic pattern in projects when I need to implement caching. I’m sure you’re familiar with it.

public Account GetAccount( int accountId )
{
    string cacheKey = string.Format( "GetAccount_{0}", accountId );

    Account account = Cache.Get( cacheKey );

    if ( account == null )
    {
        account = accountRepository.GetAccount( accountId );

        Cache.Add( cacheKey, account );
    }

    return account;
}

We build our cache key and check to see if the item is present if the cache. If it is we return the value pulled from the cache, otherwise we do the necessary work to retrieve/build the item to return and save it in the cache with the cache key we built so that the next time this method is called we can successfully pull the item from the cache. I’ve repeated this pattern over and over again, typically in a business layer when I need to retrieve data from an expensive resource like a database or a web service call or when I do complex logic to construct the object that I need to return. Luckily PostSharp provides a way to centralize all of the caching logic for me so I can concentrate on the business logic. The same method now looks like this

[Cache]
public Account GetAccount(int accountId)
{
    return accountRepository.GetAccount(accountId);
}

Once again I simply adorn the method with an attribute and it handles a lot of the repitive code. Here is what the Cache Attribute/Aspect code looks like.

public class CacheAttribute : OnMethodBoundaryAspect
{
    public override void OnEntry( MethodExecutionArgs args )
    {
        string key = args.Method.Name + "_" + Cache.GenerateKey( args.Arguments );

        object value = Cache.Get( key );

        if ( value == null )
        {
            args.MethodExecutionTag = key;
        }

        else
        {
            args.ReturnValue = value;

            args.FlowBehavior = FlowBehavior.Return;
        }
    }

    public override void OnSuccess( MethodExecutionArgs args )
    {
        string key = args.MethodExecutionTag.ToString();

        Cache.Add( key, args.ReturnValue );
    }
}

In the OnEntry method I’m building the cache key and checking to see if the item exists in the cache and if so I’m not letting the target method complete and I’m returning the value pulled from cache. If no item was found in the cache, the execution of the target method proceeds and when the target method successfully executes the OnSuccess override is fired and the item is stored in the cache.

There are a lot more interesting things to do with the two areas of caching and exception handling so I would encourage you to check out my screen casts to learn more.

Exception Handling: http://www.sharpcrafters.com/media/tutorials/exception-handling

Cachinghttp://www.sharpcrafters.com/media/tutorials/caching-1

Going Further with Cachinghttp://www.sharpcrafters.com/media/tutorials/caching-2

 

marcus_king_image

Marcus King is a Software Engineer based in Louisville, KY. He has a broad IT background ranging from infrastructure security to software development, with years of experience working for many different sized companies, from Fortune 100 to small web startups. Marcus is passionate about performance tuning applications, developing solutions for highly scalable applications, plus is heavily involved in discovering and setting standards and best practices for software development. An Aspect-Oriented Programming (AOP) champion, Marcus regularly gives presentations on the topic. In his free time he writes applications for iPhone and Android and is on the executive committee of the codepaLOUsa developer conference in Louisville, KY.