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

View file

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

View file

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

View file

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