2014年6月9日月曜日

zlib 利用サンプル

メモばっかり。C++もいい加減疲れるね。
#include <stdlib.h>
#include <zlib.h>

#define INITIAL_BUF_SIZE (256)
#define INCREMENTAL_BUF_SIZE (256)

class AbstractZlib {
public:
    AbstractZlib(int initial_size = INITIAL_BUF_SIZE, int incremental_size = INCREMENTAL_BUF_SIZE)
        : initial_size_(initial_size), incremental_size_(incremental_size) {}
    virtual int Do(void* in_data, int in_size, void** out_data, int* out_size) = 0;
protected:
    virtual int Init(z_stream* z) = 0;
    virtual int DoFunc(z_stream* z, int type) = 0;
    virtual int DoEnd(z_stream* z) = 0;

    int DoImpl(void* in_data, int in_size, void** out_data, int* out_size) {
        z_stream z = {0};
        z.zalloc = Z_NULL;
        z.zfree = Z_NULL;
        z.opaque = Z_NULL;

        int z_ret = 0;
        *out_data = NULL;
        *out_size = 0;

        if((z_ret = Init(&z)) != Z_OK) {
            return z_ret;
        }

        int osize = initial_size_;
        void* odata = malloc(osize);
        if(odata == NULL) {
            return -1;
        }

        z.next_in = static_cast<Bytef*>(in_data);
        z.avail_in = in_size;
        z.next_out = static_cast<Bytef*>(odata);
        z.avail_out = osize;

        do {
            z_ret = DoFunc(&z, Z_FINISH);
            if(z_ret == Z_STREAM_END) {
                osize = osize - z.avail_out;
                break;
            } else if(z_ret == Z_BUF_ERROR || z_ret == Z_OK) {
                odata = realloc(odata, osize + incremental_size_);
                z.next_out = static_cast<Bytef*>((unsigned char*)odata + osize);
                z.avail_out = incremental_size_;
                osize += incremental_size_;
            } else {
                break;
            }
        } while(z_ret != Z_STREAM_END);

        if(z_ret == Z_STREAM_END) {
            DoEnd(&z);
        }

        if(z_ret == Z_STREAM_END) {
            *out_data = realloc(odata, osize);
            *out_size = osize;
            return Z_OK;
        } else {
            //失敗
            free(odata);
            return z_ret;
        }
    }

private:
    int initial_size_;
    int incremental_size_;
};
class Deflater : public AbstractZlib {
    typedef AbstractZlib super;
public:
    Deflater(int initial_size = INITIAL_BUF_SIZE) : super(initial_size) {}

    virtual int Do(void* in_data, int in_size, void** out_data, int* out_size) {
        return DoImpl(in_data, in_size, out_data, out_size);
    }
protected:
    virtual int Init(z_stream* z) {
        return deflateInit(z, Z_DEFAULT_COMPRESSION);
    }
    virtual int DoFunc(z_stream* z, int type) {
        return deflate(z, type);
    }
    virtual int DoEnd(z_stream* z) {
        return deflateEnd(z);
    }
};
class Inflater : public AbstractZlib {
    typedef AbstractZlib super;
public:
    Inflater(int initial_size = INITIAL_BUF_SIZE) : super(initial_size) {}

    virtual int Do(void* in_data, int in_size, void** out_data, int* out_size) {
        return DoImpl(in_data, in_size, out_data, out_size);
    }
protected:
    virtual int Init(z_stream* z) {
        return inflateInit(z);
    }
    virtual int DoFunc(z_stream* z, int type) {
        return inflate(z, type);
    }
    virtual int DoEnd(z_stream* z) {
        return inflateEnd(z);
    }
};

#include <stdio.h>
#include <iostream>
#include "compress.h"

