SOLVED!!

Marcus Grimm and I went back forth a number of times trying to figure out why 
my benchmarks were so much faster than his.

Found it...

My SATA RAID setup had "Enable Advanced Performance" on by default (I had never 
turned it on).
My secondary tests on an IDE drive showed similar performance to Marcus.  Then 
I turned on the performance mode for that one and got a 10X performance 
improvement (advanced write caching...power loss susceptible...UPS needed if 
you want reliability).   The "Enable write caching" was already turned on.

To check your setup
My Computer/Properties on drive/Hardware/Properties on drive/Policies -- and 
check "Enable advanced performance".  

Here's the program we're benching with now.  Now compilable on Unix, Windows 
with VS 2008/2010/tdm-gcc 4.5.1.

Some results on a Western Digital 7200RPM IDE drive with advanced performance 
turned on
F:\>d:batch 1000 1 0
Sqlite Version: 3.7.5
Inserting 1000 rows using a bulk of 1
commits per second: 166.7
F:\>d:batch 1000 1 4
using wal mode
Sqlite Version: 3.7.5
Inserting 1000 rows using a bulk of 1
commits per second: 1000.0
F:\>d:batch 500000 1000 0
Sqlite Version: 3.7.5
Inserting 500000 rows using a bulk of 1000
commits per second: 71428.6
F:\>d:batch 500000 1000 4
using wal mode
Sqlite Version: 3.7.5
Inserting 500000 rows using a bulk of 1000
commits per second: 166666.7
F:\>d:batch 500000 1000 5  << note that in-memory is less than 2X disk-based 
now.
using mode: :memory:
using wal mode
Sqlite Version: 3.7.5
Inserting 500000 rows using a bulk of 1000
commits per second: 250000.0

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef _WIN32
#include <windows.h>
#include <winbase.h>
#include <sys/timeb.h>
#else
#include <sys/time.h>
#endif
#include <time.h>
#include "sqlite3.h"
double elapsed()
{
#ifdef _WIN32
        struct _timeb timebuffer;
        _ftime( &timebuffer );
        return( (double)timebuffer.time + timebuffer.millitm / 1000.0);
#else
        double t1;
     struct timeval tv;
     static long base_seconds;
     gettimeofday(&tv,NULL);
     if (base_seconds==0) base_seconds=tv.tv_sec;
     return (tv.tv_sec-base_seconds)+tv.tv_usec/(double)1000000;
#endif
}
int AddTrigger(sqlite3 *db)
{
    char SqlTxt[256];
    int             rc;
    strcpy(SqlTxt,"CREATE TRIGGER XX AFTER INSERT ON t FOR EACH ROW BEGIN ");
    strcat(SqlTxt,"UPDATE t2 SET n = NEW.i+1;");
    strcat(SqlTxt,"END;");
    rc = sqlite3_exec(db,SqlTxt,NULL,NULL,NULL);
    if (rc != SQLITE_OK) {
     puts(sqlite3_errmsg(db));
    }
    return(0);
}
int main(int argc, char *argv[])
{
  sqlite3 *db;
  sqlite3_stmt *stmt=NULL;
  int rc;
  int n=0;
  int nrec=0;
  int interval=0;
  int flags=0;
  double t1;
  char   SqlTxt[256];
  if (argc != 4) {
   fprintf(stderr,"Usage: %s nrecords commit_interval flags\n",argv[0]);
   fprintf(stderr,"Flag 0 = simple table\n");
   fprintf(stderr,"Flag 1 = in-memory database\n");
   fprintf(stderr,"Flag 2 = add index\n");
   fprintf(stderr,"Flag 4 = WAL mode\n");
   fprintf(stderr,"Flag 8 = Add an update trigger per insert\n");
   fprintf(stderr,"Flag 16= Add a manual update per insert\n");
   fprintf(stderr,"Flag 32 = Synchronous=Off\n");
   fprintf(stderr,"Add flags to combine features\n");
   exit(-1);
  }
  nrec=atoi(argv[1]);
  interval=atoi(argv[2]);
  flags=atoi(argv[3]);
  if (flags & 1)
  {
   puts("using mode: :memory:");
   rc=sqlite3_open(":memory:",&db);
  }
  else {
   remove("batch.db");
   rc=sqlite3_open("batch.db",&db);
  }
  if (rc != SQLITE_OK) {
   puts(sqlite3_errmsg(db));
  }
  rc=sqlite3_exec(db,"create table t (i integer)",NULL,NULL,NULL);
  if (rc != SQLITE_OK) {
         puts(sqlite3_errmsg(db));
  }
  rc=sqlite3_exec(db,"create table t2 (n integer)",NULL,NULL,NULL);
  if (rc != SQLITE_OK) {
     puts(sqlite3_errmsg(db));
  }
  rc=sqlite3_exec(db,"insert into t2 values(0)",NULL,NULL,NULL);
  if (rc != SQLITE_OK) {
    puts(sqlite3_errmsg(db));
  }
  if (flags & 32) {
   rc=sqlite3_exec(db,"pragma synchronous=OFF",NULL,NULL,NULL);
   if (rc != SQLITE_OK) {
       puts(sqlite3_errmsg(db));
   }
   puts("using pragma synchronous=OFF");
  }
  if (flags & 2) {
   rc=sqlite3_exec(db,"create index tx on t (i)",NULL,NULL,NULL);
   if (rc != SQLITE_OK) {
      puts(sqlite3_errmsg(db));
   }
    puts("using index on t(i)");
  }
  if (flags & 4) {
   rc=sqlite3_exec(db,"pragma journal_mode=WAL",NULL,NULL,NULL);
   if (rc != SQLITE_OK) {
     puts(sqlite3_errmsg(db));
   }
   puts("using wal mode");
  }
  if (flags & 8) {
   AddTrigger(db);
   puts("using update trigger");
/**  if (interval != 1) {
    fprintf(stderr,"Can't do trigger and begin/commit together\n");
    exit(-1);
   }
**/
  }
  if( flags & 16 )
     puts("using manual update after insert");
  printf("Sqlite Version: %s\n", sqlite3_version);
  printf("Inserting %d rows using a bulk of %d\n", nrec, interval);
  sqlite3_prepare_v2(db,"insert into t values(?)",-1,&stmt,NULL);
  t1=elapsed();
  if (interval != 1) rc=sqlite3_exec(db,"begin",NULL,NULL,NULL);
  while(n < nrec)
  {
   ++n;
   if (interval != 1 && (n% interval)==0) {
    sqlite3_exec(db,"commit",NULL,NULL,NULL);
    sqlite3_exec(db,"begin",NULL,NULL,NULL);
   }
   sqlite3_bind_int(stmt,1,n);
   rc = sqlite3_step(stmt);
   if (rc != SQLITE_DONE) {
    puts(sqlite3_errmsg(db));
   }
   sqlite3_reset(stmt);
   if( flags & 16 )
   {
     sprintf(SqlTxt, "UPDATE t2 SET n = %d;", n+1);
     sqlite3_exec(db, SqlTxt,NULL,NULL,NULL);
   }
  }
  if (interval != 1)
         sqlite3_exec(db,"commit",NULL,NULL,NULL);
  printf("commits per second: %.1f\n",nrec/(elapsed()-t1));
  sqlite3_close(db);
}




Michael D. Black
Senior Scientist
NG Information Systems
Advanced Analytics Directorate
_______________________________________________
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to