LCD replacement on a Gateway LT2032u, etc
Posted by postfuturist on 2010-07-01 21:35:08

5 days ago, I ordered a replacement LCD screen for Megan's netbook, a run-of-the-mill Gateway LT2032u machine. The screen had cracked due to an unfortunate fall. I was able to install the replacement in less than an hour, and it works perfectly. The netbook originally cost about $300 and the replacement screen was only $50. Small victories.

In other news, Opera 10.60 was released officially today. Opera is truly an awesome engineering feat. The supported operating system list is impressive: Windows, OS X, Linux (i386, x86-64, and PowerPC), FreeBSD (i386 and x86-64), and Solaris (SPARC and Intel). The FreeBSD'ers must be rejoicing. Not only is basically every modern operating system supported, but it is the fastest browser, even faster than Google's Chrome. I didn't believe it either, until I ran some benchmarks myself. It's got WebM video. Now that Firefox is getting beaten badly by 3 browsers in the speed category, the folks at Mozilla need to do some soul-searching. If the current Mozilla JavaScript engine (SpiderMonkey), which is descended directly from the first ever JavaScript interpreter created by Brendan Eich at Netscape, can't keep up, it should be replaced. Heck, Mozilla could grab V8, it's open source. It certainly wouldn't be a trivial task, maybe infeasible due to how deeply embedded in the code the current one is. But they have to do something.

The release of yet another super-fast browser is a big win for everyone. Internet Explorer is losing market share fast enough to make Microsoft actually want to compete, though IE 8 was such a spectacular failure that I have little faith in IE 9. The web is everything. Windows is still the dominant desktop OS, because that's what you get when you buy a computer. It doesn't much matter now, though. You could put someone in front of an Ubuntu desktop, they'll click the Firefox icon and be off and surfing in no time. The web is the great equalizer. Between Firefox, Chrome, and Opera, the operating system has become a commodity. Add Open Office and Google Docs into the mix and there is no reason that anyone couldn't use any operating system. Now, I prefer Linux as the perfect balance between usability and power. If I was a hardcore gamer, I would probably use Windows since it is the PC gaming operating system. I've even dabbled with Windows 7. It's not that bad--much better than Vista and finally an evolutionary step past XP.

Some people love OS X and I understand why. It is the smoothest, sexiest operating system with enough Unix cred to be cool for the developer crowd. I'm willing to trade in that sexiness for paying 1/3 as much for a computer and having a slightly more powerful, configurable operating system. OS X is also a bit too mouse-oriented for my taste.

Enough about operating systems. I want my Arm-powered Linux netbook already. When do I get that? Lenovo's got one in the works, called the Skylight, but it looks to be a bit pricey.

My .vimrc
Posted by postfuturist on 2010-06-28 13:37:00
This is mostly for my own benefit, so I can copy/paste it when I'm setting up a new system:
set nocompatible
set tabstop=4
set shiftwidth=4
set smarttab
set expandtab
set softtabstop=4
set autoindent
set smartindent

set showcmd
set hlsearch
set incsearch
set ruler
set visualbell t_vb=
set nobackup
set ignorecase
set ttyfast
set sm
syntax on
set background=dark
set virtualedit=all

set backspace=indent,eol,start

set dir=~/.vim/swap

com Q q
com W w
com Wq wq
com WQ wq
Notes On Running Ubuntu Linux on an Old Computer
Posted by postfuturist on 2010-06-27 17:42:55

These are some packages that I found useful running Ubuntu 10.04 on a 10+ year old laptop. This laptop is so awesome it has a CDROM and a floppy drive built-in! It's maxed out at 384 MB of RAM which is pretty nice considering it shipped with 64. It's a perfectly capable machine, as long as you pick the right software.

  • Window Manager: Fluxbox
  • Wireless: install wicd and remove network-manager
  • Terminal: rxvt-unicode
  • PDF Reader: epdfview
  • Web Browser: epiphany
  • Text Editing: vim
  • Video Game: nethack
So long and fare well to the IDE
Posted by postfuturist on 2010-06-26 00:58:11

Netbeans crashed. Again. For the last time.

I'm normally a patient man, but an IDE has only one thing it has to do. It has to allow me to edit text files. An IDE that crashes is worse at facilitating coding than a piece of paper. I've used them and I'm done with them: Visual Studio, Code Warrior, Eclipse, Delphi, NetBeans and a few others.

Somewhere in the last 13 or so years of fooling about with Linux, I found myself editing text files with a strange, and at first confusing tool known as Vim. Now, I'm not a gun nut, but when I reached a certain age, my father decided it was time for me to learn how to fire a real gun. The first time I held it in my hand, I was immediately frightened by the terrible weight of the device. It was a revolver with a long barrel like something out of a Western. I nearly dropped it. It took quite a bit of effort to hold steady at arm's length.

