defer starting of minions unless threading is enabled

This commit is contained in:
Stewart Allen 2022-02-24 13:47:26 -05:00
commit 07e898f053
4 changed files with 120 additions and 86 deletions

View file

@ -15,9 +15,9 @@
* `C` allow loading of workspaces from url on page load
* `C` properly import profiles attached to devices
* `C` improved routing on "fast" layers & layers with multiple islands
* `C` start/stop minions depending on whether threading enabled
* `P` refactor slicers to use single improved slice core (cnc tbd)
* `P` template vars: nozzles used and layers until next use (IDEX)
* `-` start/stop minions depending on whether threading enabled
* `-` workflow to edit in M:T and bounce back / replace vertices
* `-` abstract file loading (onshape import, mesh replace, etc)
* `-` tighten export dialogs (reduce size for smaller screens)

View file

@ -31,8 +31,7 @@ const { codec } = kiri;
const { time } = util;
const POLY = polygons;
let qtpi = Math.cos(Math.PI/4),
debug = self.debug === true,
let debug = self.debug === true,
ccvalue = this.navigator ? navigator.hardwareConcurrency || 0 : 0,
concurrent = self.Worker && ccvalue > 3 ? ccvalue - 1 : 0,
current = self.worker = {
@ -53,30 +52,15 @@ self.alert = function(o) {
console.log(o);
};
// start concurrent workers (minions)
if (concurrent) {
function minhandler(msg) {
let data = msg.data;
let seq = data.seq;
let fn = minifns[seq];
if (!fn) {
throw `missing dispatch ${seq}`;
}
delete minifns[seq];
fn(data);
function minhandler(msg) {
let data = msg.data;
let seq = data.seq;
let fn = minifns[seq];
if (!fn) {
throw `missing dispatch ${seq}`;
}
for (let i=0; i < concurrent; i++) {
let _ = debug ? '_' : '';
let minion = new Worker(`/code/kiri_pool.js?${_}${self.kiri.version}`);
minion.onmessage = minhandler;
minion.postMessage({
cmd: "label",
name: `#${i}`
});
minions.push(minion);
}
console.log(`kiri | init pool | ${gapp.version || "rogue"} | ${concurrent + 1}`);
delete minifns[seq];
fn(data);
}
// for concurrent operations
@ -84,7 +68,28 @@ const minwork =
kiri.minions = {
concurrent,
union: function(polys, minarea) {
start() {
if (minions.length || !concurrent) {
return;
}
for (let i=0; i < concurrent; i++) {
let _ = debug ? '_' : '';
let minion = new Worker(`/code/kiri_pool.js?${_}${self.kiri.version}`);
minion.onmessage = minhandler;
minion.postMessage({ cmd: "label", name: `#${i}` });
minions.push(minion);
}
console.log(`kiri | init pool | ${gapp.version || "rogue"} | ${concurrent + 1}`);
},
stop() {
for (let minion of minions) {
minion.terminate();
}
minions.length = 0;
},
union(polys, minarea) {
return new Promise((resolve, reject) => {
if (concurrent < 2 || polys.length < concurrent * 2 || POLY.points(polys) < concurrent * 50) {
resolve(POLY.union(polys, minarea, true));
@ -111,7 +116,7 @@ kiri.minions = {
});
},
fill: function(polys, angle, spacing, output, minLen, maxLen) {
fill(polys, angle, spacing, output, minLen, maxLen) {
return new Promise((resolve, reject) => {
if (concurrent < 2) {
resolve(POLY.fillArea(polys, angle, spacing, [], minLen, maxLen));
@ -135,7 +140,7 @@ kiri.minions = {
});
},
clip: function(slice, polys, lines) {
clip(slice, polys, lines) {
return new Promise((resolve, reject) => {
if (concurrent < 2) {
reject("concurrent clip unavaiable");
@ -159,7 +164,7 @@ kiri.minions = {
});
},
sliceZ: function(z, points, options) {
sliceZ(z, points, options) {
return new Promise((resolve, reject) => {
if (concurrent < 2) {
reject("concurrent slice unavaiable");
@ -188,12 +193,12 @@ kiri.minions = {
});
},
queue: function(work, ondone, direct) {
queue(work, ondone, direct) {
minionq.push({work, ondone, direct});
minwork.kick();
},
kick: function() {
kick() {
if (minions.length && minionq.length) {
let qrec = minionq.shift();
let minion = minions.shift();
@ -208,7 +213,7 @@ kiri.minions = {
}
},
wasm: function(enable) {
wasm(enable) {
for (let minion of minions) {
minion.postMessage({
cmd: "wasm",
@ -224,18 +229,28 @@ console.log(`kiri | init work | ${gapp.version || "rogue"}`);
const dispatch =
kiri.server =
kiri.worker = {
pool_start(data, send) {
minwork.start();
send.done({});
},
pool_stop(data, send) {
minwork.stop();
send.done({});
},
group: wgroup,
cache: wcache,
decimate: function(data, send) {
decimate(data, send) {
let { vertices, options } = data;
vertices = new Float32Array(vertices),
vertices = base.pointsToVertices(base.verticesToPoints(vertices, options));
send.done(vertices);
},
heal: function(data, send) {
heal(data, send) {
let { vertices, refresh } = data;
let mesh = new base.Mesh({vertices}).heal();
if (mesh.newFaces || refresh) {
@ -246,12 +261,12 @@ kiri.worker = {
}
},
snap: function(data, send) {
snap(data, send) {
current.snap = data;
send.done();
},
png: function(data, send) {
png(data, send) {
if (current.snap) {
let sws = current.snap.url;
let b64 = atob(sws.substring(sws.indexOf(',') + 1));
@ -265,7 +280,7 @@ kiri.worker = {
}
},
clear: function(data, send) {
clear(data, send) {
// current.snap = null;
current.print = null;
dispatch.group = wgroup = {};
@ -275,7 +290,7 @@ kiri.worker = {
},
// widget sync
sync: function(data, send) {
sync(data, send) {
if (data.valid) {
// remove widgets not present in valid list
for (let key in wcache) {
@ -311,7 +326,7 @@ kiri.worker = {
send.done(data.id);
},
rotate: function(data, send) {
rotate(data, send) {
let { settings } = data;
if (!settings.device.bedBelt) {
return send.done({});
@ -365,7 +380,7 @@ kiri.worker = {
send.done({});
},
unrotate: function(data, send) {
unrotate(data, send) {
let { settings } = data;
if (!settings.device.bedBelt) {
return send.done({});
@ -387,7 +402,7 @@ kiri.worker = {
send.done({});
},
slice: function(data, send) {
slice(data, send) {
send.data({update:0.001, updateStatus:"slicing"});
current.print = null;
@ -425,7 +440,7 @@ kiri.worker = {
});
},
sliceAll: function(data, send) {
sliceAll(data, send) {
const { settings } = data;
const { mode } = settings;
const driver = kiri.driver[mode];
@ -437,7 +452,7 @@ kiri.worker = {
send.done({done: true});
},
prepare: function(data, send) {
prepare(data, send) {
// create widget array from id:widget cache
const widgets = Object.values(wcache);
@ -477,7 +492,7 @@ kiri.worker = {
}, state.zeros);
},
export: function(data, send) {
export(data, send) {
const mode = data.settings.mode;
const driver = kiri.driver[mode];
@ -509,7 +524,7 @@ kiri.worker = {
});
},
colors: function(data, send) {
colors(data, send) {
const { colors, max } = data;
const colorMap = {};
colors.forEach(color => {
@ -518,7 +533,7 @@ kiri.worker = {
send.done(colorMap);
},
parse: function(args, send) {
parse(args, send) {
const { settings, code, type } = args;
const origin = settings.origin;
const offset = {
@ -547,7 +562,7 @@ kiri.worker = {
});
},
parse_svg: function(parsed, send) {
parse_svg(parsed, send) {
parsed.forEach(layer => {
layer.forEach(out => {
const { x, y, z } = out.point;
@ -561,7 +576,7 @@ kiri.worker = {
send.done({parsed: codec.encode(layers)});
},
config: function(data, send) {
config(data, send) {
const update = {};
if (data.base) {
update.base = data.base;
@ -578,7 +593,7 @@ kiri.worker = {
send.done({config: update});
},
image2mesh: function(info, send) {
image2mesh(info, send) {
let img = new png.PNG();
img.parse(info.png, (err, output) => {
let { width, height, data } = output;
@ -801,7 +816,7 @@ kiri.worker = {
});
},
zip: function(data, send) {
zip(data, send) {
let { files } = data;
let zip = new JSZip();
for (let file of files) {
@ -819,7 +834,7 @@ kiri.worker = {
});
},
wasm: function(data, send) {
wasm(data, send) {
if (data.enable) {
wasm_ctrl.enable();
} else {

View file

@ -54,7 +54,17 @@ function send(fn, data, onreply, zerocopy) {
const client = exports({
send: send,
newWorker: function() {
pool: {
start() {
send("pool_start", {}, noop);
},
stop() {
send("pool_stop", {}, noop);
}
},
newWorker() {
if (self.createWorker) {
return self.createWorker();
} else {
@ -63,7 +73,7 @@ const client = exports({
}
},
isBusy: function() {
isBusy() {
let current = 0;
for (let rec of Object.values(running)) {
@ -72,7 +82,7 @@ const client = exports({
return current > 0;
},
restart: function() {
restart() {
// prevent re-entry from cancel callback
if (restarting) {
return;
@ -119,40 +129,40 @@ const client = exports({
restarting = false;
},
decimate: function(vertices, options, callback) {
decimate(vertices, options, callback) {
let alert = kiri.api.show.alert('processing model', 1000);
vertices = vertices.buffer.slice(0);
send("decimate", {vertices, options}, function(output) {
send("decimate", {vertices, options}, (output) => {
kiri.api.hide.alert(alert);
callback(output);
});
},
heal: function(vertices, callback, refresh) {
send("heal", {vertices, refresh}, function(output) {
heal(vertices, callback, refresh) {
send("heal", {vertices, refresh}, (output) => {
callback(output);
});
},
config: function(obj) {
send("config", obj, function(reply) { });
config(obj) {
send("config", obj, noop);
},
clear: function() {
clear() {
syncd = {};
send("clear", {}, function(reply) { });
send("clear", {}, noop);
},
snap: function(data) {
send("snap", data, function(reply) { });
snap(data) {
send("snap", data, noop);
},
png: function(data, ondone) {
png(data, ondone) {
send("png", data, ondone);
},
// widget sync
sync: function(widgets) {
sync(widgets) {
if (!widgets) {
widgets = kiri.api.widgets.all();
}
@ -177,7 +187,7 @@ const client = exports({
});
},
rotate: function(settings, callback) {
rotate(settings, callback) {
send("rotate", { settings }, reply => {
if (reply.group) {
for (let widget of kiri.Widget.Groups.forid(reply.group)) {
@ -189,7 +199,7 @@ const client = exports({
});
},
unrotate: function(settings, callback) {
unrotate(settings, callback) {
send("unrotate", { settings }, reply => {
if (reply.group) {
for (let widget of kiri.Widget.Groups.forid(reply.group)) {
@ -201,12 +211,12 @@ const client = exports({
});
},
slice: function(settings, widget, callback) {
slice(settings, widget, callback) {
send("slice", {
id: widget.id,
anno: widget.annotations(),
settings: settings
}, function(reply) {
}, reply => {
callback(reply);
if (reply.done || reply.error) {
// in belt mode, slicing modifies a widget and requires re-sync
@ -217,12 +227,12 @@ const client = exports({
});
},
sliceAll: function(settings, callback) {
sliceAll(settings, callback) {
send("sliceAll", { settings }, callback);
},
prepare: function(settings, update, done) {
send("prepare", { settings }, function(reply) {
prepare(settings, update, done) {
send("prepare", { settings }, reply => {
if (reply.progress) {
update(reply.progress, reply.message, reply.layer);
}
@ -235,8 +245,8 @@ const client = exports({
});
},
export: function(settings, online, ondone) {
send("export", { settings }, function(reply) {
export(settings, online, ondone) {
send("export", { settings }, reply => {
if (reply.line) {
online(reply.line);
}
@ -252,13 +262,13 @@ const client = exports({
});
},
colors: function(colors, max, done) {
send("colors", { colors, max }, function(reply) {
colors(colors, max, done) {
send("colors", { colors, max }, reply => {
done(reply);
});
},
parse: function(args, progress, done) {
parse(args, progress, done) {
// have to do this client side because DOMParser is not in workers
if (args.type === 'svg') {
const { settings, code, type } = args;
@ -269,14 +279,14 @@ const client = exports({
z: origin.z
};
const output = kiri.newPrint().parseSVG(code, offset);
send("parse_svg", output, function(reply) {
send("parse_svg", output, reply => {
if (reply.parsed) {
done(kiri.codec.decode(reply.parsed));
}
});
return;
}
send("parse", args, function(reply) {
send("parse", args, reply => {
if (reply.progress) {
progress(reply.progress);
}
@ -286,7 +296,7 @@ const client = exports({
});
},
image2mesh: function(data, progress, output) {
image2mesh(data, progress, output) {
send("image2mesh", data, reply => {
if (reply.progress) {
progress(reply.progress);
@ -297,7 +307,7 @@ const client = exports({
}, [ data.png ]);
},
zip: function(files, progress, output) {
zip(files, progress, output) {
send("zip", {files}, reply => {
if (reply.percent !== undefined) {
progress(reply);
@ -307,7 +317,7 @@ const client = exports({
});
},
wasm: function(enable) {
wasm(enable) {
send("wasm", {enable}, reply => {
// console.log({wasm_worker_said: reply});
});

View file

@ -155,6 +155,15 @@ gapp.register("kiri.init", [], (root, exports) => {
api.platform.update_top_z();
}
function setThreaded(bool) {
if (bool) {
kiri.client.pool.start();
} else {
kiri.client.pool.stop();
}
return bool;
}
function booleanSave() {
let control = settings().controller;
let isDark = control.dark;
@ -183,7 +192,7 @@ gapp.register("kiri.init", [], (root, exports) => {
control.exportPreview = ui.exportPreview.checked;
control.decimate = ui.decimate.checked;
control.healMesh = ui.healMesh.checked;
control.threaded = ui.threaded.checked;
control.threaded = setThreaded(ui.threaded.checked);
control.assembly = ui.assembly.checked;
control.ortho = ui.ortho.checked;
control.devel = ui.devel.checked;
@ -2550,7 +2559,7 @@ gapp.register("kiri.init", [], (root, exports) => {
ui.autoSave.checked = control.autoSave;
ui.decimate.checked = control.decimate;
ui.healMesh.checked = control.healMesh;
ui.threaded.checked = control.threaded;
ui.threaded.checked = setThreaded(control.threaded);
ui.assembly.checked = control.assembly;
ui.ortho.checked = control.ortho;
ui.devel.checked = control.devel;