Archive for May, 2010

The Incredible Expressiveness of Objective-C

Friday, May 28th, 2010

I've been messing with getting my latest ObjC code going again today and I have to say that once again, ObjC simply brings a smile to my face. It's so incredibly expressive that I just can't get over it. Sure, I can do a lot of the same things in C, C++ and Java, but there's a lot I can't do simply because they don't have the ObjC runtime. I appreciate that I can send nil any message I want, and it's not going to error. That means I don't have to check every single step in the processing or worry that some bad data will blow me up.

In C, C++ and Java, I have to do this checking. It's not horrible but it does make the implementation (not the language itself) much uglier than the equivalent implementation in ObjC.

Sure, I have looked at things like Python and Clojure, and there are languages that allow the more flexible method invocation, but it's not the same as really understanding that there's a nil object, and it's OK to deal with it as a valid instance of anything. It's really pretty sweet.

I'm porting code from C to ObjC for this project, and while the C code was about as clean and nice as I could have ever written, the ObjC code is just fifty times cleaner and easier to understand. Sure, a lot of this is the objects and message passing, and another big chunk is the Cocoa objects, but even in Java, it would not have been as clean.

I love that I can drop into C code when I need to, and that I've got retain/release memory management as opposed to the reference counting and garbage collecting. I just really hate that about Java. It's always something that comes back to bite me in terms of efficiency of storage.

I had an interview once with a company that I've since realized I'm glad I didn't get the position, but at the time, I was really ready to leave where I was. The guy I was talking to realized that I had been somewhat of a mistake in that my interests were not at all in line with the position - typical recruiter move, but we had a nice talk anyway. In the end, when talking about the language, he said "Any reasonably expressive language is pretty much the same." and at the time I was thinking of Java vs. C#, and tended to agree with him.

Horrible statement by him, and horrible memory fault by me.

There's nothing like ObjC. Nothing.

Trying to Solve a Slow Tomcat Server

Thursday, May 27th, 2010

Tomcat Server

This is really frustrating. This morning, out of nowhere, one of my Tomcat webservers was taking far longer to return data than normal. By 'far longer', I mean 5 to 10 seconds when yesterday it was sub-second. Really. It's a factor of 10x to 30x in response time. Horrible.

So I'm trying to figure this out. It's not a resource issue - got plenty of memory and CPU... it's not the code - it's running fine in London and NYC... it's not a simple data error - restarts and even different JVM GC parameters makes no difference at all.

It could be hardware. It could be networking. I seem to be getting no real help on either of these. It's pretty frustrating. My co-worker, Steve, who is taking over for me on this project, wants to put in another box to the mix and see if the problem clears up. If so, then it's the box. Or is it?

If they can't find the problem under load, are they going to fix it when it's isolated and not doing anything? Maybe. But the vendor isn't going to give us a replacement box "just because". It's got to be something. I'm just stumped as to what.

What's frustrating is that it appears to be a networking problem. I get the connection, but getting the contents from the Tomcat instance is exceptionally slow. I suppose, it really appears to be a software problem. Everyone says their stuff is working just fine, but still we have this delay in getting the data.

If it's not the code - and I haven't changed the code in weeks, then it might be the configuration. Nope, I checked that... it's configured exactly right. If it's not the code, and the data loads haven't changed that much, then how likely is it really "within" the box? Not a lot, in my book. But what else could it be?

Not fun.

UPDATE: a reboot of the box fixed it. Something went very wrong with the box. Oh well... can't do much about that.

[5/28] UPDATE: turns out, there's a problem with the stated defaults with Tomcat 6.0.18. In the conf/servlet.xml file there's a maximum number of acceptor threads for the incoming socket connections. It appears that the stated default of 200 was not, in fact, what the default was. Using jConsole, we were able to see that the actual value of maxThreads for the port 8080 connector was 40. We set it in the conf/server.xml:

  <Connector port="8080" protocol="HTTP/1.1"
             connectionTimeout="20000"
             redirectPort="8443"
             maxPostSize="0"
             maxThreads="400" />