Vim is a grown-up text editing tool. It's no cap-gun, or BB rifle. It's dense and dangerous and powerful. Vim is keyboard driven and minimalistic, allowing the maximal editing power with the fewest keystrokes. As a programmer, it's all I need. Vim has never crashed on me. Not once. It has some of the sugar that the big IDE's have, like syntax highlighting, but it's lightning fast and stable and powerful. Some IDE's have code folding where you can hide parts of the code and expand them with clicks of the mouse. Why?

Click click click is for surfing the web. The keyboard is a much more powerful input tool than the mouse. The mouse is for lazy consumers. Now, I can be a lazy consumer at times. I watch the television. I click and read, click and read, click and watch. But when I'm working, the only click and clack you here is from the keys on the keyboard.

I don't like being a code generator. I don't like typing up boilerplate. I hate copying and pasting. I like small code files, with long names, and a handful of short, declarative functions. I don't like wasting time. Here's the typical way to complete a piece of web functionality in PHP. Create a script, write some SQL code to extract some data from a database, blast some HTML out to the browser. Lather, rinse, repeat. It's boring. It's inane. It begs for a higher level of abstraction.

IDE's are made for human code generators. Oh, you need to write a class that implements some Java interface? Well clickity click here, type a class name, clickity clack there and the IDE has generated a bunch boilerplate: a class definition with a bunch of stubbed methods, curly braces, semicolons. Don't want to look at all that ugly boilerplate? Just hide it by clicking on the code folding mechanism. Now you don't have to look at it anymore. What the hell? Java sucks. IDE's suck.

The job of a software developer is to solve problems where a computer be used to provide the solution. The solution almost always involves the internet and a little thing called HTTP. The goal is the solution, not the journey. The journey should be short, and never should the same path taken more than once.

Everything changes when you take one step back from the human as code-generator and apply your programming skill to solve the problem of having to generate a lot of boilerplate code. I did this at my current job. I saw that I basically did the same thing every time I wrote code to pull some rows out of a database, or update values in a database, or delete rows. So, I wrote a bunch of code that would generate the SQL on the fly and encapsulate all the database calling mechanisms. All it needed was a succinct definition of a database table to generate all that repetitive SQL and perform all the repetitive data munging.

That was a good step for me to take. It instantly made me a more efficient programmer than all my coworkers. There were some limitations to this meta-level programming. I had created a tool to create functionality quicker, but it had some warts. So, I wrote a better version of that code. It became a better tool for rapid development.

After some time, I realized that I was still doing double duty. I would write a database table definition for the database engine in SQL and then another definition in PHP that my other code would use to automate retrieving and storing data in the database. So, I wrote a piece of code that queries the database and generates the PHP table definition.

So when I write code, I can treat arbitrary rows in the database like native PHP objects. Of course, anyone using a framework like Rails or Django already does this, so it's nothing new, but it was for me.

So, back to NetBeans crashing. It crashed. I did a quick analysis in brain of what I got from the IDE in exchange for random instability, and the price was too high. IDE's help you generate code the slow way, by hand. IDE's constantly remind you about the names of classes and functions and help generate scaffolding that you can later populate with meaningful code. What a terrible waste.

I've decided to write as little code as possible from here on out. If I have to do anything more than once, I will generalize it. If some API is difficult and complex, and requires IDE hints to use properly, I don't want to program against it directly. I will wrap it up in a simple, memorable class that has the absolute simplest interface possible to solve the problem.

In the past couple weeks I've written code to make the creation of administrative interfaces with a few lines of declarative code. I wrote an HTML form class to encapsulate, standardize, and simplify form generation, validation, and security. I realized that rock-star coders like the people behind Rails and Django were just coders who didn't allow themselves to become code generators. Instead, they kept building higher and higher level abstractions until they were no longer repeating themselves. With Ruby on Rails, you can create a complete, functional web application by typing in a few lines in the terminal.

In this context, code becomes rarefied and powerful. It is no longer soupy gibberish or half-man, half-machine generated blub. So I don't need the IDE any more. I build abstractions that are easily understandable. I could go sit in the park and design code in a notebook, then go sit down and type it out, carefully, with unit tests and finish in a fraction of the time. Big, ugly languages like PHP, Java, C++ and C# coupled with big, gaudy IDE's do not encourage this style of development. Most of this realization came from spending about a month trying earnestly to learn Common LISP and then a couple weeks messing about with Django.

