Thursday, September 30, 2010

Peerritation

Peerritation [peer-i-tay-shun] (noun) : Unreasonable hostility felt toward the subject of the last peer review left to be written.
"I'd be done if it weren't for that guy!"

Wednesday, September 29, 2010

Twitter URL Search No Worky?

Twitter logoSomething is wonky with twitter's search function. In May 2010 twitter search started returning results for keywords in the original, unshortened links passing through the service. Were http://example.com/booga to be shortened and tweeted, searches for "example" and "booga" would turn up the tweet.

At some point in late September 2010 this seems to have changed. Now the original URL is generally not matched, with the possible exceptions of Top Tweets, Promoted Tweets, and Twitter's own t.co shortener. The change seems to have ramped in slowly, as even three days ago I was seeing some shortened URLs turn up in search results, while others did not. There were also a couple examples of the host portion like example.com not being indexed, but the rest of the URL triggering search results. I thought it was a glitch, but as of 9/28 it seems consistent: URLs behind third party shorteners are not being indexed.

Its possible this is just a glitch due to traffic growth. It could be a normal adjustment to the Twitter service, attempting to tweak search results for better relevance. It could be a rather bold incentive to use Twitter's URL shortener. However I cannot help but notice that it also makes room for features relating to brand management. Searching for something specific might use the regular search service, while monitoring for all links pointing to a site could be a service from a different, premium system.

Update: Apparently its just me. Tweets sent from @dgentry containing shortened links do not appear in search results for keywords in the original URL, starting late September. For example, the following tweets did not appear in search results for codingrelic or geekhold: 1 2 3 4 5 6 7 8. I also noticed thiat this tweet did not appear in a search for "ifixit." I suspect that this affects any tweet I've sent since mid-September, but I didn't start checking all of them until I realized there was a problem.

Monday, September 27, 2010

Peerrihelion

Peerrihelion [peer-rê-heel-yên] (noun) : The point at which 50% of requested peer reviews are complete.

Wednesday, September 22, 2010

GCC Function Instrumentation

One of gcc's more obscure features is -finstrument-functions. It was implemented by Cygnus Solutions, presumably as part of a contract for sombody-or-other to deliver something-or-other. When enabled, the compiler will emit calls to __cyg_profile_func_enter() and __cyg_profile_func_exit() at the top and bottom of every function.

Let's examine a simple example which prints the function addresses at entry and exit.

#include <stdio.h>

void __cyg_profile_func_enter(void *this_fn, void *call_site)
                              __attribute__((no_instrument_function));
void __cyg_profile_func_enter(void *this_fn, void *call_site) {
  printf("ENTER: %p, from %p\n", this_fn, call_site);
} /* __cyg_profile_func_enter */

void __cyg_profile_func_exit(void *this_fn, void *call_site)
                             __attribute__((no_instrument_function));
void __cyg_profile_func_exit(void *this_fn, void *call_site) {
  printf("EXIT:  %p, from %p\n", this_fn, call_site);
} /* __cyg_profile_func_enter */

int foo() {
  return 2;
}

int bar() {
  return 1;
}

int main(int argc, char** argv) {
  printf("foo=%d bar=%d\n", foo(), bar());
}

The __cyg_profile_func_enter and exit functions are passed two parameters: the address of the function being entered/exited, and the address from which it was called. Note the use of the no_instrument_function attribute. If not present, then __cyg_profile_func_enter would be instrumented like any other function. Every call would result in calling the instrumentation again, which results in another call, etc etc until it blows the stack. Previously I've used -finstrument-functions to construct a profiler for a CPU whose interrupt structure was not suitable for a sample-based profiler. All of the routines implementing the profiler were labelled no_instrument_function.

Next we'll examine the output, with just enough of the disassembled binary to make sense of it.

$ cc t.c -finstrument-functions
$ ./a.out
ENTER: 0x4005d0 @ 0x2b59e0d471c4 (calling main)
ENTER: 0x40059d @ 0x40060c       (calling foo)
EXIT:  0x40059d @ 0x40060c       (returning from foo)
ENTER: 0x40056a @ 0x400618       (calling bar)
EXIT:  0x40056a @ 0x400618       (returning from bar)
foo=2 bar=1
EXIT:  0x4005d0 @ 0x2b59e0d471c4 (returning from main)

000000000040056a <foo>:
  40056a: push   %rbp
  ...

000000000040059d <bar>:
  40059d: push   %rbp
  ...

00000000004005d0 <main>:
  4005d0: push   %rbp
  ...
  400607: callq  40059d <bar>
  40060c: mov    %eax,%ebx
  ...
  400613: callq  40056a <foo>
  400618: mov    %eax,%esi
  ...

There are a few interesting things to note in the output.

  1. Though main calls printf, we don't see a call to printf in the output. Function instrumentation is implemented during compilation, and we didn't compile printf we linked to an existing library. We'll only see the instrumentation for functions compiled with -finstrument-functions.
  2. The call_site is the instruction after the one which vectors over to run the function.
  3. The call_site which called main() looks strange. It is not in the TEXT segment, it is way up at some weird address. This is address space layout randomization in action, every run of this binary has a different address calling main. I don't know exactly what that routine is, but presumably it is part of the trampoline when the kernel begins executing a new process.

