[pypy-commit] pypy default: I'm merging this PR anyway, but if you need more improvements, pop in on #pypy on IRC
fijal
noreply at buildbot.pypy.org
Sun Feb 22 17:48:02 CET 2015
Author: Maciej Fijalkowski <fijall at gmail.com>
Branch:
Changeset: r76049:4aecd4091baf
Date: 2015-02-22 18:48 +0200
http://bitbucket.org/pypy/pypy/changeset/4aecd4091baf/
Log: I'm merging this PR anyway, but if you need more improvements, pop
in on #pypy on IRC
Merged in vvladymyrov/pypy (pull request #307)
improve _contains_ and _getitem_ performance almost 2x times using
trick I've seen in py-lmdb to avoid key alloc/dup:
diff --git a/lib_pypy/gdbm.py b/lib_pypy/gdbm.py
--- a/lib_pypy/gdbm.py
+++ b/lib_pypy/gdbm.py
@@ -20,9 +20,11 @@
} datum;
datum gdbm_fetch(void*, datum);
+datum pygdbm_fetch(void*, char*, int);
int gdbm_delete(void*, datum);
int gdbm_store(void*, datum, datum, int);
int gdbm_exists(void*, datum);
+int pygdbm_exists(void*, char*, int);
int gdbm_reorganize(void*);
@@ -37,19 +39,29 @@
''')
try:
+ verify_code = '''
+ #include "gdbm.h"
+
+ static datum pygdbm_fetch(GDBM_FILE gdbm_file, char *dptr, int dsize) {
+ datum key = {dptr, dsize};
+ return gdbm_fetch(gdbm_file, key);
+ }
+
+ static int pygdbm_exists(GDBM_FILE gdbm_file, char *dptr, int dsize) {
+ datum key = {dptr, dsize};
+ return gdbm_exists(gdbm_file, key);
+ }
+
+ '''
if sys.platform.startswith('freebsd'):
import os.path
_localbase = os.environ.get('LOCALBASE', '/usr/local')
- lib = ffi.verify('''
- #include "gdbm.h"
- ''', libraries=['gdbm'],
+ lib = ffi.verify(verify_code, libraries=['gdbm'],
include_dirs=[os.path.join(_localbase, 'include')],
library_dirs=[os.path.join(_localbase, 'lib')]
)
else:
- lib = ffi.verify('''
- #include "gdbm.h"
- ''', libraries=['gdbm'])
+ lib = ffi.verify(verify_code, libraries=['gdbm'])
except cffi.VerificationError as e:
# distutils does not preserve the actual message,
# but the verification is simple enough that the
@@ -59,6 +71,13 @@
class error(Exception):
pass
+def _checkstr(key):
+ if isinstance(key, unicode):
+ key = key.encode("ascii")
+ if not isinstance(key, str):
+ raise TypeError("gdbm mappings have string indices only")
+ return key
+
def _fromstr(key):
if isinstance(key, unicode):
key = key.encode("ascii")
@@ -107,12 +126,14 @@
def __contains__(self, key):
self._check_closed()
- return lib.gdbm_exists(self.ll_dbm, _fromstr(key))
+ key = _checkstr(key)
+ return lib.pygdbm_exists(self.ll_dbm, key, len(key)
has_key = __contains__
def __getitem__(self, key):
self._check_closed()
- drec = lib.gdbm_fetch(self.ll_dbm, _fromstr(key))
+ key = _checkstr(key)
+ drec = lib.pygdbm_fetch(self.ll_dbm, key, len(key))
if not drec.dptr:
raise KeyError(key)
res = str(ffi.buffer(drec.dptr, drec.dsize))
More information about the pypy-commit
mailing list