Kindle For PC Beta works on Linux
Posted by postfuturist on 2010-06-17 00:08:22
The latest versions of Kindle For PC don't run using Wine in Linux, but a few forum posts explain that the old beta does, so long as Wine is configured to run in Windows 98 mode. It took me awhile to track down a live link for the beta version, so I thought I would post it on my blog for future seekers. Download the Kindle For PC Beta here!
JavaScript Benchmark: Opera 10.60 vs. Google Chrome 5.0.375
Posted by postfuturist on 2010-06-14 14:49:09

I ran the SunSpider JavaScript benchmark of the latest Opera 10.60 64 bit Linux build from here. Apparently, the JavaScript engine not only rivals but looks to be a little faster than Chrome, at least for 64 bit Linux. The tests ran in 411 ms on Opera and 477 ms in Chrome.

TEST                   COMPARISON            FROM                 TO             DETAILS

=============================================================================

** TOTAL **:           1.16x as fast     477.2ms +/- 4.9%   411.2ms +/- 3.1%     significant

=============================================================================

  3d:                  1.57x as fast      86.0ms +/- 21.5%    54.8ms +/- 8.7%     significant
    cube:              2.06x as fast      31.8ms +/- 12.8%    15.4ms +/- 15.7%     significant
    morph:             1.58x as fast      31.2ms +/- 24.0%    19.8ms +/- 6.9%     significant
    raytrace:          -                  23.0ms +/- 35.2%    19.6ms +/- 24.0% 

  access:              *1.11x as slow*    47.2ms +/- 7.1%    52.6ms +/- 2.1%     significant
    binary-trees:      *2.36x as slow*     2.8ms +/- 19.9%     6.6ms +/- 21.5%     significant
    fannkuch:          *1.28x as slow*    18.4ms +/- 12.3%    23.6ms +/- 6.0%     significant
    nbody:             1.41x as fast      20.0ms +/- 6.2%    14.2ms +/- 19.0%     significant
    nsieve:            ??                  6.0ms +/- 41.4%     8.2ms +/- 29.2%     not conclusive: might be *1.37x as slow*

  bitops:              1.75x as fast      37.4ms +/- 9.6%    21.4ms +/- 9.7%     significant
    3bit-bits-in-byte: 2.20x as fast       4.4ms +/- 37.9%     2.0ms +/- 0.0%     significant
    bits-in-byte:      1.68x as fast       9.4ms +/- 24.0%     5.6ms +/- 19.9%     significant
    bitwise-and:       5.92x as fast      14.2ms +/- 13.0%     2.4ms +/- 28.4%     significant
    nsieve-bits:       ??                  9.4ms +/- 22.1%    11.4ms +/- 9.8%     not conclusive: might be *1.21x as slow*

  controlflow:         ??                  4.8ms +/- 33.8%     6.0ms +/- 14.7%     not conclusive: might be *1.25x as slow*
    recursive:         ??                  4.8ms +/- 33.8%     6.0ms +/- 14.7%     not conclusive: might be *1.25x as slow*

  crypto:              *1.15x as slow*    26.2ms +/- 10.3%    30.0ms +/- 11.7%     significant
    aes:               *1.28x as slow*    13.8ms +/- 11.7%    17.6ms +/- 14.6%     significant
    md5:               ??                  6.8ms +/- 43.7%     7.4ms +/- 19.2%     not conclusive: might be *1.09x as slow*
    sha1:              -                   5.6ms +/- 25.3%     5.0ms +/- 0.0% 

  date:                1.55x as fast      80.8ms +/- 6.4%    52.2ms +/- 12.2%     significant
    format-tofte:      -                  29.2ms +/- 16.6%    25.6ms +/- 14.4% 
    format-xparb:      1.94x as fast      51.6ms +/- 17.2%    26.6ms +/- 15.4%     significant

  math:                1.55x as fast      63.0ms +/- 8.3%    40.6ms +/- 4.1%     significant
    cordic:            2.19x as fast      22.8ms +/- 18.7%    10.4ms +/- 21.7%     significant
    partial-sums:      1.35x as fast      28.0ms +/- 9.4%    20.8ms +/- 13.0%     significant
    spectral-norm:     1.30x as fast      12.2ms +/- 19.6%     9.4ms +/- 11.8%     significant

  regexp:              *1.32x as slow*    14.2ms +/- 11.4%    18.8ms +/- 11.8%     significant
    dna:               *1.32x as slow*    14.2ms +/- 11.4%    18.8ms +/- 11.8%     significant

  string:              *1.15x as slow*   117.6ms +/- 4.6%   134.8ms +/- 2.0%     significant
    base64:            ??                 14.8ms +/- 16.2%    16.6ms +/- 10.0%     not conclusive: might be *1.12x as slow*
    fasta:             *1.15x as slow*    20.8ms +/- 9.8%    24.0ms +/- 8.2%     significant
    tagcloud:          *1.40x as slow*    27.6ms +/- 5.1%    38.6ms +/- 5.4%     significant
    unpack-code:       1.19x as fast      33.6ms +/- 5.0%    28.2ms +/- 3.7%     significant
    validate-input:    *1.32x as slow*    20.8ms +/- 10.7%    27.4ms +/- 4.1%     significant
