blob: 466eee4f0748ce54b8927e9df57e21f835d34919 [file] [edit]
/*
** Performance testing of floating-point decimal-to-binary conversion for
** SQLite versus the standard library.
**
** This module compares library atof() against SQLite's sqlite3AtoF().
** To go the other direction (binary-to-decimal) see fp-speed-1.c.
**
** To compile:
**
** make sqlite3.c
** gcc -Os -c sqlite3.c
** gcc -I. -Os test/fp-speed-2.c sqlite3.o -ldl -lm -lpthread
**
** To run the test:
**
** ./a.out 10000000
**
** Notes:
**
** * A first loop is run to measure the testing overhead. This
** overhead is then subtracted from the times of subsequent loops
** so that the estimates are for the calls to atof() or
** sqlite3AtoF() only.
*/
#include "sqlite3.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#ifdef _WIN32
# include <windows.h>
#else
# include <sys/time.h>
#endif
static const char *aVal[] = {
"-1.01638304862856430",
"+0.00492438073915869",
"+7.38187324073439948",
"+7.06785952192257171",
"+9.28072663198500256",
"+5.88710508619333946",
"-2.29980236212596628",
"-1.59035819249108474",
"+2.43134418168449782",
"-3.82909873289453990",
"+1.87879140627440013",
"+0.72706535604871466",
"+0.06395776979131836",
"+5.22923388793158619",
"+6.37476826728722313",
"+8.69723395383291069",
"-9.50744860515976919",
"-8.64802578453687530",
"-3.56575957757974703",
"-7.83231061797317613",
"+7.78138752741208003",
"-1.87397189283601965",
"+8.68981459155933572",
"+6.05667663598778378",
"+4.17033792171481606",
"+2.12838712887466515",
"-6.83952360838918106",
"-6.21142997639395291",
"-2.07535257426146373",
"+5.87274598039442902",
"+8.58889910620021018",
"+6.86244610313559176",
"-3.30539867566709051",
"-4.35968431527634449",
"+0.08341395201040996",
"-8.85819865489042224",
"-3.66220954287276982",
"-6.69658522970250632",
"+1.82041693474064884",
"+6.52345080386490003",
"+1.59230060182190114",
"+1.73625552916563894",
"+7.28754319768547858",
"+1.28358801059589267",
"+8.05162533203208194",
"+6.63246333993811454",
"-1.71265000702800620",
"+1.69957383415837123",
"+7.60487669237386637",
"+0.61591172354494550",
"+5.75448943554159432",
"+8.29702285926905818",
"-6.55319253601630674",
"+5.83213346061870300",
"+5.65571665095718917",
"+0.33227897084384087",
"-7.12106487766986866",
"-9.67212625267063433",
"-3.45839165713773950",
"+4.78960943232147507",
"-9.69260280400041378",
"+7.06838482753813854",
"-5.29701141821629619",
"-4.42870212009053932",
"+0.07288911557328087",
"-9.18554620258794474",
"+3.72941262341310077",
"+2.68574218827927192",
"-4.70706073336246853",
"+7.21758207682793342",
"-8.36784125342611634",
"+2.21748443042418221",
"+0.19498245886068610",
"-9.73340529556720719",
"-9.77938877669369998",
"-5.15611645874169315",
"-7.50489935777651747",
"+7.35560765686877845",
"-5.06816285755335998",
"+1.52097056420277478",
"-7.59897825350482960",
"+1.36541372033897758",
"-1.64417205546513720",
"-4.90424331961411259",
"-7.70636119616491307",
"+0.16994274609307662",
"+8.33743178495722168",
"-5.23553304804695800",
"-3.85100459421941479",
"-6.35136225443263398",
"+2.38693034844544289",
"+3.83527158716203602",
"-3.12631204931368879",
"-5.57947970025564908",
"-8.81098744795956043",
"-4.37273601202032169",
"-3.11099511896685399",
"-9.48418780317042682",
"-3.73984516683044072",
"+4.89840420089159599",
};
#define NN (sizeof(aVal)/sizeof(aVal[0]))
/* Return the current wall-clock time in microseconds since the
** Unix epoch (1970-01-01T00:00:00Z)
*/
static sqlite3_int64 timeOfDay(void){
#if defined(_WIN64) && _WIN32_WINNT >= _WIN32_WINNT_WIN8
sqlite3_uint64 t;
FILETIME tm;
GetSystemTimePreciseAsFileTime(&tm);
t = ((sqlite3_uint64)tm.dwHighDateTime<<32) |
(sqlite3_uint64)tm.dwLowDateTime;
t += 116444736000000000LL;
t /= 10;
return t;
#elif defined(_WIN32)
static sqlite3_vfs *clockVfs = 0;
sqlite3_int64 t;
if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0);
if( clockVfs==0 ) return 0; /* Never actually happens */
if( clockVfs->iVersion>=2 && clockVfs->xCurrentTimeInt64!=0 ){
clockVfs->xCurrentTimeInt64(clockVfs, &t);
}else{
double r;
clockVfs->xCurrentTime(clockVfs, &r);
t = (sqlite3_int64)(r*86400000.0);
}
return t*1000;
#else
struct timeval sNow;
(void)gettimeofday(&sNow,0);
return ((sqlite3_int64)sNow.tv_sec)*1000000 + sNow.tv_usec;
#endif
}
/*
** Generate text of the i-th test floating-point literal.
*/
static int fpLiteral(int i, char *z){
int e, ex, len, ix;
ex = i%401;
e = ex - 200;
len = (i/401)%16 + 4;
ix = (i/(401*16))%NN;
memcpy(z, aVal[ix], len);
z[len++] = 'e';
if( e<0 ){
z[len++] = '-';
e = -e;
}else{
z[len++] = '+';
}
z[len++] = e/100 + '0';
z[len++] = (e/10)%10 + '0';
z[len++] = e%10 + '0';
z[len] = 0;
return ex;
}
int main(int argc, char **argv){
int i;
int cnt;
sqlite3_int64 tm[3];
double arSum[401];
char z[1000];
if( argc!=2 ){
printf("Usage: %s COUNT\n", argv[0]);
printf("Suggested value for COUNT is 10 million\n");
return 1;
}
cnt = atoi(argv[1]);
if( cnt<100 ){
printf("Minimum COUNT value is 100");
return 1;
}
printf("test-overhead: ");
fflush(stdout);
memset(arSum, 0, sizeof(arSum));
tm[2] = timeOfDay();
for(i=0; i<cnt; i++){
double r = (double)i;
int ex = fpLiteral(i,z);
arSum[ex] += r;
}
tm[2] = timeOfDay() - tm[2];
for(i=1; i<=400; i++) arSum[0] += arSum[i];
printf("%6.1f ns/test, %9.6f sec total\n", tm[2]*1e3/cnt, tm[2]*1e-6);
printf("C-lib atof(): ");
fflush(stdout);
memset(arSum, 0, sizeof(arSum));
tm[0] = timeOfDay();
for(i=0; i<cnt; i++){
int ex = fpLiteral(i,z);
arSum[ex] += atof(z);
}
tm[0] = timeOfDay() - tm[0] - tm[2];
for(i=1; i<=400; i++) arSum[0] += arSum[i];
printf("%6.1f ns/test, %9.6f sec net", tm[0]*1e3/cnt, tm[0]*1e-6);
printf(", cksum: %g\n", arSum[0]);
printf("sqlite3AtoF(): ");
fflush(stdout);
memset(arSum, 0, sizeof(arSum));
tm[1] = timeOfDay();
for(i=0; i<cnt; i++){
double r = 0.0;
int ex = fpLiteral(i,z);
sqlite3_test_control(SQLITE_TESTCTRL_ATOF, z, &r);
arSum[ex] += r;
}
tm[1] = timeOfDay() - tm[1] - tm[2];
for(i=1; i<=400; i++) arSum[0] += arSum[i];
printf("%6.1f ns/test, %9.6f sec net", tm[1]*1e3/cnt, tm[1]*1e-6);
printf(", cksum: %g\n", arSum[0]);
if( tm[0] < tm[1] ){
printf("atof() is about %g times faster than sqlite3AtoF()\n",
(double)tm[1]/(double)tm[0]);
}else{
printf("sqlite3AtoF() is about %g times faster than atof()\n",
(double)tm[0]/(double)tm[1]);
}
return 0;
}