and with this (and the automatic change in jConsole) the number of acceptor threads popped up from 40 to 166 and the speed was back. Amazing that the default wasn't what they said. Had that been the case, we would have been fine.

Good lesson to know.

To activate the monitoring for Tomcat assuming it's not already active, you need to add a few command-line options to the CATALINA_OPTS environment variable in either cataling.sh or the startup.sh script:

  export CATALINA_OPTS="-Dcom.sun.monitoring.jmxremote \
      -Dcom.sun.monitoring.jmxremote.port=7999 \
      -Dcom.sun.monitoring.jmxremote.ssl=flase \
      -Dcom.sun.monitoring.jmxremote.authenticate=false"

and then restart the Tomcat server. It's probably not a huge load, but you have to have it in order to connect with jConsole, so it's probably something you need to use unless you know it's not a great idea.

Do Not autorelease the Return from -copyWithZone:

Wednesday, May 26th, 2010

xcode.jpg

This afternoon I was working on my latest version of the CryptoQuip solver and decided to turn on the built-in Clang Static Analyzer for all my debug builds as I've gotten to the point that I'm really getting close to having something useful to look at. Interestingly enough, it pointed out a problem on all my implementations of -copyWithZone: - I was returning an autoreleased instance and that's not the intended signature of the -copyWithZone: method.

For example, my original code for a simple object was:

  /*!
   This is the standard copy method for the Legend so that we can make
   clean copies without having to worry about all the details. It's a nice
   deep copy, where the contents of the returned Legend are the same as
   this instance's.
   */
  - (id) copyWithZone:(NSZone*)zone
  {
    // simply use the allocWithZone and populate it properly - easy
    return [[[Legend allocWithZone:zone] initWithMap:[self getMap]] autorelease];
  }

and the Static Analyzer pointed out that the retain count of +0 was wrong and it was supposed to be +1. I simply changed it to read:

  /*!
   This is the standard copy method for the Legend so that we can make
   clean copies without having to worry about all the details. It's a nice
   deep copy, where the contents of the returned Legend are the same as
   this instance's.
   */
  - (id) copyWithZone:(NSZone*)zone
  {
    // simply use the allocWithZone and populate it properly - easy
    return [[Legend allocWithZone:zone] initWithMap:[self getMap]];
  }

and it's all fixed. But when I'm dealing with a little more complex objects, and I'm making a deep copy, I have to be careful and autorelease the copies I'm making because the setters are calling retain on the arguments, and I don't want to have a leak by leaving a copy with a retain count of +2.

So a more complex version of -copyWithZone: looks like:

  /*!
   This is the standard copy method for the Quip so that we can make
   clean copies without having to worry about all the details. It's a nice
   deep copy, where the contents of the returned Quip are the same as
   this instance's.
   */
  - (id) copyWithZone:(NSZone*)zone
  {
    // simply use the allocWithZone and populate it properly - easy
    id   dup = [[Quip allocWithZone:zone] init];
    // now let's add in copies of all the ivars we have to make it equal
    [dup setCypherText:[[[self getCypherText] copyWithZone:zone] autorelease]];
    [dup setStartingLegend:[[[self getStartingLegend] copyWithZone:zone]
                            autorelease]];
    for (PuzzlePiece* pp in [self getPuzzlePieces]) {
      [[dup getPuzzlePieces] addObject:[[pp copyWithZone:zone] autorelease]];
    }
    return dup;	
  }

where the arguments to the setters are calls to the instance's -copyWithZone: but to get the retain count correct, we need to autorelease them leaving them with a count of +0, to then have retain called on them by the setter.

The NSMutableArray calls retain on all objects that are added to it, and release when they are removed. That explains the call to autorelease on the copy of the individual elements in that deep copy loop.

