Archive for the ‘Coding’ Category

MacVim Team Drops Snapshot 34

Monday, September 8th, 2008

MacVim.jpg

This morning I got a notice on the MacVim Google Groups that they cut Snapshot 34 and so I had to go get it and kick the tires. It's great that MacVim is available - and the updates they make to it are really amazing. Now there's a plug-in interface to be able to write add-ons without digging into the core code. Incredible. Not Vim macros... compiled plug-ins. Cool.

This is something that I love having and use it all the time.

Faster Launching MacVim Windows – Don’t Fork

Friday, August 29th, 2008

MacVim.jpg

I read an interesting message on the MacVim mailing list this morning about the speed of opening new windows with the mvim command - a shell command that's included in the MacVim package. What the developer (the main maintainer) did was to time several ways of opening up the window and the sub-components of that process. What he found was that the fork() was about two-thirds of the time! Surely, there is a faster way to do this.

And there is... he even had an answer: don't fork on opening a new window from the command line. The change to the mvim script is pretty easy. Change the script from:

  1. if [ "$gui" ]; then
  2. # Note: this isn't perfect, because any error output goes to the
  3. # terminal instead of the console log.
  4. # But if you use open instead, you will need to fully qualify the
  5. # path names for any filenames you specify, which is hard.
  6. exec "$binary" -g $opts ${1:+"$@"}
  7. else
  8. exec "$binary" $opts ${1:+"$@"}
  9. fi

to:

  1. if [ "$gui" ]; then
  2. # Note: this isn't perfect, because any error output goes to the
  3. # terminal instead of the console log.
  4. # But if you use open instead, you will need to fully qualify the
  5. # path names for any filenames you specify, which is hard.
  6. exec "$binary" -g -f $opts ${1:+"$@"} <&0 &
  7. else
  8. exec "$binary" $opts ${1:+"$@"}
  9. fi

This takes the launch time from a little over a second on my MacBook Pro to less than half a sec. OK, sure... is this that important? No, of course not, but the change is not bad, either. Not forking is a good way to keep system load down. Doesn't hurt, and that it's faster is even better.

So... if you're using MacVim - think about updating the mvim script and try it. It's a good idea.

Lots of Pricing Fun this Morning

Friday, August 29th, 2008

MarketData.jpg

We have had an upgrade of our infrastructural ticker system - that which my ticker plant is based on. It happens - things move forward, get better, all that. The problem has been that for the last two days - that's the first two days of the new infrastructure, we've had a good number of pricing issues from this new infrastructure. Not good.

So I was very interested in getting to the bottom of these issues today so that we don't have the same problems next week. What I learned from my contact in the infrastructural team is that this was a bug in their stuff when they restarted it. If we do a clean restart - clearing the cache, after their restart, then we should be OK. They have a bug fix in testing and as soon as I can get ahold of it, I will and kick the tires and give it a good check.

I don't want to get caught in the position where I'm getting these wacky prices. It's a major pain. Like a 2:30 am phone call 'pain'.

BBEdit 9 is Out!

Thursday, August 28th, 2008

BBEdit.jpg

I saw a tweet this afternoon that BBEdit 9 is out! I had to get it. Well worth the $30 upgrade from 8.7.2 that I was using. The list of new and updated features is impressive. I like the 'Ponies' feature myself. 🙂

What I think I'm going to like most is probably the under-the covers changes like rendering speed and such. It will also be nice to have the ctags colored differently than the standard language-binding tags. I use ctags a lot in my code.

I might get into the habit of using the auto-complete with the delay timer. I'm not sure as I do a lot of typing very fast, and the odds that I'm going to hit that are slim, but it's something to play with.

I general, if you like BBEdit, get it. Great tool.

Fun with STL std::map Iterators and erase()

Wednesday, August 27th, 2008

cplusplus.jpg

Today I got a somewhat sketchy bug report that, if it was true, would possibly have pointed to a section in my code where I was deleting things from an STL std::map using the erase() method whose argument was an iterator on the std::map. The original code looked something like this:

  InstrumentAliasMap::iterator    ia = mInstruments.begin();
  while (ia != mInstruments.end()) {
    if (ia->first == anInstrument) {
      // found a match - erase it
      mInstruments.erase(ia);
    } else {
      // no match, check the next one
      ++ia;
    }
  }