int main(int argc, char** argv) {
    const char in_buf[] = "aaaabbbbccccaaaabbbbccccaaaabbbbccccaaaabbbbccccaaaabbbbccccaaaabbbbcccc";

    Deflater deflater;
    void* def_odata;
    int def_osize;
    int ret = deflater.Do((void*)in_buf, sizeof(in_buf) / sizeof(in_buf[0]), &def_odata, &def_osize);
    if(ret == 0) {
        std::cout << "ret: " << ret << std::endl;
        std::cout << "osize: " << def_osize << std::endl;
        
        for(int i = 0; i < def_osize; i++) {
            if((i % 16) == 15)
                printf("%02X\n", (int)*((unsigned char*)def_odata + i));
            else
                printf("%02X ", (int)*((unsigned char*)def_odata + i));
        }
        std::cout << std::endl;
    } else {
        std::cerr << "ret: " << ret << std::endl;
    }

    Inflater inflater;
    void* inf_odata;
    int inf_osize;
    ret = inflater.Do(def_odata, def_osize, &inf_odata, &inf_osize);
    if(ret == 0) {
        std::cout << "ret: " << ret << std::endl;
        std::cout << "osize: " << inf_osize << std::endl;
        std::cout << "inflate result:" << static_cast<char*>(inf_odata) << std::endl;

    } else {
        std::cerr << "ret: " << ret << std::endl;
    }
}

2014年5月27日火曜日

HHKB Professional JP Type-S

自宅キーボードを HHKB Professional JP Type-S に変えた。
かなり気持ち良く打てるね。うるさくないし、いい感じの押下感。

感覚的にはコトコト/スコスコといった感じの押下感といったところ。擬音だけみると変だけど結構いい感じに打てる。
いろんなキーがFnを併用する事になるのが嫌な人は向かないだろうけど、ホームポジションからあまり動かなくてもよいという利点がいい人はLite2も良いけど、Type-Sの方が打鍵感は良いので買ってみると良い。
US配列にしなかったのは、日常生活に支障が出るから。
ちなみにこの文章はType-Sを使用してMacBookAirで打ってるけど、Mac利用もいい感じに使える。

2014年5月20日火曜日

stlでのallocator

とりあえずメモ。
#include <cstdlib>
#include <memory>
#include <vector>
#include <map>
#include <iostream>

class IMemAllocator {
public:
    virtual ~IMemAllocator() {}
    virtual void* malloc(int size) = 0;
    virtual void free(void* mem) = 0;
};


class CustomAllocator : public IMemAllocator {
public:
    virtual ~CustomAllocator() {}
    virtual void* malloc(int size) {
        std::cout << "malloc start. size:" << size << std::endl;
        return std::malloc(size);
    }
    virtual void free(void* mem) {
        std::cout << "free start. mem:" << mem << std::endl;
        std::free(mem);
    }
};

template <class T>
class StlAllocator : public std::allocator<T> {
public:
    typedef T* pointer;
    typedef const T* const_pointer;
    typedef size_t size_type;

    StlAllocator(IMemAllocator* allocator) : allocator_(allocator) {}
    StlAllocator(const StlAllocator& x) : allocator_(x.allocator()) {}
    template<class U> StlAllocator(const StlAllocator<U>& x) : allocator_(x.allocator()) {}

    pointer allocate(size_type n, const_pointer hint = 0) {
        std::cout << "allocate " << n * sizeof(T) << std::endl;
        //return (pointer)std::malloc(n * sizeof(T));
        return (pointer)allocator_->malloc(n * sizeof(T));
    }
    void deallocate(pointer ptr, size_type n) {
        std::cout << "free pointer" << (void*)ptr << std::endl;
        //std::free(ptr);
        allocator_->free(ptr);
    }

    template<class U> struct rebind { typedef StlAllocator<U> other; };

    IMemAllocator* allocator() const {
        return allocator_;
    }
private:
    mutable IMemAllocator* allocator_;
};

