Python Programming, news on the Voidspace Python Projects and all things techie.
IronPython on Balloons
My colleague Andrzej Krzywda has done a new blog entry. This is on creating balloon event notifications with IronPython.
Andrzej and I will be doing a presentation at PyCon on IronPython and Windows Forms. We haven't yet met to put together our presentation, we were meant to meet tonight but I'm still off work. I have put together the start of a simple demo app. which might form the crescendo of the presentation. We'll see.
Cough, Sneeze, Writing and Optimisation
I've got a cold and I'm going to bed. Before I do I'll give you a quick update.
Writing is now well underway. I've basically finished the first draft of the first chapter. It was very difficult, which I kind of expected. The first chapter is mainly a hand-wavy introduction and overview chapter, and it is harder to explain such well-defined terms as 'dynamic language' without going into concrete details.
I've also made a start on chapter two and am finding it much easier to get 'into the flow'.
At work we've just finished our fourth optimisation user story. They always turn out to be the most fun user stories to work on, and it is very satisfying to dramatically improve the performance of Resolver through a few days work and a handful of clever tricks.
This user story was improving the error handling of Resolver. The goal was to get Resolver processing data sets in under a second: with one hundred errors. We got most of the way there with our own version of traceback.extract_tb, that I wrote about before. We got another big boost with some nifty caching, but our performance test was still reporting a processing time of around 1.5 seconds.
When we instrumented our code to track down where the time was being spent we discovered something very odd. For the first 100 runs through, as we added the errors, the processing time was well below a second. As soon as the functional test timed the process, it took twice as long.
After much puzzlement we tracked it down. The difference was that once we started timing the process we use SendKeys.SendWait to send a keypress that triggers the processing.
Using SendKeys in this way was causing Resolver to take twice as long.
Once we changed the test to use something else we could mark the story complete. Hooray.
We use SendKeys a fair amount in our functional tests, but not in our performance critical tests now. In fact we find it to be horrendously unreliable. We have a method on our FunctionalTest base class called sendKeysTenaciously. It is for entering characters into text boxes, and sends each character individually and then checks it has arrived...
We created a nifty PerformanceTest base class for use with unittest. It runs the test (supplied in the subclasses that implements each test) ten times and checks that no more than two of the results are outside the specified limit. (Every set of runs has outlying times.) The limit is modified per machine as some of our computers are faster than others. It pushes the results into a database with the machine name, test name and SVN repository ID. This means we can track the performance of various aspects of Resolver. If performance starts to degrade we can track the change across checkins.
Anyway, I'm only writing this because I feel rotten. I'm afraid there'll be much less on this blog for the next few months.
This work is licensed under a Creative Commons Attribution-Share Alike 2.0 License.