where my thinking was that the iterator would be updated to the next, valid element after the erase. I think that was a major boo-boo. In all honesty, I didn't really know, but it seemed to test OK, and so it went. The problem is that after the call to erase() the iterator, ia, is invalid and can't be moved to the next valid element in the iteration.

I did a little searching on this as I was sure there was something simple about this. What I read was that the right way to do this was to take advantage of the properties of the post-increment operator which will increment the value (move it to the next element) but return the original value. So the code becomes:

  InstrumentAliasMap::iterator    ia = mInstruments.begin();
  while (ia != mInstruments.end()) {
    if (ia->first == anInstrument) {
      // found a match - erase it
      mInstruments.erase(ia++);
    } else {
      // no match, check the next one
      ++ia;
    }
  }

In this code, the iterator is moved to the next valid element and yet the original iterator value is returned to the argument of erase(). This then removes the element from the map and we're sitting on the next, good one.

I like this a lot more, and it's clear what I should have done all along. I won't forget this guy.

Dropping the ATSUI Renderer in MacVim for Now

Wednesday, August 27th, 2008

MacVim.jpg

I was doing some work with MacVim yesterday and I was a little disappointed to see a bunch of little 'blips' on the window. I'm a stickler for clean and while I know they said the ATSUI renderer might have some strange artifacts, I didn't expect to see them. Once I did, I knew I had to go back to the default renderer.

Also, with my tests, the redraw speed on my MacBook Pro is virtually identical for the two renderers. So there's no real solid benefit to putting up with these artifacts. Also, CoreText is supposed to be the way to go, and Apple might just slap the default renderer on CoreText and let that be that. Who knows? Anyway... for now, it's back to the default renderer.

Found a Few Lingering Bugs in BKJEP Parser

Wednesday, August 27th, 2008

BKit.jpg

I was working way too fast yesterday and skipped over some obvious bugs in the parser that were related to the addition of the JEP and BKit constants to the mix. The first was that pulling back a null valued variable returned a String with the value "__null__" - our tag for the null variable. This isn't right. I had to put the same value-mapping on the getVarValue() method that I had on the output of the expression parser. With that, it was fixed.

The second one was that the addConstant() method wasn't properly mapping incoming null values to the null tag, which was a problem I was having yesterday and simply wrote it off to the super's method getting called. I should have known better, but I was in a big hurry to get this done for the developer. The problem was in the missing null mapping, and when I added that in properly, everything worked just like I had expected it to.

I'm glad I went back and scanned what I was doing to make sure it was all done. These little loose ends are annoying and erode your credibility with others. Don't be sloppy - even if you have to be fast, go back and make sure it's all cleaned up.

After Much Work, Panic Ships Coda v1.5

Wednesday, August 27th, 2008

Coda.jpg

I've been on the Coda mailing lists for quite a while and have heard the rumblings about the possible death of the product. Nothing more than rumors. A small shop like Panic needs to pace what they are doing to make sure that they deliver a good product year after year. In contrast to popular belief in Corporate America, you can't expect to have a home run app (or release) every month on a tight budget. So we have had to wait.

Coda 1.5 is finally out, and it looks to have some significant improvements, and yet some significant omissions. Maybe these follow a certain usage pattern, and if so, then it's my usage of the tool that's abnormal. For instance, Coda 1.5 has built-in support for Subversion. Great. Why not CVS too? It's not that different. The core tools are on Mac OS X, so they don't have to worry about that. Still, it's nice that they have something in the way of source control, I only have to make a subversion server and migrate a repository to there, but that's a weekend.

