Archive

Archive for April, 2008

git add before commit

April 28th, 2008
Comments Off

I’ve been experimenting with git for version control of my document folder, before I use it professionally. It has several things I like, particularly the blazing speed and the fact that there’s a single .git directory instead of a myriad of .svn all over the place (which made it a bit of a pain to keep those directories in sync if one of of the sub-.svn’s got erased by, say, an over-eager script).

Coming from subversion and cvs, something struck me as odd: if you do git commit, it will only commit the changes that you have just added or removed – anything else needs to be explicitly added to the working index, even if you have added it before. Bit of a pain if you simply want to commit everything.

Digging around the git docs, there’s an option you can pass so that it will just commit all files you have previously told it about: git commit -a. There’s also an option invoked by git commit –interactive that causes it to ask you for each file if you want it to go on the current commit or not.

As to why that is:

What git add does is to move the current version of the named file to a special staging area, holding files that are ready to be committed. And what git commit (without other arguments) will do is to take the index and make a new revision out of what the index contains. git commit -a is just a convenience which adds all modified files to the index, and then commits the result.

How does this affect you? The first thing to remember is this one: only run git add on new files just before committing. Otherwise, you’ll commit the wrong contents of the file.

It takes a bit getting used to, but it’s a lovely tool so far. If you’re thinking about using it yourself, start by reading Git Magic, and then after the first three chapters move to Using git without feeling stupid and its part 2.

Ricardo Programming

Clay Shirky on cognitive surplus

April 27th, 2008
Comments Off

I was recently reminded of some reading I did in college, way back in the last century, by a British historian arguing that the critical technology, for the early phase of the industrial revolution, was gin.

The transformation from rural to urban life was so sudden, and so wrenching, that the only thing society could do to manage was to drink itself into a stupor for a generation.

So begins Clay Shirky’s article on how media is changing, and how some people just don’t get the reasons for the change. It’s not just your standard how-is-tv-like-booze piece – instead it goes deeper into not only how this cognitive surplus is being applied, but why it’s just an infinitesimal piece of what could be used, and where do people find the time.

There’s an anecdote near the end that I just hope is true.

Ricardo Science and Technology, The future

Pragmatic Programming in Erlang, chapter 8

April 24th, 2008
Comments Off

Lately I’ve been reading Joe Armstrong’s Pragmatic Programming in Erlang, learning a couple new tricks. In chapter 8 he proposes a problem:


Write a ring benchmark. Create N processes in a ring. Send a message round the ring M times so that a total of N * M messages get sent. Time how long this takes for different values of N and M.

Here is my solution:

-module(ringproblem).
-export([start/2, ring/1, rpc/2, benchmark/3]).

% Spawns a function and registers it as an atom.
start(AnAtom, Fun) ->
    Pid = spawn(Fun),
    register(AnAtom, Pid).

%% This loop receives a parameter that's either the next Pid on the chain,
%% or null if this is the last process on the chain.  It then passes the
%% message to the next process. Once the cycle has been completed, it
%% calls back the original caller to let it know.
loop(F) ->
    receive
	{ From, 0, Counter, Message } ->
	    F ! die, % tell the next process to die
	    From ! { ended, Counter },
	    io:format("Cycle for ~p ended.~n", [Message]);
	{ From, Number, Counter, Message } ->
	    case F of
		void ->
		    firstProcess ! { From, Number - 1, Counter + 1, Message };
		_Other ->
		    F ! { From, Number, Counter + 1, Message }
	    end,
	    loop(F);
	die ->
	    case F of
		void ->
		    io:format("Last process died");
		_Other ->
		    F ! die,
		    void
	    end;
	Other ->
	    io:format("I don't know what to do with ~p.~n",[Other]),
	    loop(F)
    end.

%% Sets up a ring of at least 2 elements by recursively building it back
ring(Elements) when Elements >= 2 ->
    Pid = spawn(fun() -> loop(void) end),
    ring(Elements - 1, Pid).

%% If we have no more elements, this is the first process. Register it.
ring(0, Pid) ->
   register(firstProcess, Pid);
%% otherwise walk back
ring(N, Pid) ->
    PrevPid = spawn(fun() -> loop(Pid) end),
    ring(N-1, PrevPid).

%% Do a RPC call to the first process, which should have been registered, and
%% wait until we receive a message telling us that the cycle is done.
rpc(Times, Request) ->
    statistics(runtime),
    statistics(wall_clock),
    firstProcess ! { self(), Times, 0, Request },
    receive
	{ ended, Counter } ->
	    {_, Time1} = statistics(runtime),
	    {_, Time2} = statistics(wall_clock),
	    U1 = Time1 * 1000,
	    U2 = Time2 * 1000,
	    io:format("Ring time for ~p calls = ~p (~p) microseconds~n",  [Counter, U1, U2])
    end.

benchmark(Elements, Times, Request) ->
    ring(Elements),
    rpc(Times, Request).

You would run it like this:


Eshell V5.6.2 (abort with ^G)
1> c(ringproblem).
{ok,ringproblem}
2> ringproblem:benchmark(1000, 3000, "Round and Round").
Cycle for "Round and Round" ended.
Ring time for 3000000 calls = 8360000 (8416000) microseconds
ok
3>

And eventually, possibly a couple seconds later, you’ll get a notification that the last process has died.

Ricardo Programming