I sat down to write some notes before starting this blog entry, and I wound up with two full pages in OneNote on the 1920×1200 monitor it was sitting in. The more I’ve been working on it the more I’m excited about the Paint.NET v3.5 release. It isn’t one that introduces a lot of really cool or big-ticket features, but the list of small improvements is really adding up. I’ve been able to do a lot of research and prototyping in esoteric areas of multithreading and concurrency, and have gained both more mastery and more fear for these topics.

Performance work in Paint.NET v3.5 has wound up focusing on 3 areas:

  1. Scaling up. As everyone’s been saying for years, the future is increasingly multithreaded. My newest CPU upgrade leaves me with 8 threads in Task Manager (Intel Core i7 overclocked to 3.8GHz). A lot of research and work has gone into making sure that Paint.NET continues to scale with more threads, and that I have better tools for safely and correctly implementing this across more of the application.

    ”A high-end 64-bit Intel Core i7 desktop should run Paint.NET very fast.”


  2. Scaling down. Those $300 netbooks that are taking everyone by storm only run about as fast as what I was using 7 years ago (Pentium 4 at 2.0 – 2.5ghz). Clearly, classic optimization strategies are important as well: trimming cycles, removing or deferring code execution, and optimizing repainting.

    “A brand-new netbook with an Atom processor should run Paint.NET comfortably.”

  3. Reducing memory usage. I guess this goes with scaling down. I made a bet a long time ago that 64-bit would slowly take care of the way I was allocating memory, which simplified development work but has had the consequence of consuming vast amounts of virtual address space . I was wrong: 32-bit will be here for a long time, especially since most of those hot-like-pancakes $300 netbooks are not 64-bit capable. This is currently my top reliability issue, as running out of memory causes Paint.NET to crash.

    ”It’s not all yours.”

I’ve had to split this discussion over several blog entries because otherwise it was too long and even I would have fallen asleep reading it. I’ll summarize the results here though:

  • Images open much faster, especially on single-core/single-thread systems. Actually, I already wrote about this, so go read that first 🙂
  • I ordered and assembled my own Atom-based mini-desktop (“nettop”), in order to keep myself honest as I was working on my Core 2 Quad QX6700 2.67 GHz monster and subsequently as I upgraded to a Core i7 920 2.66GHz overclocked to 3.8 GHz.
  • The selection renderer has been completely rewritten. No more dancing ants and no more GDI+ means much lower CPU usage and better performance with multiple CPU cores.
  • Much better CPU scaling for the image composition rendering pipeline using LINQ-esque functional programming and deferred execution techniques.
  • A rewritten “render cache” has resulted in an average of 30-50% less memory usage when opening multiple images, especially those with just a single layer (PNG, JPEG). This means fewer out of memory crashes, and the ability to open more images without out-of-memory errors.

Paint.NET v3.5 is a stepping stone towards a hopefully epic v4.0. I’m slowly rebuilding the application from the inside out, and it takes a lot of time to do the necessary research and development. About 2 years ago, right around the time I was preparing to release Paint.NET v3.0, I had this nagging feeling in the back of my head that said basically “ur doin’ it wrong”. My document model was wrong, my application model was brittle, and I just couldn’t implement really cool features without using up a ton of memory. I also couldn’t provide features like scripting or a better extensibility model (plugins) in a manner that was both safe and powerful.

However, I didn’t really know how to solve all of this at a scale lower than the 50,000-foot view. Since then I’ve been slowly piecing together the tools and knowledge that I’ll need to create the best version of Paint.NET ever – one that’s great both outside (for users) and inside (for developers).

Now, if you’ll excuse me, I’ve got to stop breaking things and start fixing them so that I can push out an alpha release.