Improve performance of blob reading/writing with ffi

This commit is contained in:
Simon Binder 2019-09-24 21:53:14 +02:00
parent ba21a594af
commit 3e286e27af
No known key found for this signature in database
GPG Key ID: 7891917E4147B8C0
2 changed files with 22 additions and 13 deletions

View File

@ -11,11 +11,12 @@ class CBlob extends Struct<CBlob> {
int data;
static Pointer<CBlob> allocate(Uint8List blob) {
final str = Pointer<CBlob>.allocate(count: blob.length);
for (var i = 0; i < blob.length; i++) {
str.elementAt(i).load<CBlob>().data = blob[i];
}
return str;
final str = Pointer<Uint8>.allocate(count: blob.length);
final asList = str.asExternalTypedData(count: blob.length) as Uint8List;
asList.setAll(0, blob);
return str.cast();
}
/// Allocates a 0-terminated string, encoded as utf8 and read from the
@ -30,18 +31,25 @@ class CBlob extends Struct<CBlob> {
/// Reads [bytesToRead] bytes from the current position.
Uint8List read(int bytesToRead) {
assert(bytesToRead >= 0);
final str = addressOf;
final str = addressOf.cast<Uint8>();
if (isNullPointer(str)) return null;
// todo can we user Pointer.asExternalTypedData here?
final blob = Uint8List(bytesToRead);
for (var i = 0; i < bytesToRead; ++i) {
blob[i] = str.elementAt(i).load<CBlob>().data;
}
return blob;
final data = str.asExternalTypedData(count: bytesToRead) as Uint8List;
return Uint8List.fromList(data);
}
/// More efficient version of [readString] that doesn't have to find a nil-
/// terminator. [length] is the amount of bytes to read. The string will be
/// decoded via [utf8].
String readAsStringWithLength(int length) {
return utf8.decode(read(length));
}
/// Reads a 0-terminated string, decoded with utf8.
///
/// Warning: This method is very, very slow. If there is any way to know the
/// length of the string to read, [readAsStringWithLength] will be orders of
/// magnitude faster.
String readString() {
final str = addressOf;
if (isNullPointer(str)) return null;

View File

@ -59,10 +59,11 @@ class PreparedStatement implements BasePreparedStatement {
case Types.SQLITE_FLOAT:
return bindings.sqlite3_column_double(_stmt, index);
case Types.SQLITE_TEXT:
final length = bindings.sqlite3_column_bytes(_stmt, index);
return bindings
.sqlite3_column_text(_stmt, index)
.load<CBlob>()
.readString();
.readAsStringWithLength(length);
case Types.SQLITE_BLOB:
final length = bindings.sqlite3_column_bytes(_stmt, index);
return bindings