Secondly, they add find/replace across multiple files (along with a significantly improved editor - don't know what that means for SubEthaEdit) which will help people fixing multiple links in a web system, but they have no facility for invoking a graphics editor like Photoshop, Acorn, etc. You can drag an image into a page, and it'll place the img tag there, but you can't shell out to a third-party graphics editor? Seems that would be an easy addition and then even if it's not "all in one", it's available for seamless workflow.

I like the tool. It's slick and polished. I don't have a great use for it at this time because I'm not maintaining a dozen websites daily. What I have used it for, I like, and will continue to try and fin things to work on with it. But even I can see the trade-offs they had to make on this release. It's showing more of how it's meant to be used, and what it's not meant to do.

Tricky Problem with Market Data Server and Ticker Plant

Tuesday, August 26th, 2008

MarketData.jpg

Today I was face-to-face with a bug that's been giving me grief for quite a while and I would like to say that I've solved it, but I only think I might have solved it, and we'll have to wait for time to tell to see if I really have solved the problem.

The problem relates to my market data server and it's connections to my ticker plant. In theory, these connections are reliable - breaking and re-making connections as needed to make sure that the requests get through and serviced as quickly and efficiently as possible. But there seems to be an issue with my production box and it's connection to it's ticker plant.

Upon restart, everything is fine. But after a few days, the data returned from the server - provided by the plant, "flip-flops" from a valid value to zero and back again. It's most annoying, and very difficult to track down. It doesn't happen on my development box, and developing or testing in production is just way way too dangerous.

So I was thinking it might be these connections. So I told the server to drop all connections to the plant and create new. This had the same effect as a restart in that all the requests were good then. This leads me to believe it's not in the main server but in the satellite processes that talk to the ticker plant. Armed with this, I dug into that code to see if I could see anything.

What I saw, what I hoped to see, was that I was depending on the connection to the ticker plant to be 100% reliable. Why? Well... because it typically is. But why not just use the connection methods to see if the connection is valid? And if it's valid, why not send a simple ping to the server? If either of these fail, then drop the connection and create a new one. Seems far more reliable than simply assuming that the connection will take care of itself.

The overhead is minor and this is only done once per request from the server, so the overhead should be minor. What I think was happening was the flipping was when I was hitting different connections to the ticker plant and it was just the luck of the draw which one I got. Why some went bad and didn't heal themselves on the production box, I don't know. It doesn't happen on the dev box. Maybe there's something in the networking... I don't know. But I'm hoping that this change will make the server much more reliable.

We'll have to wait and see.

Added Global ‘null’ Variable to the BKJEP Parser

Tuesday, August 26th, 2008

BKit.jpg

I got a visit from a developer who is using a shared Java library of mine - BKit, and two components of it, specifically: the BKTable and the expression parser - BKJEP, itself based on the JEP parser while it was Open Source and free. They have since closed the source on JEP and upgraded it's capabilities, but for what we need it is more than adequate, and I really don't want to get into a licensing situation with a group that started Open Source and then closed it down. They sound like they're on the brink of closing shop.

Anyway, the developer wanted to return a null value for the computed column. Originally, the idea of the computed column was to give the ability to the user of the BKTable a way to create a simple computed column without having to do it themselves. They could say "Give me a column called 'Area' that is 'width * height'" - where the columns called 'width' and 'height' were already defined in the table. When either 'width' or 'height' of any row in the table changed, the resulting 'Area' column was also updated. Nice, but not Rocket Science.

It got more complicated when they wanted to have Excel-like functions. Things like dateFormat() to turn a Date object into a String for comparison... isNull() to test if the value is null... and then if_then() to give it a simple conditional. And it's this last one that's opened the particular can of worms I'm dealing with right now.

When data is set in the expression, it's impossible to give it a true null value. The core JEP parser simply doesn't allow it. So we encoded the null to be a special String (__null__ if it matters, and it doesn't) so that it could be 'set' and 'get' from the expression. We also created the isNull() function so that you could test for it. So far so good. But what if the output of the if_then() is to be a null? Ah... there we have an issue.

There was no way to create a properly encoded null value within a JEP expression. This developer was the first to ask for it. There's a lot of good that could be done with this variable defined in all expressions... but there's a lot of danger as well.

Say the user snuck an expression past us that generated a true null value. Then used that value in the test: x == null... well... the value of 'x' would not have been encoded to the proper string constant and so it'd fail. So we have the problem that there are cases where something that should work - won't work. The easiest way to think about this is to just be careful and use the variable 'null' only when you have to. And test... test... test.

But with that, I think this adds more than it harms, so I added it in.

UPDATE: wow... that was a lot harder than I had originally thought. The first cut I had seemed to work, but it really didn't. I had assumed that within JEP the constants and the variables were kept apart as the first are immutable and the second aren't. But in fact, they are the same storage class. So... when I scanned through the variables in the BKTable's method, I still caught them and they didn't appear as column headers and so the expression was tossed out.

I had to change the way the BKTable's method worked. When I got a variable from the expression I had to check to see if it had a defined value. If it did, then it was a constant as only constants had defined values at this point in the processing of the expression. This skipping was essential to get the expressions not only passed in, but also properly evaluated. I ran all the tests on the table and they all came up OK. Whew! That was a lot more complex than I had originally thought.