aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorstephan <stephan@noemail.net>2022-06-25 07:42:24 +0000
committerstephan <stephan@noemail.net>2022-06-25 07:42:24 +0000
commit1c67ec5692ff02b506aca335d60f387a4f3b75a1 (patch)
treeb6079fb11d8507c9caa01e7087260c6fbfdc116d
parentf170b0868dd616fbc40946d95fafe02d70ffc4e4 (diff)
downloadsqlite-1c67ec5692ff02b506aca335d60f387a4f3b75a1.tar.gz
sqlite-1c67ec5692ff02b506aca335d60f387a4f3b75a1.zip
wasm: eliminated the need for Stmt objects to keep ahold of memory allocated for bound strings and blobs. Added alternate string/blob bind impls which are hypothetically more efficient but not yet proven to be so.
FossilOrigin-Name: da1d3151a440567f34a2f6c0b2bfc2e9fab81c256cc361c9ce7b46f2c23a2aa8
-rw-r--r--ext/fiddle/EXPORTED_RUNTIME_METHODS1
-rw-r--r--ext/fiddle/sqlite3-api.js75
-rw-r--r--ext/fiddle/testing1.js15
-rw-r--r--manifest16
-rw-r--r--manifest.uuid2
5 files changed, 64 insertions, 45 deletions
diff --git a/ext/fiddle/EXPORTED_RUNTIME_METHODS b/ext/fiddle/EXPORTED_RUNTIME_METHODS
index 3d06c3219..af2c48a3f 100644
--- a/ext/fiddle/EXPORTED_RUNTIME_METHODS
+++ b/ext/fiddle/EXPORTED_RUNTIME_METHODS
@@ -11,3 +11,4 @@ setValue
stackAlloc
stackRestore
stackSave
+stringToUTF8Array
diff --git a/ext/fiddle/sqlite3-api.js b/ext/fiddle/sqlite3-api.js
index eabac6cc5..450bbb62c 100644
--- a/ext/fiddle/sqlite3-api.js
+++ b/ext/fiddle/sqlite3-api.js
@@ -405,7 +405,7 @@ Module.postRun.push(function(namespace/*the module object, the target for
['getValue','setValue', 'stackSave', 'stackRestore', 'stackAlloc',
'allocateUTF8OnStack', '_malloc', '_free',
'addFunction', 'removeFunction',
- 'intArrayFromString'
+ 'intArrayFromString', 'lengthBytesUTF8', 'stringToUTF8Array'
].forEach(function(m){
if(undefined === (api.wasm[m] = SQM[m])){
toss("Internal init error: Module."+m+" not found.");
@@ -524,7 +524,6 @@ Module.postRun.push(function(namespace/*the module object, the target for
this._pStmt = arguments[1];
this.columnCount = api.sqlite3_column_count(this._pStmt);
this.parameterCount = api.sqlite3_bind_parameter_count(this._pStmt);
- this._allocs = [/*list of alloc'd memory blocks for bind() values*/]
};
/** Throws if the given DB has been closed, else it is returned. */
@@ -1186,12 +1185,29 @@ Module.postRun.push(function(namespace/*the module object, the target for
if(!f._){
f._ = {
string: function(stmt, ndx, val, asBlob){
- const bytes = api.wasm.intArrayFromString(val,true);
- const pStr = api.wasm._malloc(bytes.length || 1);
- stmt._allocs.push(pStr);
- api.wasm._malloc.HEAP.set(bytes, pStr);
- const func = asBlob ? api.sqlite3_bind_blob : api.sqlite3_bind_text;
- return func(stmt._pStmt, ndx, pStr, bytes.length, api.SQLITE_STATIC);
+ if(1){
+ /* _Hypothetically_ more efficient than the impl in the 'else' block. */
+ const stack = api.wasm.stackSave();
+ try{
+ const n = api.wasm.lengthBytesUTF8(val)+1/*required for NUL terminator*/;
+ const pStr = api.wasm.stackAlloc(n);
+ api.wasm.stringToUTF8Array(val, api.wasm.HEAP8, pStr, n);
+ const f = asBlob ? api.sqlite3_bind_blob : api.sqlite3_bind_text;
+ return f(stmt._pStmt, ndx, pStr, n-1, api.SQLITE_TRANSIENT);
+ }finally{
+ api.wasm.stackRestore(stack);
+ }
+ }else{
+ const bytes = api.wasm.intArrayFromString(val,true);
+ const pStr = api.wasm._malloc(bytes.length || 1);
+ api.wasm._malloc.HEAP.set(bytes.length ? bytes : [0], pStr);
+ try{
+ const f = asBlob ? api.sqlite3_bind_blob : api.sqlite3_bind_text;
+ return f(stmt._pStmt, ndx, pStr, bytes.length, api.SQLITE_TRANSIENT);
+ }finally{
+ api.wasm._free(pStr);
+ }
+ }
}
};
}
@@ -1221,16 +1237,28 @@ Module.postRun.push(function(namespace/*the module object, the target for
case BindTypes.blob: {
if('string'===typeof val){
rc = f._.string(stmt, ndx, val, true);
- }else{
- if(!isSupportedTypedArray(val)){
- toss("Binding a value as a blob requires",
- "that it be a string, Uint8Array, or Int8Array.");
+ }else if(!isSupportedTypedArray(val)){
+ toss("Binding a value as a blob requires",
+ "that it be a string, Uint8Array, or Int8Array.");
+ }else if(1){
+ /* _Hypothetically_ more efficient than the impl in the 'else' block. */
+ const stack = api.wasm.stackSave();
+ try{
+ const pBlob = api.wasm.stackAlloc(val.byteLength || 1);
+ api.wasm.HEAP8.set(val.byteLength ? val : [0], pBlob)
+ rc = api.sqlite3_bind_blob(stmt._pStmt, ndx, pBlob, val.byteLength,
+ api.SQLITE_TRANSIENT);
+ }finally{
+ api.wasm.stackRestore(stack);
}
- //console.debug("Binding blob",len,val);
+ }else{
const pBlob = api.wasm.mallocFromTypedArray(val);
- stmt._allocs.push(pBlob);
- rc = api.sqlite3_bind_blob(stmt._pStmt, ndx, pBlob, val.byteLength,
- api.SQLITE_STATIC);
+ try{
+ rc = api.sqlite3_bind_blob(stmt._pStmt, ndx, pBlob, val.byteLength,
+ api.SQLITE_TRANSIENT);
+ }finally{
+ api.wasm._free(pBlob);
+ }
}
break;
}
@@ -1241,16 +1269,6 @@ Module.postRun.push(function(namespace/*the module object, the target for
if(rc) stmt.db.checkRc(rc);
return stmt;
};
-
- /** Frees any memory explicitly allocated for the given
- Stmt object. Returns stmt. */
- const freeBindMemory = function(stmt){
- let m;
- while(undefined !== (m = stmt._allocs.pop())){
- api.wasm._free(m);
- }
- return stmt;
- };
Stmt.prototype = {
/**
@@ -1262,7 +1280,6 @@ Module.postRun.push(function(namespace/*the module object, the target for
finalize: function(){
if(this._pStmt){
affirmUnlocked(this,'finalize()');
- freeBindMemory(this);
delete this.db._statements[this._pStmt];
api.sqlite3_finalize(this._pStmt);
delete this.columnCount;
@@ -1275,9 +1292,7 @@ Module.postRun.push(function(namespace/*the module object, the target for
/** Clears all bound values. Returns this object.
Throws if this statement has been finalized. */
clearBindings: function(){
- freeBindMemory(
- affirmUnlocked(affirmStmtOpen(this), 'clearBindings()')
- );
+ affirmUnlocked(affirmStmtOpen(this), 'clearBindings()')
api.sqlite3_clear_bindings(this._pStmt);
this._mayGet = false;
return this;
diff --git a/ext/fiddle/testing1.js b/ext/fiddle/testing1.js
index cc84ef6ef..9c17115f3 100644
--- a/ext/fiddle/testing1.js
+++ b/ext/fiddle/testing1.js
@@ -16,6 +16,7 @@
(function(){
const T = self.SqliteTestUtil;
const log = console.log.bind(console);
+ const debug = console.debug.bind(console);
const assert = function(condition, text) {
if (!condition) {
@@ -31,7 +32,7 @@
new TextEncoder('utf-8').encode("select 3 as a")
/* Testing handling of Uint8Array input */
);
- //log("statement =",st);
+ //debug("statement =",st);
T.assert(st._pStmt)
.assert(!st._mayGet)
.assert('a' === st.getColumnName(0))
@@ -76,7 +77,7 @@
/* Achtung: ^^^ bind support might be removed from multi-mode exec. */
});
T.assert(2 === list.length);
- //log("Exec'd SQL:", list);
+ //debug("Exec'd SQL:", list);
let blob = db.selectValue("select b from t where a='blob'");
T.assert(blob instanceof Uint8Array).
@@ -138,7 +139,7 @@
assert('hi'===db.selectValue("select asis('hi')"));
const eqApprox = function(v1,v2,factor=0.05){
- //log('eqApprox',v1, v2);
+ //debug('eqApprox',v1, v2);
return v1>=(v2-factor) && v1<=(v2+factor);
};
@@ -165,11 +166,11 @@
blobArg = new Int8Array(2);
blobArg.set([0x68, 0x69]);
- console.debug("blobArg=",blobArg);
+ //debug("blobArg=",blobArg);
blobRc = db.selectValue("select asis(?1)", blobArg);
T.assert(blobRc instanceof Uint8Array).
assert(2 === blobRc.length);
- console.debug("blobRc=",blobRc);
+ //debug("blobRc=",blobRc);
T.assert(0x68==blobRc[0] && 0x69==blobRc[1]);
};
@@ -196,9 +197,10 @@
const sqlite3 = Module.sqlite3;
const api = sqlite3.api;
const oo = sqlite3.SQLite3;
- console.log("Loaded module:",api.sqlite3_libversion(),
+ log("Loaded module:",api.sqlite3_libversion(),
api.sqlite3_sourceid());
log("Build options:",oo.compileOptionUsed());
+ log("api.wasm.HEAP8 size =",api.wasm.HEAP8.length);
const db = new oo.DB();
try {
log("DB:",db.filename);
@@ -213,6 +215,7 @@
db.close();
}
log("Total Test count:",T.counter);
+ log("api.wasm.HEAP8 size =",api.wasm.HEAP8.length);
};
initSqlite3Module(self.sqlite3TestModule).then(function(theModule){
diff --git a/manifest b/manifest
index e5790b9c5..58086c003 100644
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C wasm:\seliminated\sthe\sdependency\son\sthe\sdeprecated\semcc-provided\sallocate()\sfunction.\sAdjacent\scleanups\sin\sblob\sbinding.
-D 2022-06-25T06:46:22.284
+C wasm:\seliminated\sthe\sneed\sfor\sStmt\sobjects\sto\skeep\sahold\sof\smemory\sallocated\sfor\sbound\sstrings\sand\sblobs.\sAdded\salternate\sstring/blob\sbind\simpls\swhich\sare\shypothetically\smore\sefficient\sbut\snot\syet\sproven\sto\sbe\sso.
+D 2022-06-25T07:42:24.832
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -57,7 +57,7 @@ F ext/expert/sqlite3expert.h ca81efc2679a92373a13a3e76a6138d0310e32be53d6c3bfaed
F ext/expert/test_expert.c d56c194b769bdc90cf829a14c9ecbc1edca9c850b837a4d0b13be14095c32a72
F ext/fiddle/EXPORTED_FUNCTIONS.fiddle 7fb73f7150ab79d83bb45a67d257553c905c78cd3d693101699243f36c5ae6c3
F ext/fiddle/EXPORTED_FUNCTIONS.sqlite3-api 540b9dec63a3a62a256e2f030827848a92e9b9d9b6fa5c0188295a4a1c5382cd
-F ext/fiddle/EXPORTED_RUNTIME_METHODS e499bbb5201bf671850da8dcd47de31b0db47c1183f0c669016801b4d2035534
+F ext/fiddle/EXPORTED_RUNTIME_METHODS a004bd5eeeda6d3b28d16779b7f1a80305bfe009dfc7f0721b042967f0d39d02
F ext/fiddle/Makefile e25d34a0e1324f771d64c09c592601b97219282011587e6ce410fa8acdedb913
F ext/fiddle/SqliteTestUtil.js 559731c3e8e0de330ec7d292e6c1846566408caee6637acc8a119ac338a8781c
F ext/fiddle/emscripten.css 3d253a6fdb8983a2ac983855bfbdd4b6fa1ff267c28d69513dd6ef1f289ada3f
@@ -65,11 +65,11 @@ F ext/fiddle/fiddle-worker.js 88bc2193a6cb6a3f04d8911bed50a4401fe6f277de7a71ba83
F ext/fiddle/fiddle.html 550c5aafce40bd218de9bf26192749f69f9b10bc379423ecd2e162bcef885c08
F ext/fiddle/fiddle.js 812f9954cc7c4b191884ad171f36fcf2d0112d0a7ecfdf6087896833a0c079a8
F ext/fiddle/index.md d9c1c308d8074341bc3b11d1d39073cd77754cb3ca9aeb949f23fdd8323d81cf
-F ext/fiddle/sqlite3-api.js 706bb55b3901a90ec3a0e588f00d4c260d61d5b5ac916b894f48cdd6203ff0ba
+F ext/fiddle/sqlite3-api.js 664a454d82694c6cfab36b8ad9e36620cfc44fa37e05642ba87109c37409f51f
F ext/fiddle/sqlite3-worker.js a9c2b614beca187dbdd8c053ec2770cc61ec1ac9c0ec6398ceb49a79f705a421
F ext/fiddle/testing.css 750572dded671d2cf142bbcb27af5542522ac08db128245d0b9fe410aa1d7f2a
F ext/fiddle/testing1.html ea1f3be727f78e420007f823912c1a03b337ecbb8e79449abc2244ad4fe15d9a
-F ext/fiddle/testing1.js f3a5bd125154a51dfe20b699cb90c7cf2a23fbb5eaf9129cd4fb06e262de2647
+F ext/fiddle/testing1.js 5c04721d205b3d909ec6896682743051cb5e5202e9151a058e90600a42f48f48
F ext/fiddle/testing2.html 9063b2430ade2fe9da4e711addd1b51a2741cf0c7ebf6926472a5e5dd63c0bc4
F ext/fiddle/testing2.js 7b45b4e7fddbd51dbaf89b6722c02758051b34bac5a98c11b569a7e7572f88ee
F ext/fts1/README.txt 20ac73b006a70bcfd80069bdaf59214b6cf1db5e
@@ -1978,8 +1978,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 37a8fecb56793fbd3763a2240a0bd62b639c811934d3af2ef0e5ff579073d632
-R 4c023b8516cd5b1336a52ada20a79c7d
+P 140618b212e3aa9ff2df20f22af846a1c4c5ffaeefd84330446f61362b39a8f1
+R ecfc68999ba200e5f9d0ce8c6a78fe70
U stephan
-Z 05e90a0a470a56e05a8109a17f4f47da
+Z ec8563cad502dab169a1c4538eaf6ec1
# Remove this line to create a well-formed Fossil manifest.
diff --git a/manifest.uuid b/manifest.uuid
index 1bb4a79eb..63c94d8ff 100644
--- a/manifest.uuid
+++ b/manifest.uuid
@@ -1 +1 @@
-140618b212e3aa9ff2df20f22af846a1c4c5ffaeefd84330446f61362b39a8f1 \ No newline at end of file
+da1d3151a440567f34a2f6c0b2bfc2e9fab81c256cc361c9ce7b46f2c23a2aa8 \ No newline at end of file