Sunday, June 28, 2009
AmazonFresh is a win.
Yep. I did all my grocery shopping yesterday on the Intertubes while doing serious multitasking between Chinese homework and a ton of other stuff. I never even left my comfortable IKEA armchair.
And, this morning when I woke up, all my groceries and stuff magically appeared on my doorstep. That's right! Intertube Magic! No prizes for guessing where I'm going to do all my grocery shopping in future. AmazonFresh delivers. In fact, they deliver so fast that you can shop today and have your stuff by 6am tomorrow morning.
AmazonFresh seriously makes grocery shopping fun. You don't need to drive to the grocery store, look for parking, walk to the store, traverse every single aisle to find your stuff, queue up to pay, take all your stuff out of the cart to be scanned, walk back to your car, load up your car, drive home, and unload your car. You get the point.
Manual grocery shopping is tedious, tiring, and ultimately, untechnological. The modern man shouldn't have to go to the grocery store; the grocery store ought to come to him. With any luck AmazonFresh will turn out to be a commercial success. The service is currently in "beta" for selected neighborhoods around the Seattle area.
What strikes me about AmazonFresh is their environmentally friendly techniques. All their totes (see image above) and internal temperature-control packaging/gels are recollected and reused. Ice cream was among one of the refrigerated items I bought; it arrived hard as a rock (dry ice win). Also, the fact that I don't have to take my 17.5mpg vehicle out to get groceries does wonders to the environment too.
It's cool to be green these days.
(On a side note: The above image was taken with the iPhone 3GS's new 3 megapixel camera. The quality is stunning.)
Friday, June 26, 2009
The Dawn of a New Technological Era
To put this into perspective, consider the following scenario: You are somewhere far away from campus and the weather is scorching hot. You need to return to campus. Now, the options are bleak for the man untouched by the information-on-demand revolution: he is forced (by nature) to walk back to campus in the scorching heat, or, he is required to carry an array of local bus schedules with him and has to further look them up in order to compute a dignified route back to campus.
Something about those scenarios should strike the modern man as insulting. The idea that the modern man has to walk any further than the distance from his house to his car must certainly come off as an assault on his technological dignity (after all, he should have been able to use his technology to ameliorate a humiliating walk in the scorching sun).
Likewise, the alternative of having to fumble over a bagload of bus schedules in order to successfully avoid such a humiliating walk must also come off as equally insulting. Why should the modern man have to bother himself with laborious calculations in order to live the technological life? Shouldn't his technology be already able to achieve this feat? Is it possible for the modern man to avoid the humiliating walk, and at the same time not carry around those schedules or perform tedious calculations?
The answer, in 2009, is, yes, and the solution is the iPhone 3GS. That entire stack of bus schedules can be replaced with something better -- far better. That something is the Internet. Throw in GPS, a directional compass, and the armada of features that Google Maps provides and you've got yourself a mobile navigation system that allows the modern man to shield himself from yet another insult that Mother Nature tries to inflict upon him. No manual calculations required -- just select the place you want to go to and the technology figures it all out.
But this is just the beginning. Such a level of "life simplification" would have been unthinkable just a few years ago. It is incredible to observe how much technology has advanced within a span of just a few years. Who knows what the next few years will have in store for the modern man.
Monday, June 15, 2009
Saturday, June 13, 2009
Paper is Dead: Bring on the Cloud Computing Revolution
I just coredumped my home. That's right: I literally threw out everything I didn't need and couldn't eBay. Now all the stuff that remains is what I might need (very conservative definition of "might need") and stuff I plan to eBay soon. What surprised me was what I threw out this time and the reasons for throwing them out:
No one has the time anymore to comb through a library of books to find something. What's worse still is that these books tend to get outdated extremely quickly. Technological progress is happening so fast that any book over a few years old is no longer relevant enough to be worth reading. Newspapers are dead as well. The modern man wants his information immediately, up-to-date, and in such a way that it is easy to catalogue, organize and search. This is an area that upcoming eInk readers are bound to find their place (especially once color eInk screens come of age). There are huge secondary benefits as well, namely that you don't need to cut down any trees to produce PDFs.
In addition to all that, the cloud computing revolution also makes the modern man less vulnerable to catastrophes such as fire. House burns down? No problem: everything's safe on the cloud. Just cash out your insurance check, buy a new house and computer, and you're back in business. You just can't go wrong with the cloud.
Most proper clouds are extremely resistant to failure as well. Plus, you already have a local copy of your data on your computer. So, even in the super-ultra-unbelievably-unlikely event that the cloud crashes, you're still got your data stored locally anyway. I'm still experimenting with clouds and waiting for the ultimate cloud-to-end-all-clouds, the Google Drive, to be launched.
The revolution has begun.
- All my photographic negatives, associated photo CDs, and a bunch of paper photographs. (Reason: They were all already digitized and stored on my computers and the Cloud)
- Every single old homework, along with exams I didn't want to keep. (Reason: Never even looked at them for over a year)
- A few outdated books with no resale value. (Books are so last year. Anything worth reading these days is indexed and stored on the Cloud, where it can be easily searched for.)
- A bunch of other assorted garbage no one in the 21st century uses anymore.
No one has the time anymore to comb through a library of books to find something. What's worse still is that these books tend to get outdated extremely quickly. Technological progress is happening so fast that any book over a few years old is no longer relevant enough to be worth reading. Newspapers are dead as well. The modern man wants his information immediately, up-to-date, and in such a way that it is easy to catalogue, organize and search. This is an area that upcoming eInk readers are bound to find their place (especially once color eInk screens come of age). There are huge secondary benefits as well, namely that you don't need to cut down any trees to produce PDFs.
In addition to all that, the cloud computing revolution also makes the modern man less vulnerable to catastrophes such as fire. House burns down? No problem: everything's safe on the cloud. Just cash out your insurance check, buy a new house and computer, and you're back in business. You just can't go wrong with the cloud.
Most proper clouds are extremely resistant to failure as well. Plus, you already have a local copy of your data on your computer. So, even in the super-ultra-unbelievably-unlikely event that the cloud crashes, you're still got your data stored locally anyway. I'm still experimenting with clouds and waiting for the ultimate cloud-to-end-all-clouds, the Google Drive, to be launched.
The revolution has begun.
Tuesday, June 09, 2009
Monday, June 08, 2009
Words. The leadup to the 322 final...
Right. I've got two finals this week. CSE 322 (Automata) and CSE 341 (Noobified Languages). The CSE 322 final is about 2 and half hours away so right now I'm just doing nothing in the leadup to that. My philosophy is that I should have already figured everything out by the last day of class, and hence the time between the last day of class and the final ought to be spent doing practice problems and developing exam strategies.
The idea is that you get as much sleep as possible before in the leadup to a final, enter the exam with a clear mind, then use that built-up energy to burn right through it in a 1.83 hour blaze. Studying right before a final, or, worse, "burning the midnight oil", depletes energy from this "1.83 hour cache" which impairs performance.
The CSE 322 final probably won't be as bad because I suspect it would be more a test of knowledge than a test of speed. The same, however, cannot be said of the CSE 341 (Noobified Languages) final this coming Wednesday. I'm anticipating an ultra-mega test of speed unlike anything I've witnessed before (remember the CSE 321 final). You basically learn 3 "programming" languages in the following order of execution speed in CSE 341 (they are taught in the following order as well):
I'm so glad I'm done with these playground languages and my senior year will mark the beginning of the real stuff (CPU Organization & Assembly, Operating Systems, Networks, Security, etc).
The idea is that you get as much sleep as possible before in the leadup to a final, enter the exam with a clear mind, then use that built-up energy to burn right through it in a 1.83 hour blaze. Studying right before a final, or, worse, "burning the midnight oil", depletes energy from this "1.83 hour cache" which impairs performance.
The CSE 322 final probably won't be as bad because I suspect it would be more a test of knowledge than a test of speed. The same, however, cannot be said of the CSE 341 (Noobified Languages) final this coming Wednesday. I'm anticipating an ultra-mega test of speed unlike anything I've witnessed before (remember the CSE 321 final). You basically learn 3 "programming" languages in the following order of execution speed in CSE 341 (they are taught in the following order as well):
- Slow (ML)
- Slower (Scheme)
- Slowest (Ruby)
I'm so glad I'm done with these playground languages and my senior year will mark the beginning of the real stuff (CPU Organization & Assembly, Operating Systems, Networks, Security, etc).
Tuesday, June 02, 2009
Heap and Static space executable as well!
That's right. This refers to the previous post. I didn't think this would work, but after some tests, the static data space and the heap are indeed marked as executable. At least on Attu (one of my university's linux box systems).
Executing code dynamically on the heap:
That prints "d = 8", as expected. And dynamic execution directly from the static data space:
That prints "e = 70", as expected from 100-30.
These tricks, of course, are not portable as the machine code is specific to the x86 architecture. But that's not really an issue because world+dog are all using x86 processors anyway. It really depends what your code is designed to do. One scenario I can think of is if you're developing a program for the PC and iPhone that share the same core. The iPhone runs on the ARM architecture so obviously you'll want to use canonical C programming techniques keep the core of the program portable.
Executing code dynamically on the heap:
char *lamb = malloc( 5000 );
strcpy( lamb, "\x55\x89\xe5\x8b\x55\x0c\x8b\x45\x08\x29\xd0\x5d\xc3" );
d = ((int (*)(int, int)) lamb)(10, 2);
free( lamb );
printf( " d = %d\n", d );That prints "d = 8", as expected. And dynamic execution directly from the static data space:
e = ((int (*)(int, int)) "\x55\x89\xe5\x8b\x55\x0c\x8b\x45\x08\x29\xd0\x5d\xc3")(100, 30);
printf( " e = %d\n", e );That prints "e = 70", as expected from 100-30.
These tricks, of course, are not portable as the machine code is specific to the x86 architecture. But that's not really an issue because world+dog are all using x86 processors anyway. It really depends what your code is designed to do. One scenario I can think of is if you're developing a program for the PC and iPhone that share the same core. The iPhone runs on the ARM architecture so obviously you'll want to use canonical C programming techniques keep the core of the program portable.
Monday, June 01, 2009
Lambda Functions: Yep, C's got them too.
Right. It's been interesting taking CSE 341 and learning about lambda functions along with all the hoo-hah that goes along with it. You might be surprised to learn that C has lambda functions too. Yes. That's right. Except that you have to write them in machine code :)
But, fundamentally, this is how lambda functions are implemented anyway in those functional programming languages. The lambda functions you write in those high-level languages are ultimately translated into similar code and (usually) executed dynamically on the stack. A lot of these high-level languages compile down to C too (or C--).
The idea of executing machine code directly on the stack should be familiar to those who know how buffer overflow exploits work. So first, we create a reasonably sized buffer on the stack (in main()) to hold the code:
Then, we declare some functions above main():
Right. Now comes the power of the C programming language. The reason why I padded dummy functions after those declarations is just enhance clarity in this demonstration. They strictly aren't necessary and I could have simply computed the offsets from the next function. But function order must be strictly obeyed because of the way the code subsequently gets laid out in memory.
A function is simply an array of machine instructions. So we just need to compute the size of those two functions:
Now all have left to do is load the function into the stack buffer, by copying memory directly:
Now we can simply execute the code anytime we wish by casting the stack buffer to the appropriate function pointer type and calling it:
We do the same with the second function, then we print the result:
Lo and behold (this is what printf prints):
But we can go further than that. Let's dynamically load in the machine code at runtime. First, we write a function that does subtraction in C, then we disassemble the function:
GDB tells us that the function is 13 bytes in size. So let's directly read off the machine instructions:
Some fun in Ruby turns that into the following string (representing the machine code):
Which we directly load into the buffer...
And execute...
Which returns (the result of 10 - 2):
Another reason why C is my favorite programming language. Source code is located here for the curious.
But, fundamentally, this is how lambda functions are implemented anyway in those functional programming languages. The lambda functions you write in those high-level languages are ultimately translated into similar code and (usually) executed dynamically on the stack. A lot of these high-level languages compile down to C too (or C--).
The idea of executing machine code directly on the stack should be familiar to those who know how buffer overflow exploits work. So first, we create a reasonably sized buffer on the stack (in main()) to hold the code:
char lambda[5000];Then, we declare some functions above main():
/**
* Definition of function #1:
*/
int add( int x, int y )
{
return x + y;
}
void dummyfunc1() {}
// We need to end with a dummy function so we can easily compute the size of
// the function by calculating the differences in addresses.
/**
* Definition of function #2:
*/
int sumsquares( int x, int y )
{
// Just for fun, we make this function bigger:
int part1 = x * x;
int part2 = y * y;
return part1 + part2;
}
void dummyfunc2() {}Right. Now comes the power of the C programming language. The reason why I padded dummy functions after those declarations is just enhance clarity in this demonstration. They strictly aren't necessary and I could have simply computed the offsets from the next function. But function order must be strictly obeyed because of the way the code subsequently gets laid out in memory.
A function is simply an array of machine instructions. So we just need to compute the size of those two functions:
unsigned long function_add_size = (long)dummyfunc1 - (long)add;unsigned long function_sumsquares_size = (long)dummyfunc2 - (long)sumsquares;Now all have left to do is load the function into the stack buffer, by copying memory directly:
memcpy( &lambda, (char*)add, function_add_size );Now we can simply execute the code anytime we wish by casting the stack buffer to the appropriate function pointer type and calling it:
a = ((int (*)(int, int)) lambda)(4, 5);We do the same with the second function, then we print the result:
memcpy( &lambda, (char*)sumsquares, function_sumsquares_size );
b = ((int (*)(int, int)) lambda)(4, 5);Lo and behold (this is what printf prints):
a = 9
b = 41But we can go further than that. Let's dynamically load in the machine code at runtime. First, we write a function that does subtraction in C, then we disassemble the function:
(gdb) disassemble subtract
Dump of assembler code for function subtract:
0x0804845f <subtract+0>: push %ebp
0x08048460 <subtract+1>: mov %esp,%ebp
0x08048462 <subtract+3>: mov 0xc(%ebp),%edx
0x08048465 <subtract+6>: mov 0x8(%ebp),%eax
0x08048468 <subtract+9>: sub %edx,%eax
0x0804846a <subtract+11>: pop %ebp
0x0804846b <subtract+12>: ret
End of assembler dump.GDB tells us that the function is 13 bytes in size. So let's directly read off the machine instructions:
(gdb) x/13xb subtract
0x804845f <subtract>: 0x55 0x89 0xe5 0x8b 0x55 0x0c 0x8b 0x45
0x8048467 <subtract+8>: 0x08 0x29 0xd0 0x5d 0xc3Some fun in Ruby turns that into the following string (representing the machine code):
irb(main):026:0> puts "0x55 0x89 0xe5 0x8b 0x55 0x0c 0x8b 0x45 0x08 0x29 0xd0 0x5d 0xc3".split.map {|code| '\\'+code[1..3]}.join
\x55\x89\xe5\x8b\x55\x0c\x8b\x45\x08\x29\xd0\x5d\xc3Which we directly load into the buffer...
strcpy( lambda, "\x55\x89\xe5\x8b\x55\x0c\x8b\x45\x08\x29\xd0\x5d\xc3" );And execute...
c = ((int (*)(int, int)) lambda)(10, 2);Which returns (the result of 10 - 2):
c = 8Another reason why C is my favorite programming language. Source code is located here for the curious.
Thursday, May 28, 2009
C Programming Win
I found this opening tidbit from one of the old Operating Systems class assignments (CSE 451):
Despite incredible advances in programming languages over the last 30 years, most serious systems programming is still done in C.Win.
Why is this? Because C gives the programmer more control and power over the code's execution than do other, higher-level languages like Java or even C++. Also, C typically has less runtime overhead than higher-level languages, which can translate into increased performance. Suppose you have a function that takes an integer and returns a double. In a strongly typed language, all you can do with this function is call it while passing an integer and treat the result as a double. Of course, you can do this in C. But you can also call it with no parameters, call it with 5 parameters, take the result and store it in an integer. Even better, you could treat the function as an array and read each instruction as an integer if you like. Or, you could call not the first instruction in the function, but maybe the second, or the third, or ... there is a reason why C is sometimes referred to as a "high-level assembly language".
Subscribe to:
Posts (Atom)



