Thursday, December 28, 2006

How does your blog look with zoomed fonts?

After a couple weeks of zoomed browsing, I find that many designs fall apart when you increase the font size. See problogger.net for a mild example. I'm not picking on Darren; I had to move my sidebar from the right to the left side to prevent code examples overlapping.

Try your own site. Readability is in--small fonts are so 1997.

Labels:

New Orleans

Scoble, following Edwards on the campaign trail: "Driving along I saw boarded up homes and buildings. Many of which still have spray-paint messages left by rescuers that say whether or not there were any bodies inside."

I couldn't pick a better launchpad. Go, Edwards (and Scoble).

Labels: ,

Wednesday, December 20, 2006

Five things you may not know about me...

Paul tagged me, so here goes:

  1. I wrote a successful program to stop the Code Red worm. Unlike anti-worm worms, it only affected infected computers. As a result, I appeared on TechTV's The Screen Savers. Do I really sound like that? I was pretty nervous. They asked if they could film me chained up acting like a mad man for a commercial break promo, but I declined.
  2. Back in high school, I wrote a real time, free-directional 3D rendering engine in Turbo Pascal with inline assembly language. I wrote one demo of a rotating spaceship (it looked kind of like the ship on Stealth) and another with a giant room you could walk around in and look all directions; the room looked like a sewer and even had an animated stream of slime running through the middle. Shortly thereafter, 3D graphics cards debuted and invalidated all of my hard work. Maybe I'll see if I can track down the 3 1/2" floppy when I'm back home for the holidays.
  3. There's a mountain named after my family in Missouri. Kind of like The Waltons.
  4. I'm a polydactyl. I was cripplingly self conscious of my scars when I was a kid but don't care too much nowadays. I wonder if I could type faster if I still had my extra fingers. Weird, huh?
  5. I played Tommy Cliffert in my university's production of The Cover of Life. We practiced hours every night for six weeks. I dressed as a sailor. I held the only male role, and I practiced the kissing scene with every woman in the cast.

Enough about me. I hereby tag Sam, Keith, Cedric, Mike, and my mom.

Re: God bless the re-inventers

Dave asks why JSON re-invented the wheel: "I read on Niall Kennedy that del.icio.us has come up with an API that returns a JSON structure, and I figured, sheez it can’t be that hard to parse, so let’s see what it looks like, and damn, IT’S NOT EVEN XML!"

Dave, web browser capabilities pragmatically drove JSON's Javascript-like format. Unlike XML-based protocols, you can use a JSON service across different web sites with existing browsers (without a server side proxy, Flash, etc.).

I suppose you could base the protocol on XML if you really wanted to, but you'd still have to provide a Javascript wrapper. Fewer browsers support natively parsing XML than Javascript, and performance would suffer. We do all have Ghz machines nowadays, but today's browsers seem to need that and more; I can't believe Firefox still manages to hang for seconds at a time on my Mac Pro.

Sites often offer JSON APIs in addition to XML APIs to support pure browser-based usages. del.icio.us has had an XML API for a long time; they use RSS! If I were calling an API from Java, I'd use the XML not the JSON API.

That said, I'm personally not a fan of the current JSON spec. If you structure your Javascript like the following example, you can support complex graphs, circular references, etc., whereas the current spec. only supports hierarchies: a={};b={};c='foo';a.foo='c';a.bee=b;b.ay=a;

Friday, December 15, 2006

Resize any text field

With this bookmarklet. It works great in Blogger.

Always restore your Firefox 2 session

By default, Firefox 2 saves and restores your session (i.e. your open tabs) in the event of a crash. If you want Firefox to always restore your session, go to the Firefox preferences, go to the Main tab, and under, "when Firefox starts," select, "show my windows and tabs from last time."

Thursday, December 14, 2006

Say "no" to small fonts.

I just installed NoSquint, a Firefox extensions which enables you to configure the default text zooming. 125% seems to work well on my MacBook Pro, but you can also configure the zooming by domain for especially egregious offenders.

Wednesday, December 13, 2006

Google Patent Search

If you've ever tried to search for patents before, you're going to love Google Patent Search.

Democrats may lose the Senate majority

Dave: "Tim Johnson, the 59-year-old US Senator from South Dakota, may have suffered a stroke. If he can't serve, a replacement will be appointed by South Dakota's governor, a Republican. Johnson is a Democrat, whose 51-49 majority in the new Senate would turn into a 50-50 tie."

