On 04/16/12 09:54, Bruce Korb wrote:
I suppose the motivation is performance?
If so, have you measured the improvement?
Actually, no, it is not for performance. I found it wearisome to write:
But curiosity got the better of me:
$ ./timer
strpbrk startup time: 0.000 run time: 31.081
macros startup time: 0.000 run time: 19.882
#define _GNU_SOURCE 1
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <ctype.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "timer-map.h"
#define START_CT 1000
#define FULL_CT (1000 * 1000 * 1000)
typedef struct {
struct timeval start, middle, end;
} race_times_t;
volatile char extern_ch;
char const * text = NULL;
void
print_timings(race_times_t * pb, race_times_t * mac);
void
use_strpbrk(int ct)
{
while (ct-- > 0) {
char * p = strpbrk(text, "#~");
extern_ch = *p;
}
}
void
use_macros(int ct)
{
while (ct-- > 0) {
char * p = SPN_HASH_CHARS(text);
extern_ch = *p;
}
}
void
map_file(char const * fname)
{
struct stat sb;
int sres = stat(fname, &sb);
int fd = open(fname, O_RDONLY);
void * map = mmap(NULL, sb.st_size+1, PROT_READ, MAP_SHARED, fd, 0);
if ((sres < 0) || (fd < 0) || (map == MAP_FAILED))
exit(1);
text = map;
}
int
main(int argc, char ** argv)
{
race_times_t for_strpbrk;
race_times_t for_macros;
{
char const * fn = argv[1] ? argv[1] : __FILE__;
map_file(fn);
}
gettimeofday(&for_strpbrk.start, NULL);
use_strpbrk(START_CT);
gettimeofday(&for_strpbrk.middle, NULL);
use_strpbrk(FULL_CT);
gettimeofday(&for_strpbrk.end, NULL);
for_macros.start = for_strpbrk.end;
use_macros(START_CT);
gettimeofday(&for_macros.middle, NULL);
use_macros(FULL_CT);
gettimeofday(&for_macros.end, NULL);
print_timings(&for_strpbrk, &for_macros);
return 0;
}
int
delta(struct timeval * s, struct timeval * e)
{
if (s->tv_sec == e->tv_sec)
return (500 + e->tv_usec - s->tv_usec) / 1000;
int msec = (500 + (1000000 - s->tv_usec) + e->tv_usec) / 1000;
return msec + ((e->tv_sec - s->tv_sec) - 1) * 1000;
}
void
fmtnum(char * buf, int msec)
{
int len = sprintf(buf, "%04u", msec);
char * p = buf + len - 3;
memmove(p+1, p, 4);
*p = '.';
}
void
print_timings(race_times_t * pb, race_times_t * mac)
{
static char const fmt[] =
"%-10s startup time: %9s run time: %12s\n";
int delta1 = delta(&pb->start, &pb->middle);
int delta2 = delta(&pb->middle, &pb->end);
char buf1[32], buf2[32];
fmtnum(buf1, delta1);
fmtnum(buf2, delta2);
printf(fmt, "strpbrk", buf1, buf2);
delta1 = delta(&mac->start, &mac->middle);
delta2 = delta(&mac->middle, &mac->end);
fmtnum(buf1, delta1);
fmtnum(buf2, delta2);
printf(fmt, "macros", buf1, buf2);
}
/*
* 1 bit character mapping generated 04/16/12 10:12:44
*
* char-mapper Character Classifications
*/
#ifndef TIMER_MAP_H_GUARD
#define TIMER_MAP_H_GUARD 1
#ifdef HAVE_CONFIG_H
# if defined(HAVE_INTTYPES_H)
# include <inttypes.h>
# elif defined(HAVE_STDINT_H)
# include <stdint.h>
# elif !defined(HAVE_UINT8_T)
typedef unsigned char uint8_t;
# endif /* HAVE_*INT*_H header */
#else /* not HAVE_CONFIG_H -- */
# include <inttypes.h>
#endif /* HAVE_CONFIG_H */
#if 0 /* mapping specification source (from timer-map.map) */
//
// %guard
// %file timer-map.h
// %backup
//
// hash "#~"
//
#endif /* 0 -- mapping spec. source */
typedef uint8_t timer_map_mask_t;
#define IS_HASH_CHAR( _c) is_timer_map_char((char)( _c), 0x01)
#define SPN_HASH_CHARS(_s) spn_timer_map_chars((char *)_s, 0x01)
#define BRK_HASH_CHARS(_s) brk_timer_map_chars((char *)_s, 0x01)
#define SPN_HASH_BACK(s,e) spn_timer_map_back((char *)s, (char *)e, 0x01)
#define BRK_HASH_BACK(s,e) brk_timer_map_back((char *)s, (char *)e, 0x01)
static timer_map_mask_t const timer_map_table[128] = {
/*NUL*/ 0x00, /*x01*/ 0x00, /*x02*/ 0x00, /*x03*/ 0x00,
/*x04*/ 0x00, /*x05*/ 0x00, /*x06*/ 0x00, /*BEL*/ 0x00,
/* BS*/ 0x00, /* HT*/ 0x00, /* NL*/ 0x00, /* VT*/ 0x00,
/* FF*/ 0x00, /* CR*/ 0x00, /*x0E*/ 0x00, /*x0F*/ 0x00,
/*x10*/ 0x00, /*x11*/ 0x00, /*x12*/ 0x00, /*x13*/ 0x00,
/*x14*/ 0x00, /*x15*/ 0x00, /*x16*/ 0x00, /*x17*/ 0x00,
/*x18*/ 0x00, /*x19*/ 0x00, /*x1A*/ 0x00, /*ESC*/ 0x00,
/*x1C*/ 0x00, /*x1D*/ 0x00, /*x1E*/ 0x00, /*x1F*/ 0x00,
/* */ 0x00, /* ! */ 0x00, /* " */ 0x00, /* # */ 0x01,
/* $ */ 0x00, /* % */ 0x00, /* & */ 0x00, /* ' */ 0x00,
/* ( */ 0x00, /* ) */ 0x00, /* * */ 0x00, /* + */ 0x00,
/* , */ 0x00, /* - */ 0x00, /* . */ 0x00, /* / */ 0x00,
/* 0 */ 0x00, /* 1 */ 0x00, /* 2 */ 0x00, /* 3 */ 0x00,
/* 4 */ 0x00, /* 5 */ 0x00, /* 6 */ 0x00, /* 7 */ 0x00,
/* 8 */ 0x00, /* 9 */ 0x00, /* : */ 0x00, /* ; */ 0x00,
/* < */ 0x00, /* = */ 0x00, /* > */ 0x00, /* ? */ 0x00,
/* @ */ 0x00, /* A */ 0x00, /* B */ 0x00, /* C */ 0x00,
/* D */ 0x00, /* E */ 0x00, /* F */ 0x00, /* G */ 0x00,
/* H */ 0x00, /* I */ 0x00, /* J */ 0x00, /* K */ 0x00,
/* L */ 0x00, /* M */ 0x00, /* N */ 0x00, /* O */ 0x00,
/* P */ 0x00, /* Q */ 0x00, /* R */ 0x00, /* S */ 0x00,
/* T */ 0x00, /* U */ 0x00, /* V */ 0x00, /* W */ 0x00,
/* X */ 0x00, /* Y */ 0x00, /* Z */ 0x00, /* [ */ 0x00,
/* \ */ 0x00, /* ] */ 0x00, /* ^ */ 0x00, /* _ */ 0x00,
/* ` */ 0x00, /* a */ 0x00, /* b */ 0x00, /* c */ 0x00,
/* d */ 0x00, /* e */ 0x00, /* f */ 0x00, /* g */ 0x00,
/* h */ 0x00, /* i */ 0x00, /* j */ 0x00, /* k */ 0x00,
/* l */ 0x00, /* m */ 0x00, /* n */ 0x00, /* o */ 0x00,
/* p */ 0x00, /* q */ 0x00, /* r */ 0x00, /* s */ 0x00,
/* t */ 0x00, /* u */ 0x00, /* v */ 0x00, /* w */ 0x00,
/* x */ 0x00, /* y */ 0x00, /* z */ 0x00, /* { */ 0x00,
/* | */ 0x00, /* } */ 0x00, /* ~ */ 0x01, /*x7F*/ 0x00
};
static inline int
is_timer_map_char(char ch, timer_map_mask_t mask)
{
unsigned int ix = (unsigned char)ch;
return ((ix < 128) && ((timer_map_table[ix] & mask) != 0));
}
static inline char *
spn_timer_map_chars(char * p, timer_map_mask_t mask)
{
while ((*p != '\0') && is_timer_map_char(*p, mask)) p++;
return p;
}
static inline char *
brk_timer_map_chars(char * p, timer_map_mask_t mask)
{
while ((*p != '\0') && (! is_timer_map_char(*p, mask))) p++;
return p;
}
static inline char *
spn_timer_map_back(char * s, char * e, timer_map_mask_t mask)
{
if (s == e) e += strlen(e);
while ((e > s) && is_timer_map_char(e[-1], mask)) e--;
return e;
}
static inline char *
brk_timer_map_back(char * s, char * e, timer_map_mask_t mask)
{
if (s == e) e += strlen(e);
while ((e > s) && (! is_timer_map_char(e[-1], mask))) e--;
return e;
}
#endif /* TIMER_MAP_H_GUARD */