Serving up Django with Tornado
Posted by postfuturist on 2010-06-06 20:35:55

This article is mainly of interest to web developers who might want to publish a site built with the Django web framework in a lightweight fashion (without involving Apache).

First, let me enumerate the stack that is serving this page to you right now.

  1. Hosting: VPS Hosting from ARP Networks
  2. Operating System: Ubuntu Server Edition 10.04
  3. Reverse proxy server (and file server): Nginx
  4. Web server: Tornado
  5. Web framework: Django
  6. Database: MySQL

Here is my Tornado script which I partially plagiarized from somewhere:

#! /usr/bin/env python

import os
import tornado.httpserver
import tornado.ioloop
import tornado.wsgi
import sys
import django.core.handlers.wsgi
sys.path.append('/some/folder/here/myapp')

def main():
    os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
    application = django.core.handlers.wsgi.WSGIHandler()
    container = tornado.wsgi.WSGIContainer(application)
    http_server = tornado.httpserver.HTTPServer(container)
    http_server.listen(8001, "127.0.0.1")
    tornado.ioloop.IOLoop.instance().start()

if __name__ == "__main__":
    main()

I'm serving up this script with Supervisor by creating a script in /etc/supervisor/conf.d/ called myapp.conf and it looks like this:

[program:myapp]
command=/some/folder/here/scripts/mytornadoscript.py

This is the nginx config:

server {
    listen    80;
    server_name deliciousrobots.com;
    rewrite    ^ http://blog.deliciousrobots.com$request_uri?;
}
server {
        listen       80;
    
        server_name blog.deliciousrobots.com;
        root /some/folder/here;

    	location / {
            proxy_pass      http://127.0.0.1:8001;
            proxy_set_header X-Real-IP $remote_addr;
        }

        location /static/ {
            expires 30d;
        }

        location /wp-content/ {
            expires 30d;
        }

        location /media/ {
            root /usr/share/pyshared/django/contrib/admin;
        }
}

I needed the wp-content from my old wordpress blog because of some image I had uploaded. That's it!

This Blog Now Django-Powered
Posted by postfuturist on 2010-06-03 23:53:25

This blog is now my first public site that I've built with the Python programming language and Django web framework. I needed some motivation to build a project that I could show people, so for the last week or so I've used a few bits of my personal time to build a Django-powered replacement for my WordPress / PHP blog. Django has proved to be simpler and more powerful than I had guessed. I spent likely no more than 15 or 20 hours total working on it, including time spent creating the style sheet and writing a database migration to get my old posts, categories, and comments into the new database.

It's still a bit rough around the edges, and missing a lot of the features of WordPress, but that just gives me things to work on when I'm on the bus to and from work (where most of the code for this blog was written.) I haven't added category pages, just the front page with the latest 10 posts, individual pages for each post with working comments (all comments are moderated for the time being so they will not show up right away), a sitemap.xml file for google's sake, and an RSS Feed.

Again, I've decided to shy away from Apache, even though it is the "easy" way to deploy webpages, especially Django apps. For the WordPress version of the blog, I had been running Nginx on the front, delegating requests to php-cgi instances. I kept Nginx as the frontend server, so all static files are served super fast, and regular page requests are proxied to a Tornado instance. It's bloody fast--even on this $10 a month VPS, and I'm not caching anything, yet. I'm using Supervisor to manage my Tornado script.

I know some things are broken, like images on old posts. I'll get to those, eventually. It's enough that I got it running for right now.

The Reluctant Sysadmin
Posted by postfuturist on 2010-04-25 12:12:04

As a software developer, I work on top of abstraction layers. There are a number of black boxes I build on top of. Compilers and servers fall into this category. The less time I think about the mundane details of how the code I write gets run, the more time I can spend dealing with the higher level abstractions, like "what is this application supposed to do, exactly?" That level of ignorance is helpful at times, but ultimately not healthy to maintain absolutely. That's one reason why I've been steeping myself in the black arts of compiler construction. The other seedy underworld I have placed myself in recently is that of server administration.

