Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
Bug 549080 - dev-db/sqlite - Use pread(), pread64(), pwrite(), pwrite64()
Summary: dev-db/sqlite - Use pread(), pread64(), pwrite(), pwrite64()
Status: RESOLVED FIXED
Alias: None
Product: Gentoo Linux
Classification: Unclassified
Component: Current packages (show other bugs)
Hardware: All Linux
: Normal normal (vote)
Assignee: Arfrever Frehtes Taifersar Arahesis
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-05-10 15:04 UTC by Thomas Deutschmann (RETIRED)
Modified: 2015-05-15 10:55 UTC (History)
1 user (show)

See Also:
Package list:
Runtime testing required: ---


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Thomas Deutschmann (RETIRED) gentoo-dev 2015-05-10 15:04:26 UTC
Hi,

we are currently building dev-db/sqlite with support for pread.

Please consider adding support for pread{,64}.


To test I used "db_bench_sqlite3" from dev-libs/leveldb:

  # cd /usr/portage/dev-libs/leveldb/
  # ebuild leveldb-1.18-r1.ebuild clean configure
  # cd /var/tmp/portage/dev-libs/leveldb-1.18-r1/work/leveldb-1.18
  # make db_bench_sqlite3
  # cp db_bench_sqlite3 /tmp


With dev-db/sqlite-3.8.9 (without pread):

HDD:
====
$ ./db_bench_sqlite3
SQLite:     version 3.8.9
Date:       Fri May  8 19:37:01 2015
CPU:        4 * Intel(R) Core(TM) i7-3770K CPU @ 3.50GHz
CPUCache:   8192 KB
Keys:       16 bytes each
Values:     100 bytes each
Entries:    1000000
RawSize:    110.6 MB (estimated)
------------------------------------------------
fillseq      :      10.109 micros/op;   10.9 MB/s
fillseqsync  :     153.433 micros/op;    0.7 MB/s (10000 ops)
fillseqbatch :       3.382 micros/op;   32.7 MB/s
fillrandom   :      21.185 micros/op;    5.2 MB/s
fillrandsync :     157.832 micros/op;    0.7 MB/s (10000 ops)
fillrandbatch :      11.005 micros/op;   10.1 MB/s
overwrite    :      21.390 micros/op;    5.2 MB/s
overwritebatch :      15.715 micros/op;    7.0 MB/s
readrandom   :       5.645 micros/op;
readseq      :       1.947 micros/op;   49.0 MB/s
fillrand100K :     378.080 micros/op;  252.3 MB/s (1000 ops)
fillseq100K  :     468.469 micros/op;  203.6 MB/s (1000 ops)
readseq      :      44.409 micros/op; 2147.5 MB/s
readrand100K :      51.067 micros/op;



RAM DISK:
=========
$ ./db_bench_sqlite3
SQLite:     version 3.8.9
Date:       Fri May  8 19:48:14 2015
CPU:        4 * Intel(R) Core(TM) i7-3770K CPU @ 3.50GHz
CPUCache:   8192 KB
Keys:       16 bytes each
Values:     100 bytes each
Entries:    1000000
RawSize:    110.6 MB (estimated)
------------------------------------------------
fillseq      :       7.639 micros/op;   14.5 MB/s
fillseqsync  :       7.749 micros/op;   14.3 MB/s (10000 ops)
fillseqbatch :       3.074 micros/op;   36.0 MB/s
fillrandom   :      16.689 micros/op;    6.6 MB/s
fillrandsync :       9.526 micros/op;   11.6 MB/s (10000 ops)
fillrandbatch :       9.227 micros/op;   12.0 MB/s
overwrite    :      17.695 micros/op;    6.3 MB/s
overwritebatch :      13.470 micros/op;    8.2 MB/s
readrandom   :       6.012 micros/op;
readseq      :       1.996 micros/op;   47.8 MB/s
fillrand100K :     242.195 micros/op;  393.8 MB/s (1000 ops)
fillseq100K  :     283.248 micros/op;  336.7 MB/s (1000 ops)
readseq      :      47.220 micros/op; 2019.6 MB/s
readrand100K :      54.109 micros/op;

db_bench_sqlite3 uses a hard coded path. For ramdisk test you have to do something like

  # mkdir /tmp/leveldbtest-0
  # mount -t tmpfs -o size=1000M none /tmp/leveldbtest-0/

(yes, you need ~1gig)


Now I applied to following changes to "/usr/portage/dev-db/sqlite/sqlite-3.8.9.ebuild":