int main(int argc, char** argv) {
    CustomAllocator custom_allocator;
    StlAllocator<int> stl_allocator(&custom_allocator);

    {
        std::vector<int, StlAllocator<int> > v(stl_allocator);
        v.push_back(1);
        std::cout << v.front() << std::endl;
        v.erase(v.begin());
    }

    StlAllocator<std::pair<int, int> > map_allocator(&custom_allocator);
    {
        std::map<int, int, std::less<int>, StlAllocator<std::pair<int, int> > > m(std::less<int>(), map_allocator);
        m[1] = 1;
        m.clear();
    }
}
$ valgrind ./a.out
==31143== Memcheck, a memory error detector
==31143== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==31143== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==31143== Command: ./a.out
==31143==
allocate 4
malloc start. size:4
1
free pointer0x5a1d040
free start. mem:0x5a1d040
allocate 40
malloc start. size:40
free pointer0x5a1d090
free start. mem:0x5a1d090
==31143==
==31143== HEAP SUMMARY:
==31143== in use at exit: 0 bytes in 0 blocks
==31143== total heap usage: 2 allocs, 2 frees, 44 bytes allocated
==31143==
==31143== All heap blocks were freed -- no leaks are possible
==31143==
==31143== For counts of detected and suppressed errors, rerun with: -v
==31143== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

2014年5月19日月曜日

sqlite3 memory allocator のカスタマイズ

sqlite3はメモリ管理を置き換えることができるので試してみる。
定義する必要がある関数は以下の通り
http://www.sqlite.org/c3ref/mem_methods.html

メモリ確保/開放処理を定義して以下のように置き換えてみた。とりあえずmalloc/freeを使うだけなので効率はよろしくない。xReallocはmalloc,memcpy,freeで実装した。(reallocを使っても当然良いけど、)

やってみて気づいたことは、xSize関数として確保したメモリサイズを返す関数を作る必要があることと、この関数は0x0で呼び出される事が結構あるので、NULLチェックを行う必要があること。
確保したメモリサイズは4バイト分余計に確保して先頭に持っておいた。
また、NULLで呼ばれたら、単に0を返しておけば問題ない様だ。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <sqlite3.h>

class IMemAllocator {
public:
    virtual ~IMemAllocator() {}
    virtual void* malloc(int size) = 0;
    virtual void free(void* mem) = 0;
};
class SqliteAllocator {
private:
    static IMemAllocator* allocator_;
public:
    static void set_allocator(IMemAllocator* allocator) {
        allocator_ = allocator;
    }
    static IMemAllocator* allocator() {
        return allocator_;
    }
    static void* malloc(int size) {
        void* mem = allocator_->malloc(size + sizeof(int));
        *(int*)mem = size;
        return (char*)mem + sizeof(int);
    }
    static void free(void* mem) {
        allocator_->free((void*)((char*)mem - sizeof(int)));
    }
    static void* realloc(void* mem, int size) {
        int osize = SqliteAllocator::size(mem);
        void* remem = SqliteAllocator::malloc(size);
        memcpy(remem, mem, osize);
        SqliteAllocator::free(mem);
        return remem;
    }
    static int size(void* mem) {
        if(mem == NULL) {
            return 0;
        }
        return *(int*)((char*)mem - sizeof(int));
    }
    static int roundup(int size) {
        return size;
    }
    static int init(void* appdata) {
        return 0;
    }
    static void shutdown(void* appdata) {
        free(appdata);
    }

    static sqlite3_mem_methods* create_mem_methods() {
        sqlite3_mem_methods* methods = (sqlite3_mem_methods*)malloc(sizeof(sqlite3_mem_methods));
        sqlite3_mem_methods m = {
            .xMalloc = SqliteAllocator::malloc,
            .xFree = SqliteAllocator::free,
            .xRealloc = SqliteAllocator::realloc,
            .xSize = SqliteAllocator::size,
            .xRoundup = SqliteAllocator::roundup,
            .xInit = SqliteAllocator::init,
            .xShutdown = SqliteAllocator::shutdown,
            .pAppData = methods,
        };
        *methods = m;
        return methods;
    }
};
IMemAllocator* SqliteAllocator::allocator_;

