tricu

An interpreted language for exploring Tree Calculus
Log | Files | Refs | README | LICENSE

demo-cost.mjs (2562B)


      1 // Opt-in deterministic work/allocation screen, not a wall-time/RAM benchmark.
      2 // Supply an independently retained prior site directory; never rewrite its pins.
      3 import assert from 'node:assert/strict';
      4 import {readFile} from 'node:fs/promises';
      5 import {resolve,join} from 'node:path';
      6 import {fileURLToPath} from 'node:url';
      7 import {createHash} from 'node:crypto';
      8 import {Graph} from '../dist/graph.js';
      9 import {decodeBundle,loadBundle} from '../dist/bundle.js';
     10 import {PACKAGE_BUDGET} from './budgets.mjs';
     11 import {PACKAGE_COLLECTION} from '../dist/execution.js';
     12 import {runIO} from '../dist/io.js';
     13 const current=fileURLToPath(new URL('../',import.meta.url));
     14 if(!process.argv[2])throw Error('Select the retained reference site directory');
     15 async function measure(directory){
     16   const data=JSON.parse(await readFile(join(directory,'demos.json'))),result={};
     17   for(const [name,demo] of Object.entries(data.demos)){
     18     const bytes=await readFile(join(directory,'bundles',demo.hash+'.arboricx'));
     19     assert.equal(createHash('sha256').update(bytes).digest('hex'),demo.hash);
     20     const bundle=decodeBundle(bytes);const cases=[];
     21     for(const c of demo.haskellCases){
     22       const g=new Graph(PACKAGE_BUDGET,PACKAGE_COLLECTION),exports=loadBundle(g,bundle);
     23       let output=g.apply(exports.get(c.export),c.arguments.map(tree=>g.fromTernary(tree))),terminal='';
     24       if(demo.mode==='io')output=await runIO(g,output,{
     25         before:async()=>{},after(){},running(){},read:async()=>c.input,write(text){terminal+=text;}
     26       },true);
     27       assert.equal(g.toTernary(output),c.result);assert.equal(terminal,c.terminal);
     28       cases.push({key:JSON.stringify([c.export,c.arguments,c.input,c.result,c.terminal]),...g.stats});
     29     }
     30     result[name]={hash:demo.hash,bytes:bytes.length,cases};
     31   }
     32   return {compiler:data.compilerBundleSha256,demos:result};
     33 }
     34 const before=await measure(resolve(process.argv[2])),after=await measure(current),summary={};
     35 for(const [name,old] of Object.entries(before.demos)){
     36   const next=after.demos[name];let workBefore=0,workAfter=0,allocationsBefore=0,allocationsAfter=0;
     37   for(const c of old.cases){
     38     const n=next.cases.find(n=>n.key===c.key);assert.ok(n,`missing independent reference case: ${name}`);
     39     workBefore+=c.work;workAfter+=n.work;allocationsBefore+=c.allocations;allocationsAfter+=n.allocations;
     40   }
     41   summary[name]={commonCases:old.cases.length,bytesBefore:old.bytes,bytesAfter:next.bytes,
     42     workBefore,workAfter,allocationsBefore,allocationsAfter};
     43 }
     44 console.log(JSON.stringify({summary,before,after},null,2));