Friday, May 22, 2009

Speed Improvements... and Profiling.

It's incredibly important to profile before you begin to try and do any optimizations. The reasons for this should be obvious, but I've caught myself trying to do optimizations without profiling first. Bad idea. Sometimes you make things worse. It's also important to profile after every single change and not change multiple things at once. This lets you quickly determine if a change was good or bad.

MapX and RowValues

MapX is a 3rd party tool that displays geographical data. It is available from MapInfo (now owned by Pitney-Bowes) and is quite useful. It also hasn't been updated in about 7 years, since they have a new product called MapXtreme (what's so extreme about it?). Which means that we are stuck trying to pull performance out of a legacy application again that, well, isn't going to get any faster on it's own.

I made an interesting discovery a few weeks ago regarding accessing datasets. A dataset, in MapX terms, is a set of data associated with geographical data. While the map data (lat,long) is stored in a map file, the data is stored in a proprietary data format with a link between the data and the map object. There are times when we need to pull lots of data to display it to the user (an info tool, for example, so you can query what an object is on the map).

To access the data, you can directly refer to the dataset using the object's feature key. Something like:
strValue = dataset(feature key, field)
This works, but once need to query more than once against a row (or feature key), then it makes more sense to use a RowValues object, which is easy enough:
set rowValues = dataset.RowValues(feature key)
strValue = rowValues(field).Value
And there we go. For one value, the timing is similar. Once you do several requests in a row, however, it gets much faster. The more fields you read in a row, the higher the speed increase (economy of scale!).

Visual Basic 6 and Combo Boxes

Another fun thing discovered this week is that Visual Basic 6 is slow when adding lots of items to a combo box. How much is lots of items? Try 12,000 unique strings! So, off we go trying to find a better way. And, sure enough, there is a fairly simple way, as long as you don't mind getting your hands dirty with the windows messaging system api.

So we go from:
combobox.add "this string"
To:
SendMessage combobox.hWnd, CB_ADDSTRING, 0, ByVal "this string"
Simple enough, for a 50% time decrease for 12,000 items... from 1 second to 1/2 a second! Very good stuff.

MapX and Display

Some times measured speed doesn't mean that much to a user if it appears the system is hung and not doing anything at all.

Interestingly enough, MapX's map control has a setting called RedrawInterval. This setting sets how long between map redraws while the control is generating data to be displayed. A lower setting means that the map will be redrawn more frequently. A higher value means that the map won't update until it is done or the time has run out. When viewing a small section of a map, this doesn't make much difference.

What we discovered though, is that when a user is zoomed out to seeing a radius of 10km's worth of mapping data, the map is taking a while to redisplay for big cities. This makes sense, since there is a lot of road data to display for a large city... but, as it turns out, our RedrawInterval was set to 300, which translates to 3 seconds (who works in 1/100ths of a second?).

Setting it to the minimum of 10 (so 0.1 seconds) actually results in a perceived speed increase. Why? As it turns out, MapX draws each layer in sequence internally before displaying them. Since we have about a dozen layers (County, City, Railroads, Roads, Highways, etc...), this means that updates to the screen start happening sooner. Overall, the time taken to completely redraw the screen is longer (not by much, for larger cities it is about 2-3% slower on average, it's negligible for smaller cities/towns.), but, to the user, it appears to have drawn faster since they can see updates happening.

Wednesday, May 20, 2009

Printing from a Service...

We've been working on adding the ability to create PDF files on the server side of our application. This sounds much easier than it is. Our server base is IBM UniVerse (how many people can say they are familiar with that?), an older multivalued database system. On top of being a multivalued database, it is also, essentially, a runtime environment.

To complicate this, the items that need to be printed are HTML documents, with some custom javascript that needs to run before the file can be printed (mostly to correct faulty HTML mistakes by people who have no clue about HTML -- but that's another topic for another day). So that means we need to run it through Internet Explorer. But wait, the complications are still not done! We use MeadCo's ScriptX to do the actual printing, since printing through IE's own engine is both complex and unreliable.

So, add all this together to try printing from a single source location.

Several "easy" solutions were tried first, some killed by the boss (due to too much interaction required from users, most of whom are quite unskilled with computers), some killed due to their technical limitations (IBM UniVerse offers the ability to shell out to DOS, but this lacks a windows context, so IE doesn't run properly -- ie: no javascript can be fired off).

So we came up with several proposals, of which one was approved by management for moving forward: build a window service that could print these pdf documents by running a small program that encapsulates the IE engine, thus providing a windows context for the printing.

Seemed so simple then. From that point on, things went all over the place.

Getting IE to run with a windows context was easy enough. Getting our ScriptX related javascript to run took a little more effort, but was manageable. Then came the brick wall. Sure, it works fine on XP running from the service account. What about Server 2k3? Or Vista?

Sure enough, changes to the way the service account runs starting in 2k3 meant that our solution no longer worked that well... Services in 2k3/Vista run in session 0, same as XP. However, that level is now isolated from users. In other words, only certain resources are now available to the service account. And, sure enough, Printers aren't one of them.

MSDN notes that the printing namespace isn't available from windows services (or at least not supproted) [1]. I'm obviously not the first person who's run into issues with printing from a service (StackOverflow questions: 1, 2, 3).

So, for now, we've gotten around it by creating a local account that has the printer available to it. This is far from an ideal solution and I continue to look for a solution that allows me to see printers from a 2k3/Vista windows service...

Friday, May 8, 2009

Gary Bettman and the NHL

I will be the first to admit that Gary Bettman has done some great things to help grow the NHL. The numbers sort of speak for themselves ($440 million in 1993 to $2.2 billion in 2007).

That said, I wish he would get lost.

While I would love to see another team come to Southwestern Ontario, I realize that as long as Bettman is there, it won't happen.

But my biggest complaint, by far, is the following line from Bettman:
“We generally try to avoid relocating franchises unless you absolutely have to,” he said. “We think when a franchise is in trouble, you try and fix the problems. That’s what we did in Pittsburgh and Ottawa and Buffalo prior to our work stoppage. That’s what we did when the perception was that five out of the six Canadian franchises around the turn of the century were in trouble. We fixed the problems. We don’t run out on cities.”

We don't run out on cities?

Would you like to tell that to the cities that have lost franchises since you became the comissioner? I'm willing to let Minnesota (1993) slide, since they were leaving when you got into the league and they now have a team back.

But what about Quebec City (1995)? Winnipeg (1996)? Hartford (1997)? Three great cities where hockey was appreciated. But I guess they don't fall into big business.

On top of that, let's take a look at the four franchises Bettman let into the NHL:

Nashville (1998): Barely alive, constantly looking for investors, can't sell out an arena.
Atlanta (1999): While more financially stable than Nashville, they haven't been able to convince anybody to want to play for them.
Columbus Blue Jackets (2000): Although it's in Columbus, it is doing okay as a team. Not super financially stable, but doing reasonably well in comparison to the last two.
Minnesota (2000): Oh look, hockey is back in a hockey town! After the last one was move for purely business reasons, this team is doing well, with great fans. Unfortunately, they have trouble convincing people to play in Minnesota.

And that's not even looking at where he relocated teams to. Carolina? Do they need a hockey team? Or what about the currently floundering Phoenix Coyotes? How many times does the rest of the league need to bail a team out (to the tune of $35 million dollars!) before they realize that they could move it to a better market?

But this is Bettman, he doesn't give up on cities... Unless you're a Canadian or Northern US team, that is.