Me: Gulp.

Sunday, December 10, 2006

Caching Class-related information...

Jacob is exploring caching information related to Java Class instances.

Say for example we need collections of getter methods in classes. Rather than filter out the getter methods every time we need them, we can build the collection of getters once and cache the result in a static map:

  /** Maps a class to getter methods in that class. */
  static Map<Class<?>, Collection<Method>> getterCache = ...;

Problems arise when the garbage collector needs to reclaim a Class instance to which our map holds a strong reference. This could happen if our cache class is in the system class path and a class in our cache is from a web application.

When we go to reload the web application, our cache class keeps a strong reference to the web application class which keeps a strong reference to its class loader which keeps strong references to all of the other web application classes--memory leak.

If you can, store the cache somewhere where it will free up at the same time as the classes it caches. For example, in the case of a web application, we might store the cache in the servlet context.

If you must keep strong references from a static scope, you have to keep a WeakReference to the Class instance making it available for garbage collection. Jacob pointed out that we need to keep a WeakReference to the cache key, but often times your value also has a strong reference to the Class instance.

In our getter example, our value is a list of methods. Those methods each keep a strong reference to their class--memory leak. How do we fix this? We can't keep a weak reference to the value itself in this case. In between usages of our cached data, we'll hold the only reference. We could wrap each Method instance in a weak reference, but I find keeping a SoftReference to the cached value works just fine. Plus, the garbage collector can reclaim values which we don't access often.

How do we implement this cache? It just so happens I've created a class ReferenceCache which solves this exact problem. ReferenceCache wraps ConcurrentHashMap and references keys and values however you like, strongly, softly or weakly.

Compared to using a WeakHashMap, ReferenceCache abstracts more of the caching logic so you don't have to write code to check for a value, create a value, and put the value in the cache over and over. You only write code to create the value.

Where WeakHashMap uses equality to compare keys, ReferenceCache compares weakly and softly referenced objects by identity; weak and soft references are inherently identity based.

WeakHashMap cleans up after garbage collected keys in the same code path as your map operations. Thanks to the ConcurrentHashMap behind the scenes, ReferenceCache can perform these cleanups in a background thread.

What's more, ReferenceCache creates values canonically, i.e. it will only create one value per key at a time. This comes in handy pretty much any time you need a canonical map and prevents extraneous value creations other times.

Getting back to our getter example, a ReferenceCache-based implementation goes something like this:

  static Map<Class<?>, Collection<Method>> getterCache =
      new ReferenceCache<Class<?>, Collection<Method>>(
          WEAK, SOFT) {
    protected Collection<Method> create(Class<?> clazz) {
      Collection<Method> getters = new ArrayList<Method>();
      for (Method m : clazz.getMethods())
        if (isGetter(m))
          getters.add(m);
      return getters;
    }
  };

  static boolean isGetter(Method m) {
    String name = m.getName();
    return name.length() > 3
        && name.startsWith("get")
        && Character.isUpperCase(name.charAt(3))
        && m.getParameterTypes().length == 0
        && !Modifier.isStatic(m.getModifiers())
        && ...;
  }

Now, what do we do about Super Type Tokens? ;)

P.S. Any time you cache objects, run performance tests to determine whether your cache really does more good than harm.

Wednesday, December 06, 2006

I've always wanted a link blog.

Google Reader's item sharing couldn't make it easier. You can see my shared items in the sidebar to the right and subscribe to the feed (using Google Reader of course).

I can separate the Java items into their own feed if you like. Let me know.

Don't buy Wii HD component cables off eBay.

I ordered some from Nintendo's online store, and they came in two days.

Monday, December 04, 2006

Super Type Tokens

Class<T> works fine so long as T is a raw type, but I recently needed to pass around references to full blown generic types. For example, due to the fact that Java uses erasure to maximize compatibility, List.class compiles but List<Integer>.class does not.

Ted recently ran into this problem, too. He was lucky enough to get off with a warning, but my code actually needs to differentiate between List<Integer> and List<String>.

Neal came to the rescue with a clever (and cleverly named) pattern for retaining otherwise non-reifiable types at runtime. Check out super type tokens.

In a nutshell, instead of saying List<Integer>.class, you can say new TypeReference<List<Integer>>() {}, where the API for TypeReference may look very similar to that of Class.