Monday Jun 27, 2011

Building a physical CPU load meter

I built this analog CPU load meter for my dev workstation:

All I did was drill a few holes into the CPU and probe the power supply lines...

Okay, I lied. This is actually a fun project that would make a great intro to embedded electronics, or a quick afternoon hack for someone with a bit of experience.

The parts

The main components are:

• Current meter: I got this at MIT Swapfest. The scale printed on the face is misleading: the meter itself measures only about 600 microamps in each direction. (It's designed for use with a circuit like this one). We can determine the actual current scale by connecting (in series) the analog meter, a variable resistor, and a digital multimeter, and driving them from a 5 volt power supply. This lets us adjust and reliably measure the current flowing through the analog meter.

• Arduino: This little board has a 16 MHz processor, with direct control of a few dozen input/output pins, and a USB serial interface to a computer. In our project, it will take commands over USB and produce the appropriate amount of current to drive the meter. We're not even using most of the capabilities of the Arduino, but it's hard to beat as a platform for rapid development.

• Resistor: The Arduino board is powered over USB; its output pins produce 5 volts for a logic 'high'. We want this 5 volt potential to push 600 microamps of current through the meter, according to the earlier measurement. Using Ohm's law we can calculate that we'll need a resistance of about 8.3 kilohms. Or you can just measure the variable resistor from earlier.

We'll also use some wire, solder, and tape.

Building it

The resistor goes in series with the meter. I just soldered it directly to the back:

Some tape over these components prevents them from shorting against any of the various junk on my desk. Those wires run to the Arduino, hidden behind my monitor, which is connected to the computer by USB:

That's it for hardware!

Code for the Arduino

The Arduino IDE will compile code written in a C-like language and upload it to the Arduino board over USB. Here's our program:

``````#define DIRECTION 2
#define MAGNITUDE 3

void setup() {
Serial.begin(57600);
pinMode(DIRECTION, OUTPUT);
pinMode(MAGNITUDE, OUTPUT);
}

void loop() {
if (x == -1)
return;

if (x < 128) {
digitalWrite(DIRECTION, LOW);
analogWrite (MAGNITUDE, 2*(127 - x));
} else {
digitalWrite(DIRECTION, HIGH);
analogWrite (MAGNITUDE, 255 - 2*(x - 128));
}
}
``````

When it turns on, the Arduino will execute `setup()` once, and then call `loop()` over and over, forever. On each iteration, we try to read a byte from the serial port. A value of `-1` indicates that no byte is available, so we `return` and try again a moment later. Otherwise, we translate a byte value between 0 to 255 into a meter deflection between −600 and 600 microamps.

Pins 0 and 1 are used for serial communication, so I connected the meter to pins 2 and 3, and named them `DIRECTION` and `MAGNITUDE` respectively. When we call `analogWrite` on the `MAGNITUDE` pin with a value between 0 and 255, we get a proportional voltage between 0 and 5 volts. Actually, the Arduino fakes this by alternating between 0 and 5 volts very rapidly, but our meter is a slow mechanical object and won't know the difference.

Suppose the `MAGNITUDE` pin is at some intermediate voltage between 0 and 5 volts. If the `DIRECTION` pin is low (0 V), conventional current will flow from `MAGNITUDE` to `DIRECTION` through the meter. If we set `DIRECTION` high (5 V), current will flow from `DIRECTION` to `MAGNITUDE`. So we can send current through the meter in either direction, and we can control the amount of current by controlling the effective voltage at `MAGNITUDE`. This is all we need to make the meter display whatever reading we want.

Code for the Linux host

On Linux we can get CPU load information from the `proc` special filesystem:

``````keegan@lyle\$ head -n 1 /proc/stat
cpu  965348 22839 479136 88577774 104454 5259 24633 0 0
``````

These numbers tell us how much time the system's CPUs have spent in each of several states:

1. user: running normal user processes
2. nice: running user processes of low priority
3. system: running kernel code, often on behalf of user processes
4. idle: doing nothing because all processes are sleeping
5. iowait: doing nothing because all runnable processes are waiting on I/O devices
6. irq: handling asynchronous events from hardware
7. softirq: performing tasks deferred by irq handlers
8. steal: not running, because we're in a virtual machine and some other VM is using the physical CPU
9. guest: acting as the host for a running virtual machine

The numbers in `/proc/stat` are cumulative totals since boot, measured in arbitrary time units. We can read the file twice and subtract, in order to get a measure of where CPU time was spent recently. Then we'll use the fraction of time spent in states other than idle as a measure of CPU load, and send this to the Arduino.

We'll do all this with a small Python script. The pySerial library lets us talk to the Arduino over USB serial. We'll configure it for 57,600 bits per second, the same rate specified in the Arduino's `setup()` function. Here's the code:

``````#!/usr/bin/env python

import serial
import time

port = serial.Serial('/dev/ttyUSB0', 57600)

old = None
while True:
with open('/proc/stat') as stat:
if old is not None:
diff = [n - o for n, o in zip(new, old)]
idle = diff[3] / sum(diff)
port.write(chr(int(255 * (1 - idle))))
old = new
time.sleep(0.25)
``````

That's it!

That's all it takes to make a physical, analog CPU meter. It's been done before and will be done again, but we're interested in what you'd do (or have already done!) with the concept. You could measure website hits, or load across a whole cluster, or your profits from trading Bitcoins. One standard Arduino can run at least six meters of this type (being the number of pins which support `analogWrite`), and a number of switches, knobs, buzzers, and blinky lights besides. If your server room has a sweet control panel, we'd love to see a picture!

~keegan

Saturday May 07, 2011

Improving your social life with git

I've used RCS, CVS, Subversion, and Perforce. Then I discovered distributed version control systems. Specifically, I discovered git. Lightweight branching? Clean histories? And you can work offline? It seemed to be too good to be true.

But one important question remained unanswered: Can git help improve my social life? Today, we present to you the astonishing results: why yes, yes it can. Introducing gitionary. The brainchild of Liz Denys and Nelson Elhage, it's what you get when you mash up Pictionary, git, and some of your nerdiest friends.

Contestants get randomly assigned git commands and are asked to illustrate them. They put this bold idea to the test quite some time ago in an experiment/party known only as `git drunk` (yes, some alcohol may have been involved), and we've reproduced selected results below. Each drawing is signed with the artist's username, and the time it took our studio audience to correctly guess the git command.

Suffice it to say, git is complicated. Conceptually, git is best modeled as a set of transformations on a directed acyclic graph, and sometimes it's easiest to illustrate it that way, as with this illustration of `git rebase`:

On other occasions, a more literal interpretation works best:

But not always:

A little creativity never hurts, though, which is why this is my personal favorite from the evening:

You can find more details (and the full photoset from the evening) at Liz's writeup of the event. Download the gitionary cards, print them double-sided on card stock, and send us pictures of your own gitionary parties!

Thursday Jul 29, 2010

Today is System Administrator Appreciation Day, and being system administrators ourselves,  we here at Ksplice decided to have a little fun with this holiday.

We've taken a break, drank way too much coffee, and created a very special Choose Your Own Adventure for all the system administrators out there.

Feedback and comments welcome. Above all: Happy System Administrator Appreciation Day. Share the love with your friends, colleagues, and especially any sysadmins you might know.

Wednesday Jun 16, 2010

ntris: an idea taken a step too far

About nine months ago, I lost a lot of free time to a little applet called Pentris. The addition of pentomino pieces made the gameplay quite different from the original falling block game, but I couldn't help but think that Pentris didn't go far enough. As a programmer, I had to implement the natural generalization of the game. After a much longer development cycle than I had originally anticipated, ntris is now ready. (You'll need Java to run the applet.)

In ntris, as your score increases, so does the probability that you will get increasingly large polyominoes. At the beginning, you'll only get pieces made of 1-5 squares. By the time your score gets to 100, about one piece in three will be a hexomino - and that's still just the beginning. Very few of my beta-testers have survived long enough to see a decomino. The current high is 421, by wuthefwasthat - can you beat it?

Here's a few of my most feared pieces.

You don't want to see these in your queue.

Everyone who plays ntris is familiar with these pieces. From left to right: the mine, whose rotational symmetry and hot pink color make a deadly combination; the jerk, and its close relative, the donut, which are the smallest pieces with non-trivial homotopy; and the dog, one of the pieces I call "animals", for obvious reasons.

I've also implemented a multiplayer mode in which you can face off against another player. In play-testing, I found that a large polyomino was a much more intimidating attack than the usual garbage, so clearing lines sends larger pieces to your opponents. I think multiplayer ntris offers something no other game does: the satisfaction of making your opponent play a monstrous nonomino. They're not clearing lines anytime soon.

Dealing with a massive piece.

When you just start out playing ntris, there are a few things you should remember.

• Don't be too greedy. Creating a deep empty column is a sure way to lose.
• Pay attention to your queue. Plan ahead when you see a large piece coming.
• You can hold a bad piece if you can't place it, but don't keep it there too long.
• Use singletons to fix your board. Maneuver them into holes and bad spots.

I should also tell you about a more advanced ntris technique, "laying it across", which is a key element of higher-level play.

Lay it across

What makes ntris different from Tetris, Blockles, and Pentris? Some simple math reveals a major gameplay difference between ntris and the other games. Let's look at Tetris first. The playing field is 10 columns wide, and each piece takes up four squares. That means that, asymptotically, you have to clear 4/10 of a line with each drop. Suppose that you use a standard open column strategy and only clear lines with 4-longs. Each one clears 4 lines, and there are 6 other tetrominoes, so, you clear, on average, 4/7 of a line per piece - enough to stay alive.

At the start of ntris, you could get any of the 29 pieces made of 1-5 squares. These pieces have, on average, 4.38 squares per piece. The board is 12 columns wide, so you have to clear 4.38/12 = 0.365 lines per drop. If you use only straight pieces to clear lines, you clear on average 15 lines every 29 pieces, or 0.517 lines per piece. But clearing multiple lines at a time yields large score bonuses, so if you're greedy, you'll only clear lines when you get a 4-long or a 5-long. Naiively, this means that you only clear 9 lines every 29 pieces - 0.310 lines per piece - so you are bound to lose.

The solution is skimming, or clearing lines with the horizontal parts of your pieces. By skimming, you can clear four lines with the long-L-block and the long-J-block, as well as with the 4-long.

Skimming a long-L-block.

Similarly, when you start getting hexominoes, you can clear five lines with more than just the 5-long. If you do the math, you'll see that with a score over 100, you must use some form of skimming just to clear lines fast enough to survive. When you start to get even larger blocks, you'll have to take skimming to an extreme to deal with them. Here's a good example of how you "lay it across":

a) A nasty piece. b) Lay it across. c) Play more pieces on the same line. d) The play resolves.

To lay a piece across, play the piece such that most of it falls on a single horizontal line. Clear that line with the next few pieces. Laying it across can be counter-intuitive, since it often creates several holes in your board, but it is often the only viable way to play a piece. A word of caution: before laying a piece across, you should always think ahead a few moves, to be sure that the play will resolve quickly. Otherwise, you run the risk of covering part of your board with the piece that wouldn't go away.

I'm only an average ntris player, and we have just scratched the surface of ntris strategy. Many of you will be much better than me at this game. The server is always running, and I promise this game isn't as hard as it might seem. Can you get the high score in ntris?

Please note: ntris is my personal project and is not affiliated with or endorsed by Ksplice or the makers of Tetris. Please see www.tetris.com for more information about Tetris.