This instrumentation facility is not often used. The aforementioned call graph profiler is the only time I've used it. Nonetheless I hope you find it interesting.


Update 7/2011: In the comments Frank Denis notes that on OSX the functions are profile_func_enter() and profile_func_exit().

Thursday, September 16, 2010

Code Snippet: D_NOTIFY and inotify

D_NOTIFY is a facility in the Linux 2.4 kernel to monitor a directory for changes. It will send the monitoring application a signal when files in the directory are added, removed, or modified. It will be triggered if a new subdirectory is added, but does not trigger when files in that subdirectory are modified. D_NOTIFY sends a signal as notification. By default it will send SIGIO, though this can be changed.

In Linux 2.6 the far superior inotify interface was added. Where dnotify sends signals, inotify uses a file descriptor suitable for adding to select() or poll(). If your application will always run on 2.6, you should use inotify. If you need to support older kernels, dnotify still works in 2.6.

Code snippets using D_NOTIFY and inotify are provided below. Both examples monitor the current working directory for addition, removal, or modification of files.


D_NOTIFY

Suitable for 2.4 and 2.6 kernels.

#include <stdio.h>
#define __USE_GNU
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>

volatile sig_atomic_t modified = 0;

static void handler(int signum, siginfo_t* si, void* data) {
  modified = 1;
}

#define MYSIG (SIGRTMIN+3)

int main(int argc, char** argv) {
  struct sigaction act;
  int fd;

  act.sa_sigaction = handler;
  sigemptyset(&act.sa_mask);
  act.sa_flags = SA_SIGINFO;
  sigaction(MYSIG, &act, NULL);

  fd = open(".", O_RDONLY);
  /* The default signal is SIGIO, but we use MYSIG instead */
  fcntl(fd, F_SETSIG, MYSIG);
  fcntl(fd, F_NOTIFY, DN_MODIFY | DN_CREATE | DN_DELETE | DN_MULTISHOT);

  while (1) {
    pause();

    if (modified) {
      printf("Directory modified!\n");
      modified = 0;
    }
  }
}

inotify

Suitable for 2.6 kernels, with a much nicer (non-signals based) API.

#include <stdio.h>
#include <stdlib.h>
#include <sys/inotify.h>

int main(int argc, char** argv) {
  int fd, watchdir, rlen;
  /* there is a variable length filename in the inotify_event, need to leave room for it. */
  char buf[sizeof(struct inotify_event) + 256];

  if ((fd = inotify_init()) < 0) {
    perror("inotify_init failed");
    exit(1);
  }

  if ((watchdir = inotify_add_watch (fd, ".",
                   IN_MODIFY | IN_CREATE | IN_DELETE)) < 0) {
    perror("inotify_add_watch failed");
    exit(2);
  }

  while ((rlen = read(fd, buf, sizeof(buf))) > 0) {
    struct inotify_event* event = (struct inotify_event*) buf;
    /* can examine event-> mask to determine what happened */
    printf("Directory modified!\n");
  }
}

Monday, September 13, 2010

Lucky Numbers

I think this drive would be even luckier if it were 888.8 GB.


Frys Ad for 808.8GB drive, $58

Thursday, September 9, 2010

Early Morning Computing

I get up very early in the morning, typically around 4am. The house is pitch black, so when I open my computer it vaporizes the top layer of my cornea. Even at its lowest setting the laptop screen is uncomfortably bright, but I learned something new yesterday which will save my eyeballs. On MacOS X, pressing control+alt+command+8 reverses the video. This is done system wide, at a low level in the video subsystem. No support in applications is required.


Screenshot with reversed video
(simulated screenshot)

The overall effect is much more comfortable in dark environments, albeit somewhat jarring with images. Pressing the key combination again toggles it back. The video also reverts to normal when the laptop is closed, presumably as a failsafe in case it is engaged by accident.

Tuesday, September 7, 2010

Custom Body Parts On Demand

Several weeks ago I cracked a tooth, which had to be capped with a crown. Years ago this would have required the dentist to cut away the broken sections of tooth, and then a mold would be sent off to a manufacturer. The crown would come back several weeks later, while in the meantime I'd have to be very careful of the broken tooth.

That was then, this is now. Now the dentist uses a laser scanner to make a 3D model of the shape of the tooth before and after trimming out the broken section. The difference between the two gives the rough shape of the crown to be made, which the dentist can adjust with CAD software. He described the adjustments as "the tooth the way it was twenty years ago, not the way it is now."


CAD software sculpting dental crown

Now we don't send this CAD model off to be manufactured. The dentist has a CNC milling machine in the office. It starts from a ceramic ingot and cuts away anything which isn't shaped like the desired crown.



We're living in the future, where replacement body parts are sculpted on demand. It makes me feel old that I can remember it wasn't always this way.