I'll cop to this: I suck as a sysadmin. My first act, after putting myself in charge of my very own server (a VPS, actually) was to lock myself out of administrative access. Well, the best way to learn something is by taking it apart and sometimes you break things this way. When I was just a young thing, I would quickly grow tired of playing with toys. Phillips screw drivers were my favorite tool, they allowed me to take apart almost any electronic toy or piece of equipment. Sometimes I broke things. I loved electric motors, I would take them out of my toys, and wire them up to batteries for fun or slightly nefarious purposes. But mostly I turned perfectly good toys into piles of parts. Once I figured out that my desk lamp had quite a bit of electricity flowing through it. I learned this by taking out the bulb and poking my finger into the bare socket. I had seen someone causing water to separate into hydrogen and oxygen (O2) gas by applying electricity, so I placed to wires into a glass of water and connected the other two to the parts of the same lamp socket. This produced a terrific flash of light, and melted some of the wires into balls of molten copper.

Me having a server is like a ten year old boy having 110 volts of electricity at his disposal. I don't really have a lot of experience with server security and I might get a shock here or there, but I probably won't burn the house down. Since you are reading this very blog, I have managed to successfully migrate it to the new server, as well as my wife's blog and a private git repo. I've even made some improvements. Apache isn't even installed on my server. I'm running Nginx which is directly interacting with php running through a CGI interface. I'm using normal WP Cache for page caching and APC for PHP opcode caching and it seems to be pretty snappy. Now that I have a server playground to work with, I can experiment with other technologies, like CouchDB, MongoDB, Node.js, Django, Rails, the oddly-named Hunchentoot, and whatever else I'd like.

All in all, I've had fun with the new server, setting up file permissions, making sure only the services I want running are running, no extra open ports, and all that. Getting Nginx to do my bidding is a bit of a challenge, but worth it compared to the massive hulk that is Apache. All this is possible through extremely inexpensive Linux VPS services provided by ARP Networks. Apparently, these guys don't spend any money advertising, they just are awesome and get business through word of mouth. That's probably why they are so inexpensive. The introductory level VPS is only $10 a month, compared to $20 for Linode or Slicehost for similar service.

Don't believe every blog you read - a cautionary tale.
Posted by postfuturist on 2010-04-19 19:45:02

Right now, I am using DreamHost shared hosting to host my blog. They pretty much do what they say they do. There is an advantage to easy-click installs in the land of web hosting. I'm really not a server administrator. I'm a programmer. I don't like to think about deploying to servers, or monitoring servers, or configuring servers. However, I decided that I wanted a VPS to host my stuff on. I want to run different things like a git-server, maybe a node-js server, OpenID and possibly even email. There is the idea that I shouldn't be beholden to any company for my personal data. I should be able to host the services that are important to me on a server that, for the most part, I control. After shopping around, I decided to go with ARP Networks. They seem to have really competitive pricing for Linux and Free/OpenBSD VPS hosting. So far, I feel like that is probably a good decision.

I didn't really feel like running full blown Apache on the VPS, and according to a little research, I could even port my Wordpress blog over to a VPS just with Nginx, PHP, and MySQL. I found a few blog entries detailing how they got this combination running. Well, there is one that I had gleamed some information from, but it turns out that information was wrong. Here was the command I was supposed to run, assuming that "jsmith" is my user name.

sudo usermod -G webmasters jsmith
That command is supposed to add my user to the webmasters group. Only problem is that it also removes you from every other group. The proper command is:
sudo usermod -a -G webmasters jsmith
That makes the group assignment an append, not a replace. Here is the important bit of the man page for usermod:
-G, --groups GROUP1[,GROUP2,...[,GROUPN]]] A list of supplementary groups which the user is also a member of. Each group is separated from the next by a comma, with no intervening whitespace. The groups are subject to the same restrictions as the group given with the -g option. If the user is currently a member of a group which is not listed, the user will be removed from the group. This behaviour can be changed via the -a option, which appends the user to the current supplementary group list.
OK, now here is the page with the faulty instructions. It's been up since August of 2008, that's nearly two years.

Hopefully, the folks at ARP Networks will be kind and help me out, or else I'm locked out of my VPS permanently. Don't believe every blog you read, even if looks legit and there are a bunch of comments at the bottom stating how useful and awesome the information is. Really, though, it is my fault for running commands that I didn't understand fully. Anything run as superuser should be carefully inspected.

Update: The ARP Networks folks bailed me out of my ignorance. Apparently, I could have fixed it myself with their out-of-band access tools. Today, I wear the scarlet N (for noob.)