--- sqlite-3.8.9.ebuild.old     2015-05-10 16:56:38.000000000 +0200
+++ sqlite-3.8.9.ebuild 2015-05-10 16:57:34.000000000 +0200
@@ -106,6 +106,9 @@
        # http://sqlite.org/unlock_notify.html
        append-cppflags -DSQLITE_ENABLE_UNLOCK_NOTIFY

+       # Use pread/pwrite
+       append-cppflags -DUSE_PREAD64
+
        if use icu; then
                append-cppflags -DSQLITE_ENABLE_ICU
                if amalgamation; then


...and re-run my benchmarks:

RAM DISK:
=========
SQLite:     version 3.8.9
Date:       Fri May  8 19:54:59 2015
CPU:        4 * Intel(R) Core(TM) i7-3770K CPU @ 3.50GHz
CPUCache:   8192 KB
Keys:       16 bytes each
Values:     100 bytes each
Entries:    1000000
RawSize:    110.6 MB (estimated)
------------------------------------------------
fillseq      :       7.625 micros/op;   14.5 MB/s
fillseqsync  :       7.501 micros/op;   14.7 MB/s (10000 ops)
fillseqbatch :       3.021 micros/op;   36.6 MB/s
fillrandom   :      16.272 micros/op;    6.8 MB/s
fillrandsync :       9.206 micros/op;   12.0 MB/s (10000 ops)
fillrandbatch :       8.854 micros/op;   12.5 MB/s
overwrite    :      17.091 micros/op;    6.5 MB/s
overwritebatch :      12.899 micros/op;    8.6 MB/s
readrandom   :       5.674 micros/op;
readseq      :       1.947 micros/op;   49.0 MB/s
fillrand100K :     228.538 micros/op;  417.4 MB/s (1000 ops)
fillseq100K  :     224.698 micros/op;  424.5 MB/s (1000 ops)
readseq      :      42.136 micros/op; 2263.3 MB/s
readrand100K :      48.376 micros/op;


HDD:
====
SQLite:     version 3.8.9
Date:       Fri May  8 19:57:29 2015
CPU:        4 * Intel(R) Core(TM) i7-3770K CPU @ 3.50GHz
CPUCache:   8192 KB
Keys:       16 bytes each
Values:     100 bytes each
Entries:    1000000
RawSize:    110.6 MB (estimated)
------------------------------------------------
fillseq      :       9.636 micros/op;   11.5 MB/s
fillseqsync  :     156.583 micros/op;    0.7 MB/s (10000 ops)
fillseqbatch :       3.213 micros/op;   34.4 MB/s
fillrandom   :      19.531 micros/op;    5.7 MB/s
fillrandsync :     159.840 micros/op;    0.7 MB/s (10000 ops)
fillrandbatch :      10.240 micros/op;   10.8 MB/s
overwrite    :      20.228 micros/op;    5.5 MB/s
overwritebatch :      14.699 micros/op;    7.5 MB/s
readrandom   :       5.332 micros/op;
readseq      :       1.724 micros/op;   55.3 MB/s
fillrand100K :     346.456 micros/op;  275.3 MB/s (1000 ops)
fillseq100K  :     356.193 micros/op;  267.8 MB/s (1000 ops)
readseq      :      39.081 micros/op; 2440.3 MB/s
readrand100K :      45.004 micros/op;


I would have proposed a patch for the ebuild but I don't know what's the best way to do that: Not sure if all our arches support pread/pwrite. On 64-bit systems you want to use pread64 instead of just pread...



Reproducible: Always
Comment 1 Thomas Deutschmann (RETIRED) gentoo-dev 2015-05-10 15:06:28 UTC
Mhh...

> we are currently building dev-db/sqlite with support for pread.

should be obviously

> we are currently building dev-db/sqlite *without* support for pread.

:>
Comment 2 Arfrever Frehtes Taifersar Arahesis 2015-05-15 00:19:50 UTC
With glibc, on 64-bit architectures, pread() and pread64() probably behave identically:

$ gcc -E -P - <<< "#include <unistd.h>" |& grep -E "typedef .* __off"
typedef long int __off_t;
typedef long int __off64_t;
$ gcc -E -P -m32 - <<< "#include <unistd.h>" |& grep -E "typedef .* __off"
__extension__ typedef long int __off_t;
__extension__ typedef __quad_t __off64_t;
$ gcc -E -P -m32 - <<< "#include <unistd.h>" |& grep -E "typedef .* __quad_t"
__extension__ typedef long long int __quad_t;
$ gcc -o test -x c - <<< $'#include <stdio.h>\nint main(){printf("sizeof(__off_t) = %zd\\nsizeof(__off64_t) = %zd\\n", sizeof(__off_t), sizeof(__off64_t));}'
$ ./test
sizeof(__off_t) = 8
sizeof(__off64_t) = 8
$ gcc -m32 -o test -x c - <<< $'#include <stdio.h>\nint main(){printf("sizeof(__off_t) = %zd\\nsizeof(__off64_t) = %zd\\n", sizeof(__off_t), sizeof(__off64_t));}'
$ ./test
sizeof(__off_t) = 4
sizeof(__off64_t) = 8



