47 lines
2.5 KiB
JavaScript
47 lines
2.5 KiB
JavaScript
/* Does the batched path have a cliff at N=4..6? Sweep every N through the REAL
|
|||
|
|
service, interleaved A/B so machine load hits both arms equally. */
|
||
|
|
import { fork } from 'child_process';
|
||
|
|
import os from 'os'; import path from 'path';
|
||
|
|
import { fileURLToPath } from 'url';
|
||
|
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||
|
|
const MODELS_DIR = path.join(os.homedir(), 'Library/Application Support/Church Translate Models');
|
||
|
|
const LANGS = ['spa_Latn','por_Latn','fra_Latn','zho_Hans','hat_Latn','hin_Deva','kor_Hang','vie_Latn','arb_Arab'];
|
||
|
|
const TEXT = 'And I want you to understand that God has a plan for your life';
|
||
|
|
|
||
|
|
const child = fork(path.join(__dirname, 'mt-service.js'), [], { stdio: ['ignore','pipe','pipe','ipc'] });
|
||
|
|
child.stderr.on('data', () => {});
|
||
|
|
let seq = 0; const pending = new Map();
|
||
|
|
child.on('message', (m) => {
|
||
|
|
if (m.type === 'ready') { pending.get('ready')(); return; }
|
||
|
|
if (m.type === 'progress' || m.type === 'note') return;
|
||
|
|
const w = pending.get(m.id); if (!w) return; pending.delete(m.id);
|
||
|
|
if (m.type === 'error') w.reject(new Error(m.message));
|
||
|
|
else w.resolve(m.type === 'multi' ? m.texts : m.text);
|
||
|
|
});
|
||
|
|
const send = (p) => new Promise((resolve, reject) => { const id = ++seq; pending.set(id, {resolve,reject}); child.send({...p, id}); });
|
||
|
|
const ready = new Promise(r => pending.set('ready', r));
|
||
|
|
child.send({ type:'load', model:'Xenova/nllb-200-distilled-600M', dtype:'fp32', cacheDir: MODELS_DIR });
|
||
|
|
await ready;
|
||
|
|
|
||
|
|
const one = (t) => send({ type:'translate', text:TEXT, src:'eng_Latn', tgt:t });
|
||
|
|
const many = (ts) => send({ type:'translateMulti', text:TEXT, src:'eng_Latn', tgts:ts });
|
||
|
|
await one('spa_Latn'); await many(['spa_Latn','fra_Latn']);
|
||
|
|
|
||
|
|
const REPS = 3;
|
||
|
|
console.log(' N | serial(med) | batched(med) | speedup | identical');
|
||
|
|
console.log('---+-------------+--------------+---------+----------');
|
||
|
|
for (let n = 1; n <= 9; n++) {
|
||
|
|
const langs = LANGS.slice(0, n);
|
||
|
|
const S = [], B = []; let same = 0, tot = 0;
|
||
|
|
for (let r = 0; r < REPS; r++) {
|
||
|
|
let t = Date.now(); const so = {}; for (const l of langs) so[l] = await one(l); S.push(Date.now()-t);
|
||
|
|
t = Date.now(); const bo = await many(langs); B.push(Date.now()-t);
|
||
|
|
for (const l of langs) { tot++; if (so[l] === bo[l]) same++; }
|
||
|
|
}
|
||
|
|
const med = (a) => a.sort((x,y)=>x-y)[Math.floor(a.length/2)];
|
||
|
|
const s = med(S), b = med(B);
|
||
|
|
console.log(String(n).padStart(2) + ' | ' + (s+'ms').padStart(11) + ' | ' + (b+'ms').padStart(12) +
|
||
|
|
' | ' + ((s/b).toFixed(2)+'x').padStart(7) + ' | ' + same + '/' + tot);
|
||
|
|
}
|
||
|
|
child.kill();
|