int replace_custom_allocator(IMemAllocator* allocator) {
    SqliteAllocator::set_allocator(allocator);
    return sqlite3_config(SQLITE_CONFIG_MALLOC, SqliteAllocator::create_mem_methods());
}

sqlite3_mem_methods default_methods;
void* log_malloc(int size) {
    std::cout << "malloc start. size:" << size << std::endl;
    void* mem = default_methods.xMalloc(size);
    std::cout << "malloc end. mem:" << mem << std::endl;
    return mem;
}
void log_free(void* mem) {
    std::cout << "free start. mem:" << mem << std::endl;
    default_methods.xFree(mem);
    std::cout << "free end." << std::endl;
}
void* log_realloc(void* mem, int size) {
    std::cout << "realloc start. mem:" << mem << ", size:" << size << std::endl;
    mem = default_methods.xRealloc(mem, size);
    std::cout << "realloc end. mem:" << mem << std::endl;
    return mem;
}
int log_size(void* mem) {
    std::cout << "size start. mem:" << mem << std::endl;
    int size = default_methods.xSize(mem);
    std::cout << "size end. size:" << size << std::endl;
    return size;
}
int log_roundup(int size) {
    std::cout << "roundup start size:" << size << std::endl;
    int result = default_methods.xRoundup(size);
    std::cout << "roundup end result:" << result << std::endl;
    return result;
}
int log_init(void* appdata) {
    std::cout << "init start appdata:" << appdata << std::endl;
    int result = default_methods.xInit(appdata);
    std::cout << "init end. result:" << result << std::endl;
    return result;
}
void log_shutdown(void* appdata) {
    std::cout << "shutdonw start appdata:" << appdata << std::endl;
    default_methods.xShutdown(appdata);
    std::cout << "shutdonw end." << std::endl;
}

sqlite3_mem_methods log_memory_methods = {
    .xMalloc = log_malloc,
    .xFree = log_free,
    .xRealloc = log_realloc,
    .xSize = log_size,
    .xRoundup = log_roundup,
    .xInit = log_init,
    .xShutdown = log_shutdown,
};

int set_logged_allocator() {
    int rc = -1;
    std::cout << "sqlite3_config(SQLITE_CONFIG_GETMALLOC, &default_methods) start." << std::endl;
    rc = sqlite3_config(SQLITE_CONFIG_GETMALLOC, &default_methods);
    std::cout << "sqlite3_config(SQLITE_CONFIG_GETMALLOC, &default_methods) end." << rc << std::endl;
    if(rc == SQLITE_OK) {
        log_memory_methods.pAppData = default_methods.pAppData;
        std::cout << "sqlite3_config(SQLITE_CONFIG_MALLOC, &my_memory_methods) start." << std::endl;
        rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &log_memory_methods);
    }
    return rc;
}

