Skip to content

Instantly share code, notes, and snippets.

@dckc
Last active October 7, 2023 16:55
Show Gist options
  • Save dckc/5b2e9faf0cb6028e09bec0d12eeea383 to your computer and use it in GitHub Desktop.
Save dckc/5b2e9faf0cb6028e09bec0d12eeea383 to your computer and use it in GitHub Desktop.
differential bundle loading
// @ts-check
import '@endo/init';
import { createHash } from 'crypto';
import { ZipReader } from '@endo/zip';
/**
* @file What files in a bundle are not already in already loaded bundles?
*
* For each b1-* style bundle in the bundles table of a swingstore,
* load only the files that are not already in a loaded bundle.
*
* See also:
*
* share Zoe/ERTP libraries among contracts #2391
* https://github.com/Agoric/agoric-sdk/issues/2391
*/
/**
* SQL short-hand
*
* @param {import('better-sqlite3').Database} db
*/
export const dbTool = db => {
const prepare = (strings, ...params) => {
const dml = strings.join('?');
return { stmt: db.prepare(dml), params };
};
const sql = (strings, ...args) => {
const { stmt, params } = prepare(strings, ...args);
return stmt.all(...params);
};
sql.get = (strings, ...args) => {
const { stmt, params } = prepare(strings, ...args);
return stmt.get(...params);
};
sql.run = (strings, ...args) => {
const { stmt, params } = prepare(strings, ...args);
stmt.run(...params);
};
return sql;
};
/** @param {Uint8Array} bytes */
const computeSha512 = bytes => {
const hash = createHash('sha512');
hash.update(bytes);
return hash.digest().toString('hex');
};
/** @param {ReturnType<typeof dbTool>} sql */
const bundleLoader = sql => {
const createTables = async () => {
sql.run`create table if not exists bundleFiles
(name text, sha512 text primary key, content blob, info text)`;
sql.run`create temp table if not exists bundleTmp
(name text, sha512 text primary key, content blob, info text)`;
};
/** @param {ZipReader} zipRd */
const saveNewFiles = async zipRd => {
const files = { new: 0, total: zipRd.files.size };
const bytes = { new: 0, total: 0 };
for (const [name, { content }] of zipRd.files.entries()) {
bytes.total += content.length;
const sha512 = computeSha512(content);
const {
qty,
} = sql.get`select count(*) qty from bundleFiles where sha512 = ${sha512}`;
if (qty) continue;
files.new += 1;
bytes.new += content.length;
sql.run`insert into bundleFiles (name, sha512, content) values (${name}, ${sha512}, ${content})`;
console.log('added', name, content.length);
}
files.pct = Math.round((files.new / files.total) * 10000) / 100;
bytes.pct = Math.round((bytes.new / bytes.total) * 10000) / 100;
return { files, bytes };
};
return { createTables, saveNewFiles };
};
/** @param {ZipReader} zipRd */
const getEntry = async zipRd => {
const de = new TextDecoder();
const cmapBytes = zipRd.files.get('compartment-map.json').content;
const cmap = JSON.parse(de.decode(cmapBytes));
return cmap.entry;
};
/** @param {string[]} argv */
const main = async (argv, { betterSqlite3 }) => {
const { default: Database } = betterSqlite3;
const [_node, _script, dbFn] = argv;
if (!dbFn) throw Error('missing dbFn');
console.log(Database);
const db = new Database(dbFn);
const sql = dbTool(db);
const loader = bundleLoader(sql);
await loader.createTables();
sql.run`delete from bundleFiles`; // @@@@
const de = new TextDecoder();
const loaded = sql`select * from bundles`;
for (const { bundleID, bundle } of loaded) {
if (!bundleID.startsWith('b1-')) continue;
const zipBuf = bundle;
const zipRd = new ZipReader(zipBuf);
const entry = await getEntry(zipRd);
console.log(entry, bundleID);
const stats = await loader.saveNewFiles(zipRd);
console.log(entry, stats);
}
};
main([...process.argv], {
betterSqlite3: await import('better-sqlite3'),
}).catch(err => {
console.error(err);
process.exit(1);
});
entry files files_tot bytes cmap_size bytes_tot pct_saved
{"compartment":"@agoric/zoe-v0.26.2","module":"./contractFacet.js"} 166 170 959230 89326 960462 0.12827160262457027
{"compartment":"@agoric/vats-v0.15.1","module":"./src/proposals/network-proposal.js"} 49 92 375408 48710 509261 26.283771975470337
{"compartment":"@agoric/swingset-vat-v0.32.2","module":"./src/vats/comms/index.js"} 21 58 166976 30879 358097 53.37129325294543
{"compartment":"@agoric/inter-protocol-v0.16.1","module":"./src/vaultFactory/vaultFactory.js"} 34 196 397473 102216 1302999 69.49552532273624
{"compartment":"@agoric/inter-protocol-v0.16.1","module":"./src/proposals/addAssetToVault.js"} 34 169 314469 97058 1062255 70.39609133400172
{"compartment":"@agoric/swingset-vat-v0.32.2","module":"./src/devices/timer/device-timer.js"} 2 29 30868 21083 126076 75.51635521431517
{"compartment":"@agoric/zoe-v0.26.2","module":"./src/contracts/scaledPriceAuthority.js"} 21 134 166738 63817 807962 79.36313836541818
{"compartment":"@agoric/swingset-vat-v0.32.2","module":"./src/devices/mailbox/device-mailbox.js"} 2 29 23964 21095 119172 79.89124962239453
{"compartment":"@agoric/swingset-vat-v0.32.2","module":"./src/devices/bridge/device-bridge.js"} 2 28 22911 20416 115096 80.09400847987767
{"compartment":"@agoric/swingset-vat-v0.32.2","module":"./src/devices/vat-admin/device-vat-admin.js"} 4 43 46881 26503 251807 81.38216967757052
{"compartment":"@agoric/vats-v0.15.1","module":"./src/vat-zoe.js"} 16 137 154045 69608 829312 81.42496430776355
{"compartment":"@agoric/vats-v0.15.1","module":"./src/core/boot-chain.js"} 11 202 189281 109248 1189255 84.08406943842994
{"compartment":"@agoric/smart-wallet-v0.5.3","module":"./src/walletFactory.js"} 8 149 137248 81185 907003 84.86796625810499
{"compartment":"@agoric/swingset-vat-v0.32.2","module":"./src/vats/timer/vat-timer.js"} 2 67 70957 39311 470221 84.90986153319396
{"compartment":"@agoric/vats-v0.15.1","module":"./src/vat-bridge.js"} 4 73 64766 39952 483405 86.60212451257227
{"compartment":"@agoric/vats-v0.15.1","module":"./src/vat-bank.js"} 3 115 94909 58856 716228 86.74877273717308
{"compartment":"@agoric/vats-v0.15.1","module":"./src/vat-ibc.js"} 4 95 68712 49717 524303 86.89460102269108
{"compartment":"@agoric/swingset-vat-v0.32.2","module":"./src/vats/vat-admin/vat-vat-admin.js"} 2 64 57713 37748 445699 87.05112643286164
{"compartment":"@agoric/inter-protocol-v0.16.1","module":"./src/price/fluxAggregatorContract.js"} 6 167 133317 90802 1042656 87.21371190498112
{"compartment":"@agoric/inter-protocol-v0.16.1","module":"./src/proposals/core-proposal.js"} 8 181 132108 100852 1129772 88.30666718594549
{"compartment":"@agoric/vats-v0.15.1","module":"./src/provisionPool.js"} 3 155 110693 92660 961044 88.48200498624412
{"compartment":"@agoric/inter-protocol-v0.16.1","module":"./src/feeDistributor.js"} 3 113 78043 60676 700961 88.86628500016405
{"compartment":"@agoric/swingset-vat-v0.32.2","module":"./src/vats/vattp/vat-vattp.js"} 2 64 47779 37724 435765 89.03560405264305
{"compartment":"@agoric/inter-protocol-v0.16.1","module":"./src/econCommitteeCharter.js"} 2 127 83593 77605 777907 89.25411392364383
{"compartment":"@agoric/vats-v0.15.1","module":"./src/vat-agoricNames.js"} 3 112 71409 57487 669963 89.34135168658568
{"compartment":"@agoric/inter-protocol-v0.16.1","module":"./src/psm/psm.js"} 2 165 105065 90351 1015525 89.65411979025627
{"compartment":"@agoric/inter-protocol-v0.16.1","module":"./src/reserve/assetReserve.js"} 3 164 104006 90056 1009168 89.69388644903525
{"compartment":"@agoric/vats-v0.15.1","module":"./src/vat-priceAuthority.js"} 3 113 70672 62552 687395 89.71886615410354
{"compartment":"@agoric/vats-v0.15.1","module":"./src/core/startWalletFactory.js"} 2 155 98704 88822 969530 89.81939702742567
{"compartment":"@agoric/inter-protocol-v0.16.1","module":"./src/proposals/price-feed-proposal.js"} 2 110 68050 59179 669483 89.83544018294714
{"compartment":"@agoric/vats-v0.15.1","module":"./src/vat-board.js"} 4 100 61493 55602 608592 89.89585798038752
{"compartment":"@agoric/governance-v0.10.3","module":"./src/binaryVoteCounter.js"} 4 117 71372 61768 715575 90.02592320860846
{"compartment":"@agoric/vats-v0.15.1","module":"./src/vat-network.js"} 2 92 49382 48665 504625 90.21411939559079
{"compartment":"@agoric/governance-v0.10.3","module":"./src/committee.js"} 4 136 80573 67797 828546 90.27537396837351
{"compartment":"@agoric/vats-v0.15.1","module":"./src/vat-provisioning.js"} 2 97 56797 50687 589048 90.35783161983403
{"compartment":"@agoric/inter-protocol-v0.16.1","module":"./src/proposals/startPSM.js"} 1 168 96581 96581 1051353 90.81364679608086
{"compartment":"@agoric/vats-v0.15.1","module":"./src/mintHolder.js"} 2 108 57958 56263 652227 91.1138300009046
{"compartment":"@agoric/vats-v0.15.1","module":"./src/centralSupply.js"} 2 108 57834 56272 652103 91.1311556609922
{"compartment":"@agoric/inter-protocol-v0.16.1","module":"./src/proposals/committee-proposal.js"} 1 76 38636 38636 450530 91.42432246465275
{"compartment":"@agoric/governance-v0.10.3","module":"./src/contractGovernor.js"} 1 120 62923 62923 742613 91.52681140782614
{"compartment":"@agoric/inter-protocol-v0.16.1","module":"./src/auction/auctioneer.js"} 1 179 95653 95653 1145422 91.6491039983517
with agg as (
select skip, entry, count(*) files, sum(size) bytes from bundleDetail group by entry, skip
)
, noskip as (select * from agg where skip = 0)
, skip as (select * from agg where skip = 1)
select noskip.entry, noskip.files, noskip.files + skip.files files_tot
, noskip.bytes, cmap_size, noskip.bytes + skip.bytes bytes_tot
, 100.0 * skip.bytes / (noskip.bytes + skip.bytes) pct_saved
from noskip
join skip on noskip.entry = skip.entry
join (select entry, size cmap_size from bundleDetail where name = 'compartment-map.json') c on c.entry = noskip.entry
order by pct_saved
;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment