// ============================================================================ // This is a Servlet sample for the G-WAN Web Server (http://www.trustleap.com) // ---------------------------------------------------------------------------- // bench.c: How much time should it take to format a RFC-1123 HTTP date string // like "Tue, 06 Jan 2009 06:12:20 GMT"? // // We were wondering how G-WAN C servlets are doing in comparison to the system // Wininet InternetTimeFromSystemTime() Windows API call. Tip: much faster. // // ============================================================================ #include #include "gwan.h" // exported G-WAN functions // Title of our HTML page static u8 title[]="Benchmarking function calls (with CPU clock cycles)"; // Top of our HTML page static u8 top[]= "" "%s" // "" "" "

%s

"; // ---------------------------------------------------------------------------- // imported functions: // get_reply(): get a pointer on the 'reply' dynamic buffer from the server // set_reply(): send back the 'reply' dynamic buffer's pointer to the server // time2rfc(): like httpdate(), but faster and thread-safe // cycles64(): return the number of elapsed CPU clock cycles (64-bit) // xbuf_cat(): like strcat(), but in the specified dynamic buffer // xbuf_xcat(): formatted strcat() (a la printf) in a given dynamic buffer // ---------------------------------------------------------------------------- int main(int argc, char *argv[]) { u8 date[32], *p; __int64 start, overh; u32 i, rounds=10, ms_min=0xffffffff, ms_ave=0, ms_max=0, sv_min=0xffffffff, sv_max=0, sv_ave=0, t=time(0), z=1; // create a dynamic buffer and get a pointer on the server response buffer xbuf_ctx reply; get_reply(argv, &reply); memset(date, 0, sizeof(date)-1); // ---- format the top of our HTML page with a title xbuf_xcat(&reply, top, title, title); // ---- find the CPU clock cycles count overhead so we can remove it later i=rounds; while(i--) start=cycles64(), overh=cycles64()-(start+z), overh--; // ------------------------------------------------------------------------- // benchmark the "Wininet API" function call // ------------------------------------------------------------------------- do{ char *p; SYSTEMTIME st; typedef u32(WINAPI *pHTTPTIME)(const SYSTEMTIME *pst, u32 dwRFC, char *lpszTime, u32 cbTime); pHTTPTIME pHttpTime=0; HMODULE hlib=LoadLibrary("wininet.dll"); pHttpTime=(pHTTPTIME)GetProcAddress(hlib, "InternetTimeFromSystemTime"); if(!pHttpTime) { xbuf_cat(&reply, "Can't load InternetTimeFromSystemTime
"); break; } // check that all function calls provide similar results GetSystemTime(&st); // GetSystemTime(&st); is *much* slower than time(0); pHttpTime(&st, 0, date, sizeof(date)); xbuf_xcat(&reply, "
WinInet API call: %s
", date); xbuf_cat(&reply, "
" ""); // warm the cpu cache to get consistent values i=rounds*2; while(i--) start=cycles64(), p=pHttpTime(&st, 0, date, sizeof(date)); i=rounds; // now time it while(i--) { start=cycles64(); pHttpTime(&st, 0, date, sizeof(date)); start=cycles64()-(start+overh); if(ms_min>start) ms_min=start; if(ms_max", !(i&1), start); } ms_ave/=rounds; xbuf_cat(&reply, "
functiontime
WinInet API call%u
"); FreeLibrary(hlib); }while(0); // ------------------------------------------------------------------------- // benchmark the "time2rfc(t, date);" function call // ------------------------------------------------------------------------- // check that all function calls provide similar results xbuf_xcat(&reply, "
C servlet time2rfc(): %s
", time2rfc(t, date)); xbuf_cat(&reply, "
" ""); // warm the cpu cache to get consistent values i=rounds*2; while(i--) start=cycles64(), p=time2rfc(t, date); // 32-bit time stamp counter overflow period on a 1GHz CPU: // 2^32 cycles * (1 second/1,000,000,000 cycles) = 4.29 seconds i=rounds; while(i--) { start=cycles64(); time2rfc(t, date); start=cycles64()-(start+overh); if(sv_min>start) sv_min=start; if(sv_max", !(i&1), start); } sv_ave/=rounds; xbuf_cat(&reply, "
functiontime
time2rfc()%u
"); // ---- write how many CPU cycles these operations took xbuf_xcat(&reply, "
" "" "" "" "
functionmaxaveragemin
WinInet API call%u%u%u
time2rfc()%u%u%u
" "
TrustLeap's code scaled %.02f times " "better
", ms_max, ms_ave, ms_min, sv_max, sv_ave, sv_min, (double)ms_ave/(double)sv_ave); // ---- close our HTML page xbuf_cat(&reply, "
"); // confirm the reply's dynamic buffer address and size to the server // (they have changed when more memory is allocated during formatting) set_reply(argv, &reply); return(200); // return an HTTP code (200:'OK') } // ============================================================================ // End of Source Code // ============================================================================