int setup_db(const std::string& filename) {
    int rc = -1;
    sqlite3* db = NULL;

    std::remove(filename.c_str());
    rc = sqlite3_open_v2(filename.c_str(), &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0);
    if(rc != SQLITE_OK) {
        std::cout << "open error:" << sqlite3_errmsg(db) << std::endl;
        return 1;
    }
    std::cout << filename << " opened." << std::endl;

    std::string create_sql = "CREATE TABLE foo "
        "(ID INTEGER, column1 INTEGER, column2 INTEGER, column3 INTEGER, column4 INTEGER, "
        "column5 INTEGER, column6 INTEGER, column7 INTEGER, column8 INTEGER, "
        "PRIMARY KEY(ID));";

    rc = sqlite3_exec(db, create_sql.c_str(), NULL, NULL, NULL);
    if(rc != SQLITE_OK) {
        std::cout << "create table error:" << sqlite3_errmsg(db) << std::endl;
        return 1;
    }
    std::cout << "table created." << std::endl;

    rc = sqlite3_exec(db, "BEGIN TRANSACTION IMMEDIATE;", NULL, NULL, NULL);
    if(rc == SQLITE_OK) {
        std::string insert_sql = "INSERT INTO foo VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?);";
        sqlite3_stmt* stmt;
        rc = sqlite3_prepare_v2(db, insert_sql.c_str(),  -1, &stmt, NULL);
        if(rc == SQLITE_OK) {
            for(int i = 0; i < 10000; i++) {
                sqlite3_clear_bindings(stmt);
                for(int column = 1; column <= 9; column++) {
                    rc = sqlite3_bind_int(stmt, column, i);
                    if(rc != SQLITE_OK) {
                        break;
                    }
                }
                if(rc != SQLITE_OK) {
                    break;
                }
                rc = sqlite3_step(stmt);
                if(rc != SQLITE_DONE) {
                    break;
                }
                sqlite3_reset(stmt);
            }
        }
        sqlite3_finalize(stmt);
        rc = sqlite3_exec(db, "COMMIT;", NULL, NULL, NULL);
    }
    sqlite3_close(db);
    if(rc == SQLITE_DONE || rc == SQLITE_OK) {
        return SQLITE_OK;
    } else {
        std::cout << sqlite3_errmsg(db) << std::endl;
    }
    return 1;
}

class CustomAllocator : public IMemAllocator {
public:
    virtual ~CustomAllocator() {}
    virtual void* malloc(int size) {
        return ::malloc(size);
    }
    virtual void free(void* mem) {
        ::free(mem);
    }
};
int main(int argc, char** argv) {
    int rc = -1;
    std::cout << "replace_custom_allocator start." << std::endl;
    CustomAllocator allocator;
    rc = replace_custom_allocator(&allocator);
    if(rc != SQLITE_OK) {
        return -1;
    }
    //log用
    std::cout << "set_logged_allocator start." << std::endl;
    rc = set_logged_allocator();
    if(rc != SQLITE_OK) {
        return -1;
    }
    std::cout << "sqlite3_init start." << std::endl;
    rc = sqlite3_initialize();
    if(rc != SQLITE_OK) {
        return -1;
    }
    std::cout << "setup_db start." << std::endl;
    rc = setup_db("tmp.db");
    if(rc != SQLITE_OK) {
        return -1;
    }
    std::cout << "sqlite3_shutdown start." << std::endl;
    rc = sqlite3_shutdown();
}

2014年5月7日水曜日

sqlite3でのINSERT OR REPLACEでの更新とINSERTでの追加

気になったので、パフォーマンスを比較してみた。
実行環境は Ubuntu14.04,gcc(g++) 4.8.2

1万行のデータを用意した上で、INSERT OR REPLACEですべてのデータを更新する時間と、INSERTでさらに1万行追加する場合の時間を調べた。追加部分はトランザクションは使わずに、1件ごとにコミットを行った場合の実行時間を調べた。

以下のコードを5回実行して見たところ、5回平均で、
INSERT OR REPLACE:10148.904ms
INSERT:10075.39ms
となり、INSERT OR REPLACEが0.73%遅い結果になった。あまり有意な差ではない。

ちなみに、HDDの読書速度を計測したところ read 257.40MB/sec, write 103MB/sec ちょっと昔のSSDらしい数値になった。
$ sudo hdparm -t /dev/sda1

/dev/sda1:
 Timing buffered disk reads: 774 MB in  3.01 seconds = 257.40 MB/sec
$ sudo time dd if=/dev/zero of=/tmp/hdparm_write.tmp ibs=1M obs=1M count=1024
1024+0 レコード入力
1024+0 レコード出力
1073741824 バイト (1.1 GB) コピーされました、 10.3988 秒、 103 MB/秒
0.12user 1.35system 0:10.40elapsed 14%CPU (0avgtext+0avgdata 2968maxresident)k
680inputs+2097152outputs (1major+790minor)pagefaults 0swaps

auto_vacuumはOFF(sqlite3 replace.db "pragma auto_vacuum;"の結果は0)だが、INSERT OR REPLACEの場合はファイルサイズは増えないようだった。