In general, the Static Analyzer is saving my bacon by avoiding improper code practices as I get back into ObjC coding. I'm really happy with it. Fantastic!

Fixing CVS pserver Issues on Snow Leopard

Wednesday, May 26th, 2010

This morning I was going to check something into one of the projects I host on my CVS repository running on my home server. I had done the transfer when the old Mac died, and thought I had it all going, but clearly I was wrong. Today I found another issue.

What I saw was that when I went into a checked-out project and did a cvs update, I got a nasty error message:

  peabody{drbob}3: cvs update
  ? src/CKPropertyChangeEvent.h
  ? src/CKPropertyChangeListener.h
  ? src/CKPropertyChangeSupport.h
  cvs update: failed to create lock directory for `/usr/local/CVSroot/CKit'
  (/usr/local/CVSroot/CKit/#cvs.lock): Permission denied
  cvs update: failed to obtain dir lock in repository `/usr/local/CVSroot/CKit'
  cvs [update aborted]: read lock failed - giving up

Clearly, I'd missed something else. Now I had to find it.

On the server, I have the CVS pserver set up as described here. The missing thing in this description is the permissions. Those are pretty simple:

  $ cd /usr/local
  $ sudo chown -R root:wheel CVSroot

so that everything in the repository is owned by root and the group wheel. Easy. I also made sure that everything is group writeable so taht if a user is in the group wheel, they can update/change the projects in the repository. Then, the username and group in the launchd plist makes sense. The problem is, my new account wasn't in the wheel group.

Because the CVS passwd file has just my username and encoded password, I'm required by cvs to have a valid account on that server. I do, but I also need to be able to read/write to the CVSroot to do any real operations on the projects in the repository. What I failed to do was to insure that my account had access to the same group.

To find out the groups you're in, simply use id:

  $ id
  uid=501(drbob) gid=20(staff) groups=20(staff),204(_developer),100(_lpoperator),
  98(_lpadmin),80(admin),61(localaccounts),12(everyone),
  401(com.apple.access_screensharing),402(com.apple.sharepoint.group.1)

and it's pretty clear that wheel isn't in that list. So let's add it:

  $ sudo dscl . append /Groups/wheel GroupMembership drbob

and now id shows us what we need to see:

  $ id
  uid=501(drbob) gid=20(staff) groups=20(staff),204(_developer),100(_lpoperator),
  98(_lpadmin),80(admin),61(localaccounts),12(everyone),0(wheel),
  401(com.apple.access_screensharing),402(com.apple.sharepoint.group.1)

Yup, right there on the end of the second line is wheel. Now I can do cvs updates without a problem. Good enough.

GraphicConverter 6.7.2 is Out

Wednesday, May 26th, 2010

This morning I noticed that GraphicConverter 6.7.2 was out, and I'm becoming a fan of these guys as they are really trying to live up to their name. The release notes say that they are adding support for more file types as well as the links they already have into iPhoto - which I think is great.

It's one of those programs that you don't usually need, but when you need it, it's something you really need. Glad to see it improve.

Working with A Truckload of Mr. Wizards

Tuesday, May 25th, 2010

Honestly, I've been working at The Shop for about 14 months - the shortest job I've ever had outside college, and still I seem to know more than many of the "smart" folks that have been here for years and years. Why is it that people think they know so bloody much, and when they do, why don't they bother to ask as opposed to springing into immediate action and then showing the world how smart they are from averting certain destruction?

Had they asked, I could have told them that their ideas were good ones, but that they really weren't paying enough attention to the details of the situation and had overlooked the essential facts that made the situation not the end of the world. In fact, their change would have been the disastrous one.

I don't mind telling people this, but it's disheartening to say the least. On one hand, it's nice to see that people are checking things to make sure everything is OK. On the other hand, they aren't checking very well so their checks are causing more problems than if they just hadn't checked.

