Skip to content

Commit b48937e

Browse files
committed
#494 factored out the parsing model logic and moved to web worker to dont kill performances
1 parent 6eaae80 commit b48937e

3 files changed

Lines changed: 122 additions & 15 deletions

File tree

webapp/Utils.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ const Utils = {
6161
}
6262

6363
// skip the list element, e.g. "E"!
64-
console.debug(`Skip ${item} at ${nextObject.label}`);
64+
// console.debug(`Skip ${item} at ${nextObject.label}`);
6565
skipped = true;
6666
} else {
6767
skipped = false;

webapp/components/experiments/ExperimentEdit.js

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ import ParameterMenu from './ParameterMenu';
2626
import useStyles from './ExperimentEditStyle';
2727
import * as ExperimentHelper from './ExperimentHelper';
2828
import DialogBox from '../general/DialogBox';
29+
import workerCode from './workers/processExperimentData';
30+
2931
const RANGE_VALUE = 0;
3032
const SUPPORTED_TYPES = [REAL_TYPE.INT, REAL_TYPE.FLOAT, REAL_TYPE.STR, REAL_TYPE.BOOL];
3133
const MAX_TRIALS = 100;
@@ -191,13 +193,13 @@ const ExperimentEdit = (props) => {
191193
const [experimentNameError, setExperimentNameError] = useState('');
192194
const [selectionParams, setSelectionParams] = useState([]);
193195
const [trialNumberErrorDialogOpen, setTrialNumberErrorDialogOpen] = useState({ condition: false, number: 1 });
196+
const [paramsCounter, setParamsCounter] = useState(0);
194197

195198
// Existing Experiment.
196199
const [experiment, setExperiment] = useState(null);
197200
const experiments = useSelector((state) => state.experiments.experiments);
198201

199202
let numberOfTrials = 1;
200-
// const dispatch = useDispatch();
201203
const validateParameter = (param) => {
202204
let updatedParam = param;
203205
if (param.type === LIST) {
@@ -253,20 +255,20 @@ const ExperimentEdit = (props) => {
253255
const getParameters = () => {
254256
ExperimentsApi.getParameters()
255257
.then((params) => {
256-
const flattened = Utils.flatten(params);
257-
const paramKeys = Object.keys(flattened);
258-
259-
const filteredKeys = paramKeys.filter((key) => {
260-
// TODO: avoid to fetch field twice!
261-
const field = Utils.getMetadataField(`netParams.${key}`);
262-
if (field && SUPPORTED_TYPES.includes(field.type)) {
263-
return true;
258+
// eslint-disable-next-line prefer-template
259+
// eslint-disable-next-line no-undef
260+
const worker = new Worker(workerCode);
261+
worker.onmessage = function (e) {
262+
switch (e.data.resultMessage) {
263+
case 'OK':
264+
setSelectionParams(e.data.params.results);
265+
worker.terminate();
266+
break;
267+
default:
268+
console.error('worker processing metadata for autocomplete not working.');
264269
}
265-
return false;
266-
});
267-
268-
console.debug(`Size before ${paramKeys.length}, after: ${filteredKeys.length}`);
269-
setSelectionParams(filteredKeys);
270+
};
271+
worker.postMessage({ message: 'process', params: { data: params, metadata: window.metadata } });
270272
});
271273
};
272274

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
const workerCode = () => {
2+
// eslint-disable-next-line no-undef
3+
self.onmessage = function (event) {
4+
// The object that the web page sent is stored in the event.data property.
5+
const Utils = {
6+
getMetadataField (key, field = null) {
7+
if (key === undefined) {
8+
return null;
9+
}
10+
11+
let currentObject;
12+
let nextObject = event.data.params.metadata;
13+
let skipped = false;
14+
15+
// eslint-disable-next-line no-restricted-syntax
16+
key.split('.').forEach((item) => {
17+
if (
18+
currentObject != null
19+
&& currentObject?.container === true
20+
&& !(item in nextObject)
21+
) {
22+
if (skipped) {
23+
return null;
24+
}
25+
26+
// skip the list element, e.g. "E"!
27+
// console.debug(`Skip ${item} at ${nextObject.label}`);
28+
skipped = true;
29+
} else {
30+
skipped = false;
31+
32+
if (item in nextObject) {
33+
currentObject = nextObject[item];
34+
if ('children' in currentObject) {
35+
nextObject = currentObject.children;
36+
}
37+
} else {
38+
currentObject = null;
39+
}
40+
}
41+
});
42+
43+
if (currentObject) {
44+
return field ? currentObject[field] : currentObject;
45+
}
46+
47+
return null;
48+
},
49+
50+
flatten (obj, path = '') {
51+
if (!(obj instanceof Object)) {
52+
// eslint-disable-next-line no-new-object
53+
const newObj = new Object();
54+
newObj[path.replace(/\.$/g, '')] = obj;
55+
return newObj;
56+
}
57+
58+
return Object.keys(obj).reduce(
59+
(output, key) => (obj instanceof Array
60+
? Object.assign(output, Utils.flatten(obj[key], `${path}[${key}].`))
61+
: Object.assign(output, Utils.flatten(obj[key], `${path + key}.`))),
62+
{},
63+
);
64+
},
65+
};
66+
67+
const REAL_TYPE = {
68+
INT: 'int',
69+
FLOAT: 'float',
70+
BOOL: 'bool',
71+
STR: 'str',
72+
FUNC: 'func',
73+
DICT: 'dict',
74+
DICT_DICT: 'dict(dict)',
75+
};
76+
const SUPPORTED_TYPES = [
77+
REAL_TYPE.INT,
78+
REAL_TYPE.FLOAT,
79+
REAL_TYPE.STR,
80+
REAL_TYPE.BOOL,
81+
];
82+
const { data } = event.data.params;
83+
const flattened = Utils.flatten(data);
84+
const paramKeys = Object.keys(flattened);
85+
const filteredKeys = paramKeys.filter((key) => {
86+
// TODO: avoid to fetch field twice!
87+
const field = Utils.getMetadataField(`netParams.${key}`);
88+
if (field && SUPPORTED_TYPES.includes(field.type)) {
89+
return true;
90+
}
91+
return false;
92+
});
93+
94+
// eslint-disable-next-line no-undef
95+
postMessage({ resultMessage: 'OK', params: { results: filteredKeys } });
96+
};
97+
};
98+
99+
let code = workerCode.toString();
100+
code = code.substring(code.indexOf('{') + 1, code.lastIndexOf('}'));
101+
102+
const blob = new Blob([code], { type: 'application/javascript' });
103+
const workerScript = window.URL.createObjectURL(blob);
104+
105+
export default workerScript;

0 commit comments

Comments
 (0)