以下、コードと実行結果ログ
#include <time.h>
#include <cstdio>
#include <iostream>
#include <sqlite3.h>

class Stopwatch {
public:
    Stopwatch(std::string msg) : msg_(msg) {
        clock_gettime(CLOCK_MONOTONIC_RAW, &start_);
    }
    virtual ~Stopwatch() {
        timespec end;
        clock_gettime(CLOCK_MONOTONIC_RAW, &end);
        double nano = (double)(end.tv_sec - start_.tv_sec) * 1000 * 1000 * 1000 + (end.tv_nsec - start_.tv_nsec);
        std::cout << msg_ << " took " << nano / 1000 / 1000 << " msec" << std::endl;
    }
private:
    std::string msg_;
    timespec start_;
};

int setup_db(const std::string& filename) {
    int rc = -1;
    sqlite3* db = NULL;

    std::remove(filename.c_str());
    rc = sqlite3_open_v2(filename.c_str(), &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0);
    if(rc != SQLITE_OK) {
        std::cout << "open error:" << sqlite3_errmsg(db) << std::endl;
        return 1;
    }
    std::cout << filename << " opened." << std::endl;

    std::string create_sql = "CREATE TABLE foo "
        "(ID INTEGER, column1 INTEGER, column2 INTEGER, column3 INTEGER, column4 INTEGER, "
        "column5 INTEGER, column6 INTEGER, column7 INTEGER, column8 INTEGER, "
        "PRIMARY KEY(ID));";

    rc = sqlite3_exec(db, create_sql.c_str(), NULL, NULL, NULL);
    if(rc != SQLITE_OK) {
        std::cout << "create table error:" << sqlite3_errmsg(db) << std::endl;
        return 1;
    }
    std::cout << "table created." << std::endl;

    rc = sqlite3_exec(db, "BEGIN TRANSACTION IMMEDIATE;", NULL, NULL, NULL);
    if(rc == SQLITE_OK) {
        std::string insert_sql = "INSERT INTO foo VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?);";
        sqlite3_stmt* stmt;
        rc = sqlite3_prepare_v2(db, insert_sql.c_str(),  -1, &stmt, NULL);
        if(rc == SQLITE_OK) {
            for(int i = 0; i < 10000; i++) {
                sqlite3_clear_bindings(stmt);
                for(int column = 1; column <= 9; column++) {
                    rc = sqlite3_bind_int(stmt, column, i);
                    if(rc != SQLITE_OK) {
                        break;
                    }
                }
                if(rc != SQLITE_OK) {
                    break;
                }
                rc = sqlite3_step(stmt);
                if(rc != SQLITE_DONE) {
                    break;
                }
                sqlite3_reset(stmt);
            }
        }
        rc = sqlite3_exec(db, "COMMIT;", NULL, NULL, NULL);
    }
    if(rc == SQLITE_DONE || rc == SQLITE_OK) {
        return SQLITE_OK;
    } else {
        std::cout << sqlite3_errmsg(db) << std::endl;
    }
    return 1;
}

