Mike Schaeffer's Weblog
Fri, 04 Mar 2005
Maybe this should have been obvious from the beginning, but
I'm no longer putting "general interest" blog posts at
the root for the topic. Rather, those posts are now going
under a "general" subtopic of the root.
The problem with making general interest posts at the root of a topic is that there's then no way to watch only the general topics. If you look at the root topic, you get the whole topic.
reddit this! Digg Me!
The problem with making general interest posts at the root of a topic is that there's then no way to watch only the general topics. If you look at the root topic, you get the whole topic.
reddit this! Digg Me!
[/tech/this_blog] permanent link
It never ceases to amaze me how much good material there is
online. Here's some more:
Ps: Be sure to check out Olin Shiver's philosophy of undergraduate advising. It's an example to be followed. ;-)
reddit this! Digg Me!
Ps: Be sure to check out Olin Shiver's philosophy of undergraduate advising. It's an example to be followed. ;-)
reddit this! Digg Me!
I'm writing some content for a future post on the offshoring of jobs overseas,
but I want to clear something up before it gets posted: Outsourcing and offshoring
are two different and orthogonal concepts. This seems to be something that gets
misunderstood a great deal, but simply put, outsourcing is the movement of
jobs to a different company and offshoring is the movement of
jobs to a different country. Either one can be done without the other.
The scenarios that people tend to get upset about (at least in the United States) are the scenarios involving offshoring, the movement of work overseas. Outsourcing, however, does not necessarily imply that the work gets moved to a different country: it's very common for work to be outsourced to another American business employing American workers. An example of this is hiring a Madison Avenue firm to put together an ad campaign. Sure, it'd be possible to develop the talent in house to do this yourself, but there are many advantages in outsourcing the work to a more specialized vendor.
reddit this! Digg Me!
The scenarios that people tend to get upset about (at least in the United States) are the scenarios involving offshoring, the movement of work overseas. Outsourcing, however, does not necessarily imply that the work gets moved to a different country: it's very common for work to be outsourced to another American business employing American workers. An example of this is hiring a Madison Avenue firm to put together an ad campaign. Sure, it'd be possible to develop the talent in house to do this yourself, but there are many advantages in outsourcing the work to a more specialized vendor.
reddit this! Digg Me!
[/tech/business] permanent link
This
is cool. What it is is a web-based color picker that automatically gives
you a couple different kinds of complementary colors.
reddit this! Digg Me!
reddit this! Digg Me!
[/tech/general] permanent link
A few months ago, my wife and I recently switched from a
Sanyo 4700 and a 4900 on Sprint PCS to a pair of
Sony Ericsson T-637's
on bCingular Wireless. Overall, the
switch has been an improvement, but there are still a few nagging issues:
I guess that looks like a lot of complaining, but otherwise the phone is very nice. The last phone I've liked as much is my old Nokia 8260 (and the 6160 before that). The Sanyo 4900 doesn't even come close. I'm happy enough with this phone to consider buying another Sony Ericsson. (The new W800i looks pretty nice...)
reddit this! Digg Me!
I guess that looks like a lot of complaining, but otherwise the phone is very nice. The last phone I've liked as much is my old Nokia 8260 (and the 6160 before that). The Sanyo 4900 doesn't even come close. I'm happy enough with this phone to consider buying another Sony Ericsson. (The new W800i looks pretty nice...)
reddit this! Digg Me!
[/tech/products] permanent link
Wed, 02 Mar 2005
I'm in the middle of developing a Scheme compiler for a future release of
vCalc. While I've been developing the code, I've peppered it full of debugging
print statements that look something like this:
with the output statements in place, the compiler takes about 250-300ms to compile relatively small functions. Not great, particularly considering that there's no optimization being done at all. Anyway, on a hunch I removed the format statements, and execution time improved by a couple orders of magnitude to a millisecond or two per function. That's a lot closer to what I was hoping for at this stage of development.
On the other hand, I hadn't realized that my (ad hoc, slapped together in an hour) format function was running quite that slowly. I think it'll end up being an interesting optimnization problem sooner or later.
reddit this! Digg Me!
(format #t "compiling ~l, tail?=~l, value?=~l" form tail? value?)
with the output statements in place, the compiler takes about 250-300ms to compile relatively small functions. Not great, particularly considering that there's no optimization being done at all. Anyway, on a hunch I removed the format statements, and execution time improved by a couple orders of magnitude to a millisecond or two per function. That's a lot closer to what I was hoping for at this stage of development.
On the other hand, I hadn't realized that my (ad hoc, slapped together in an hour) format function was running quite that slowly. I think it'll end up being an interesting optimnization problem sooner or later.
reddit this! Digg Me!
Tue, 01 Mar 2005
This be should part of the Win32 API if it's not already.
Basically, it amounts to a variant of the MessageBox API that allows custom button labels, rather than just "Yes",
"No", "Abort", "Retry", etc.
Maybe this kind of API would have made abominations like this less likely:
At least users might be able to avoid calling errors "OK", of all things...
reddit this! Digg Me!
Maybe this kind of API would have made abominations like this less likely:
At least users might be able to avoid calling errors "OK", of all things...
reddit this! Digg Me!
[/tech/general] permanent link
Idempotence has benefits at a program's run-time, as well as at
build time. To illustrate, consider the case of a reference
counted string. For the sake of example, it might be declared like
this (In case you're wondering, no, I don't think this is a
production-ready counted string library...):
The reference counting mechanism buys you two things. It gives you the ability to delete strings when they're no longer accessible; It also gives you the abilty to avoid string copies by deferring them to the last possible moment. This second benefit, known as copy-on-write, is where idempotence can play a role. What copy on write entails is ensuring that whenever you write to a resource, you ensure that you have a copy unique to to yourself. If the copy you have isn't unique, copy-on-write requires that you duplicate the resource and modify the copy instead of the original. If you never modify the string, you never make the copy.
This means that the beginning of every string function that alters a string has to look something like this:
Apply a little refactoring, and you get this...
Of course,
Next up are a few more examples of idempotence, as well as a look into some of the pitfalls.
reddit this! Digg Me!
struct CountedString
{
int _references;
char *_data;
};
CountedString *makeString(char *data)
{
CountedString cs = (CountedString *)malloc(sizeof(CountedString));
cs->_references = 1;
cs->_data = strdup(data);
return 1;
}
CountedString *referToString(CountedString *cs)
{
cs->_references++;
return cs;
}
void doneWithString(CountedString *cs)
{
cs->_references--;
if (cs->_references == 0)
{
free(cs->_data);
free(cs);
}
}
// ... useful library functions go here...
The reference counting mechanism buys you two things. It gives you the ability to delete strings when they're no longer accessible; It also gives you the abilty to avoid string copies by deferring them to the last possible moment. This second benefit, known as copy-on-write, is where idempotence can play a role. What copy on write entails is ensuring that whenever you write to a resource, you ensure that you have a copy unique to to yourself. If the copy you have isn't unique, copy-on-write requires that you duplicate the resource and modify the copy instead of the original. If you never modify the string, you never make the copy.
This means that the beginning of every string function that alters a string has to look something like this:
CountedString *alterString(CountedString *cs)
{
if (cs->_references > 1)
{
CountedString *uniqueString = makeString(cs->_data);
doneWithString(cs);
cs = uniqueString;
}
\\ ... now, cs can be modified at will
return cs;
}
Apply a little refactoring, and you get this...
CountedString *ensureUniqueInstance(CountedString *cs)
{
if (cs->_references > 1)
{
CountedString *uniqueString = makeString(cs->_data);
doneWithString(cs);
cs = uniqueString;
}
return cs;
}
CountedString *alterString(CountedString *cs)
{
cs = ensureUniqueReference(cs);
\\ ... now, cs can be modified at will
return cs;
}
Of course,
ensureUniqueInstance ends up being idempotent: it gets you
into a known state from an unknown state, and it doesn't (semantically) matter if
you call it too often. That's the key insight into why idempotence can be useful.
Because idempotent processes don't rely on foreknowledge of your system's state to work reliably,
they can be a predictable means to get into a known state. Also, If you hide
idempotent processes behind the appropriate abstractions, they allow you to write
code that's more self documenting. A function that begins with a line like
cs = ensureUniqueInstance(cs); more clearly says to the reader that it
needs a unique instance of cs than lines of code that check the reference count of
cs and potentially duplicate it.
Next up are a few more examples of idempotence, as well as a look into some of the pitfalls.
reddit this! Digg Me!
[/tech/programming/idempotence] permanent link
Another useful blog from Microsoft.
Michael Kaplan has been blogging
for quite some time on internationalization and other Unicode-related issues.
His blog full of deep, technical information on a part of Windows that seems
to get overlooked a lot. I've been starting the very first steps of getting
vCalc (and my Scheme interpreter) to be Unicode aware, so his blog has been
timely reading.
I've also found, via Lambda the Ultimate, a website dedicated to Alexander Stepanov's papers and code. Stepanov is one of the principals behind the C++ STL (STepanov and Lee) Standard Template Library.
reddit this! Digg Me!
I've also found, via Lambda the Ultimate, a website dedicated to Alexander Stepanov's papers and code. Stepanov is one of the principals behind the C++ STL (STepanov and Lee) Standard Template Library.
reddit this! Digg Me!
[/tech/general] permanent link
Over the last several months, I've been spending a great deal of time
in New York City on business. In that time, I have never been quite
as suprised by prices as I have tonight. I wasn't even trying to
do anything all that unusual, just two loads of laundry.
Normally, I'd expect that two loads of laundry would cost about $6. The washer would be $1.50 or so per run, and the dryer would be another $1.50 per run, for a total of $6. Maybe even $7.50, if you decide to run a second dryer cycle. Even in New York (west Midtown Manhattan), I've been in apartments recently that charge about that much.
However, this apartment is special: they use a "smart" card system to manage payments. There's a dispenser on the side of the wall that sells $7 cards for $10 (cards themselves cost $3). The dispenser also allows you to reload cards in $5 and $10 increments. Once you have a card, there are slots in each of the washers and dryers that accept the card and debit from it the $2.50 it takes to buy a cycle in one of the machines. Yes, you read that right: $2.50. $2.50 in my apartment complex buys a 34 minute washer cycle or a 30 (yes, 30) minute dryer cycle.
So tonight, I spent $15 (200% of my estimate) and got this:
The part of this that bothers me the most is the $3 surcharge on the smart card. Thanks to the pricing structure of the laundromat, the $3 surcharge really amounts to a $5 surcharge. This means that someone was either stupid enough not to notice that customers would always end up with $2 of useless change, or was malicious enough to use this as a sleazy way to bilk customers out of an extra $2. Not to mention that I get the hassle of trying not to lose this stupid card, lest I want to drop another $5 on yet another card.
reddit this! Digg Me!
Normally, I'd expect that two loads of laundry would cost about $6. The washer would be $1.50 or so per run, and the dryer would be another $1.50 per run, for a total of $6. Maybe even $7.50, if you decide to run a second dryer cycle. Even in New York (west Midtown Manhattan), I've been in apartments recently that charge about that much.
However, this apartment is special: they use a "smart" card system to manage payments. There's a dispenser on the side of the wall that sells $7 cards for $10 (cards themselves cost $3). The dispenser also allows you to reload cards in $5 and $10 increments. Once you have a card, there are slots in each of the washers and dryers that accept the card and debit from it the $2.50 it takes to buy a cycle in one of the machines. Yes, you read that right: $2.50. $2.50 in my apartment complex buys a 34 minute washer cycle or a 30 (yes, 30) minute dryer cycle.
So tonight, I spent $15 (200% of my estimate) and got this:
The part of this that bothers me the most is the $3 surcharge on the smart card. Thanks to the pricing structure of the laundromat, the $3 surcharge really amounts to a $5 surcharge. This means that someone was either stupid enough not to notice that customers would always end up with $2 of useless change, or was malicious enough to use this as a sleazy way to bilk customers out of an extra $2. Not to mention that I get the hassle of trying not to lose this stupid card, lest I want to drop another $5 on yet another card.
reddit this! Digg Me!