I've talked to a lot of my friends in this industry outside of The Shop they are amazed by what I've come to understand as "general practices" here. There's no need to list them all, it's one of the motivations for my leaving in about a week. But what's worse is that all these technical issues are being looked at by the same people that are checking the things I've been working on for the last year.

Because of this, I can't really honestly hold out a lot of hope for the technology decisions for this place. It needs to be gutted of it's primary technology folks, new ones brought in that understand what a global, multi-million dollar trading firm needs, and then staff up those people capable of achieving those goals. Because I promise you, the "stars" that don't catch the details in a start-up script are not going to be able to catch the nuances of a price feed or much of anything else, for that matter.

Business can be harsh... but it's not about harsh or friendly - it's about business, and if it's your money, do what you want. But if it's someone else's... well... then they have a right to deserve a little more.

Google Chrome (dev) 6.0.408.1 is Out

Monday, May 24th, 2010

I noticed this morning that while I was looking at a few houses with Liza, Google Chrome (dev) was updated to 6.0.408.1. That's a good jump as far as Google goes, and it'll be interesting to see what had changed in my daily usage. It's getting better and better, and pretty soon Safari is going to have to sit up and take notice.

The Little Things – Changing the Favicons for My HostMonster Sites

Friday, May 21st, 2010

OK, it's a little thing, but these days, I'm looking for the little things to help out as these times are tough... but enough of that. One of the things I've been wanting to do for a while is to really improve the quality of my 'favicons' on my HostMonster sites so that it's a little better than my initials and also a little cleaner separation on the different sites so they don't all obviously look like part of one site.

I found a nice little site that had a ton of nice, public domain 16x16 icons perfect for such a use as mine. I had a blast looking at a few pages of icons and picking out a few to clean up a bit and then throw on the sites. It's not a lot, but the effect - to me, is significant.

It's the little things we have to focus on... the biggies are just too daunting to approach these days.

Transition Out? Nah… Beat that Dead Horse… Er… Cow, Eh?

Thursday, May 20th, 2010

cow.jpg

This is an interesting experience. When I have given notice that I'm leaving at other companies, it's been "Thanks, let's get everything out of your head before you leave" and I'd go through a series of meetings - some with just a few folks, others with a much larger audience, and I'd present, they'd question me... You know - a typical debriefing. That's what I expected here.

I couldn't have been more wrong.

While there have been a few emails and a few conversations, the largest component of my transition period is doing work. I can see taking the time to finish up things that I can fit into the two weeks I have left. That makes sense - I'm spending a day or so on something that would take another developer several days to get up to speed on. It's just reasonable efficiency.

But Ralph is going much farther than that. He's asking me to start and finish new work. He also wants me to stay for three weeks. Well... following this logic, why don't I stay for another 3 years and do all the new projects?

Oh that's right... I quit!

This transition time is me being nice and professional, and in return, I'm being treated like a cow (again) - stay as long as I say... do all that I ask... Sorry Ralph, I don't think so.

So if it continues tomorrow, it's time to go have a talk with HR. This isn't what they want to have done, I'm sure. It's my final impression of this place, and they'd rather it end on nice, friendly terms, than have me walk out of here and tell everyone I know of the lunatic managers in this place.

Google’s Font Directory

Thursday, May 20th, 2010

google-labs-logo.gif

This was an interesting bit of news today: Google is hosting web fonts now in their Google Font Directory - very interesting. The idea is that you go to this page, find a font you want to use by seeing how it's rendered in your browser, and then you get a line of HTML to download it, and you can then use it in your CSS as a font.

Impressive.

First, the preview tool is the browser - so you can actually see what you're going to be getting. Then, just as with the Google Visualization widgets, you have a single line to "import" the font, and then you're free to use it.

Clearly, they will see who's asking for what, and in doing that they are one step closer to world domination, but what the heck... It's a very nice way to preview the font for a web page, and then be able to be sure that your client will be able to see it in the way you wanted - regardless of what machine or fonts they have.

Very neat. I'm going to have to remember this.