int main(int argc, char** argv) {
    sqlite3* db = NULL;
    int rc = setup_db("replace.db");
    if(rc == SQLITE_OK) {
        rc = sqlite3_open_v2("replace.db", &db, SQLITE_OPEN_READWRITE, 0);
        Stopwatch stopwatch("INSERT OR REPLACE");
        std::string insert_sql = "INSERT OR REPLACE INTO foo VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?);";
        sqlite3_stmt* stmt;
        rc = sqlite3_prepare_v2(db, insert_sql.c_str(),  -1, &stmt, NULL);
        if(rc == SQLITE_OK) {
            for(int i = 0; i < 10000; i++) {
                sqlite3_clear_bindings(stmt);
                rc = sqlite3_bind_int(stmt, 1, i);
                for(int column = 2; column <= 9 && rc == SQLITE_OK; column++) {
                    rc = sqlite3_bind_int(stmt, column, i + 1);
                }
                if(rc != SQLITE_OK) {
                    break;
                }
                rc = sqlite3_step(stmt);
                if(rc != SQLITE_DONE) {
                    break;
                }
                sqlite3_reset(stmt);
            }
        }
        rc = sqlite3_close(db);
    }
    rc = setup_db("insert.db");
    if(rc == SQLITE_OK) {
        rc = sqlite3_open_v2("insert.db", &db, SQLITE_OPEN_READWRITE, 0);
        Stopwatch stopwatch("INSERT");
        sqlite3_stmt* stmt;
        std::string insert_sql = "INSERT INTO foo VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?);";
        rc = sqlite3_prepare_v2(db, insert_sql.c_str(),  -1, &stmt, NULL);
        if(rc == SQLITE_OK) {
            for(int i = 10000; i < 20000; i++) {
                sqlite3_clear_bindings(stmt);
                rc = sqlite3_bind_int(stmt, 1, i);
                for(int column = 2; column <= 9 && rc == SQLITE_OK; column++) {
                    rc = sqlite3_bind_int(stmt, column, i + 1);
                }
                if(rc != SQLITE_OK) {
                    break;
                }
                rc = sqlite3_step(stmt);
                if(rc != SQLITE_DONE) {
                    break;
                }
                sqlite3_reset(stmt);
            }
        }
        rc = sqlite3_close(db);
    }
}
$ g++ -O3 -std=c++0x sqlite_rep_performance.cc -lsqlite3
$ for i in `seq 1 1 5`; do ./a.out; done
replace.db opened.
table created.
INSERT OR REPLACE took 10127 msec
insert.db opened.
table created.
INSERT took 9759.16 msec
replace.db opened.
table created.
INSERT OR REPLACE took 9718.24 msec
insert.db opened.
table created.
INSERT took 9924.77 msec
replace.db opened.
table created.
INSERT OR REPLACE took 10552.1 msec
insert.db opened.
table created.
INSERT took 9813.62 msec
replace.db opened.
table created.
INSERT OR REPLACE took 9872.28 msec
insert.db opened.
table created.
INSERT took 10426.2 msec
replace.db opened.
table created.
INSERT OR REPLACE took 10474.9 msec
insert.db opened.
table created.
INSERT took 10453.2 msec

2014年4月21日月曜日

Ubuntuインストール後、画面がまともに表示されないとき

とりあえず、Ubuntu14.04をインストール。以前使用していた13.10はきれいに消してインストールした。
ただ、今Ubuntu用に使用しているメインマシンは結構前に組んだ自作PCで、オンボードのビデオカード(Nvidia)ではまともに表示がされない。
いやされるのはされるけど、ちょっと触るとすぐ画面が崩れたり、ハングしたりする。
ということで個人用のメモ

ctrl+alt+F1でコンソールに入る。
$ sudo apt-get install nvidia-settings nvidia-current

これで何とかなる。ハズ。頑張ってGUIで入れようとしても無駄だ。>未来の自分

2014年3月18日火曜日

Mojolicious メモ(その1)

このメモは間違っている可能性があります。

Mojoliciousをapacheで起動
/etc/httpd/conf.d/mymojo.conf
<Location /mymojo>
 SetHandler perl-script
 PerlResponseHandler Plack::Handler::Apache2
 PerlSetVar psgi_app /home/mem1j/my_mojo/script/my_mojo
</Location>

サンプルで出来てるtemplate/example/welcom.html.epとかでのパスは指定方法を変更してアプリ配置場所を指すように変更する。
<h2><%= $msg %></h2>
This page was generated from the template "templates/example/welcome.html.ep"
and the layout "templates/layouts/default.html.ep",
<a href="<%== url_for %>">click here</a> to reload the page or
<a href="<%== url_for('/index.html') %>">here</a> to move forward to a static page.

最後のパス指定を'/index.html'から <%== url_for('/index.html') %> に変更