With _FILE_OFFSET_BITS=64, pread() is redirection to pread64():

$ gcc -E -P - <<< "#include <unistd.h>" | grep -EA1 "(pread|pwrite)"
extern ssize_t pread (int __fd, void *__buf, size_t __nbytes,
        __off_t __offset) ;
extern ssize_t pwrite (int __fd, const void *__buf, size_t __n,
         __off_t __offset) ;
$ gcc -E -P -D_LARGEFILE64_SOURCE - <<< "#include <unistd.h>" | grep -EA1 "(pread|pwrite)"
extern ssize_t pread (int __fd, void *__buf, size_t __nbytes,
        __off_t __offset) ;
extern ssize_t pwrite (int __fd, const void *__buf, size_t __n,
         __off_t __offset) ;
extern ssize_t pread64 (int __fd, void *__buf, size_t __nbytes,
   __off64_t __offset) ;
extern ssize_t pwrite64 (int __fd, const void *__buf, size_t __n,
    __off64_t __offset) ;
$ gcc -E -P -D_FILE_OFFSET_BITS=64 - <<< "#include <unistd.h>" | grep -E "(pread|pwrite)"
extern ssize_t pread (int __fd, void *__buf, size_t __nbytes, __off64_t __offset) __asm__ ("" "pread64") ;
extern ssize_t pwrite (int __fd, const void *__buf, size_t __nbytes, __off64_t __offset) __asm__ ("" "pwrite64") ;
$ gcc -E -P -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 - <<< "#include <unistd.h>" | grep -EA1 "(pread|pwrite)"
extern ssize_t pread (int __fd, void *__buf, size_t __nbytes, __off64_t __offset) __asm__ ("" "pread64") ;
extern ssize_t pwrite (int __fd, const void *__buf, size_t __nbytes, __off64_t __offset) __asm__ ("" "pwrite64") ;
extern ssize_t pread64 (int __fd, void *__buf, size_t __nbytes,
   __off64_t __offset) ;
extern ssize_t pwrite64 (int __fd, const void *__buf, size_t __n,
    __off64_t __offset) ;
$ gcc -S -D_FILE_OFFSET_BITS=64 -o - -x c - <<< $'#include <unistd.h>\nint main(){pread(0,0,0,0);pwrite(0,0,0,0);}' | grep -E "(pread|pwrite)"
        call    pread64
        call    pwrite64
$ gcc -S -m32 -D_FILE_OFFSET_BITS=64 -o - -x c - <<< $'#include <unistd.h>\nint main(){pread(0,0,0,0);pwrite(0,0,0,0);}' | grep -E "(pread|pwrite)"
        call    pread64
        call    pwrite64



src/sqliteInt.h of SQLite 3.8.10.1:
#ifndef SQLITE_DISABLE_LFS
# define _LARGE_FILE       1
# ifndef _FILE_OFFSET_BITS
#   define _FILE_OFFSET_BITS 64
# endif
# define _LARGEFILE_SOURCE 1
#endif



After building of SQLite on 64-bit architecture with -DUSE_PREAD and without -DUSE_PREAD64:
$ readelf -s .libs/libsqlite3.so | grep -E "(pread|pwrite)"
    60: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND pread64@GLIBC_2.2.5 (3)
    75: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND pwrite64@GLIBC_2.2.5 (3)
  1619: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND pread64@@GLIBC_2.2.5
  1651: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND pwrite64@@GLIBC_2.2.5
Comment 3 Arfrever Frehtes Taifersar Arahesis 2015-05-15 01:26:53 UTC
pread64() and pwrite64() are declared when _LARGEFILE64_SOURCE is defined.

src/sqliteInt.h of SQLite 3.8.10.1:
#if defined(__GNUC__) && !defined(_GNU_SOURCE)
# define _GNU_SOURCE
#endif

features.h of glibc 2.20:
#ifdef _GNU_SOURCE
...
# undef  _LARGEFILE64_SOURCE
# define _LARGEFILE64_SOURCE    1
...
#endif

So using of pread64() and pwrite64() with glibc and compiler not defining __GNUC__ might require using -D_LARGEFILE64_SOURCE (potentially using append-lfs-flags() from flag-o-matic.eclass).
Comment 4 Arfrever Frehtes Taifersar Arahesis 2015-05-15 10:55:58 UTC
Fixed in dev-db/sqlite-3.8.10.1.