Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: slow post message #623

Merged
merged 6 commits into from
Aug 31, 2021
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 24 additions & 19 deletions src/application/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,31 +59,37 @@ export default class ModV {
});

this.$worker.addEventListener("message", e => {
const message = e.data;
const { type } = message;

// if (
// type !== "metrics/SET_FPS_MEASURE" &&
// type !== "modules/UPDATE_ACTIVE_MODULE_PROP" &&
// type !== "beats/SET_BPM" &&
// type !== "beats/SET_KICK" &&
// type !== "tick"
// ) {
// console.log(`⚙️%c ${type}`, "color: red");
// }

if (e.data.type === "tick" && this.ready) {
this.tick(e.data.payload);
return;
}

const message = e.data;
const { type } = message;

if (Array.isArray(message)) {
return;
}
const payload = e.data.payload ? JSON.parse(e.data.payload) : undefined;

// if (
// type !== "metrics/SET_FPS_MEASURE" &&
// type !== "modules/UPDATE_ACTIVE_MODULE_PROP" &&
// type !== "beats/SET_BPM" &&
// type !== "beats/SET_KICK"
// ) {
if (this.debug) {
console.log(`⚙️%c ${type}`, "color: red", payload);
if (type === "commitQueue") {
for (let i = 0; i < payload.length; i++) {
const commit = payload[i];
store.commit(commit.type, commit.payload);
}
} else {
store.commit(type, payload);
}
// }

store.commit(type, payload);
});

const that = this;
Expand All @@ -92,10 +98,9 @@ export default class ModV {
state: store.state,
getters: store.getters,

async commit(...args) {
return await that.$asyncWorker.postMessage(
commit(...args) {
return that.$worker.postMessage(
{
__async: true,
type: "commit",
identifier: args[0],
payload: args[1]
Expand All @@ -104,8 +109,8 @@ export default class ModV {
);
},

async dispatch(...args) {
return await that.$asyncWorker.postMessage(
dispatch(...args) {
return that.$asyncWorker.postMessage(
{
__async: true,
type: "dispatch",
Expand Down
103 changes: 91 additions & 12 deletions src/application/worker/index.worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,42 +9,111 @@ async function start() {
const store = require("./store").default;
const loop = require("./loop").default;
const grabCanvasPlugin = require("../plugins/grab-canvas").default;
const get = require("lodash.get");

const { tick: frameTick } = require("./frame-counter");
const { getFeatures, setFeatures } = require("./audio-features");
// const featureAssignmentPlugin = require("../plugins/feature-assignment");

let interval = store.getters["fps/interval"];

const commitQueue = [];

store.subscribe(mutation => {
const { type, payload } = mutation;
const { type: mutationType, payload: mutationPayload } = mutation;

if (type === "beats/SET_BPM" || type === "fps/SET_FPS") {
store.dispatch("tweens/updateBpm", { bpm: payload.bpm });
if (mutationType === "beats/SET_BPM" || mutationType === "fps/SET_FPS") {
store.dispatch("tweens/updateBpm", { bpm: mutationPayload.bpm });
}

if (type === "beats/SET_KICK" && payload.kick === lastKick) {
if (
mutationType === "beats/SET_KICK" &&
mutationPayload.kick === lastKick
) {
return;
} else if (type === "beats/SET_KICK" && payload.kick !== lastKick) {
lastKick = payload.kick;
} else if (
mutationType === "beats/SET_KICK" &&
mutationPayload.kick !== lastKick
) {
lastKick = mutationPayload.kick;
}

if (type === "fps/SET_FPS") {
if (mutationType === "fps/SET_FPS") {
interval = store.getters["fps/interval"];
}

if (
type === "modules/UPDATE_ACTIVE_MODULE" &&
(payload.key !== "props" || payload.key !== "meta")
mutationType === "modules/UPDATE_ACTIVE_MODULE" &&
(mutationPayload.key !== "props" || mutationPayload.key !== "meta")
) {
return;
}

const {
inputs: { inputs, inputLinks }
} = store.state;

// Update mutation type Input Links
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is an input link of type mutation?

Copy link
Member Author

@2xAA 2xAA Aug 19, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are multiple types of input links.

  • all input links
    • Params:
      • inputId
        • String. The ID of the input to link to
      • ?source
        • String. Identifies what created and/or manages this input link
      • ?min
        • Number. Minimum expected value, will scale the incoming value to the input's min/max if min and max are set
      • ?max
        • Number. Maximum expected value, will scale the incoming value to the input's min/max if min and max are set
  • getter
    • ⚠️ updates every frame
    • Reads a getter in the store, possibly with arguments, defined in ?args, and applies that to the input link defined with inputId
    • Params:
      • location
        • String. location of the getter in the store, e.g. meyda/getFeature
      • ?args
        • Array. arguments for a getter that is a function, e.g. ["energy"]
  • mutation
    • Waits for a mutation type, defined with match.type, possibly checks the mutation payload for specific unique parameters, defined on match.?payload, and applies a store value, specified with location, to the input link defined with inputId
    • Params:
      • location
        • String. location of the value to read in the store, e.g. midi.devices[1].channelData[1][144]
      • match
        • Object. Parameters of the mutation to match. Has keys:
          • type
            • String. Mutation type from the store, e.g. midi/WRITE_DATA
          • ?payload
            • Object. Key-value pairs to match in the mutation payload. e.g.
            {
              id: `${id}-${name}-${manufacturer}`,
              channel,
              type
            } 
  • state
    • ⚠️ updates every frame
    • Reads a location in the store and applies that to the input link defined with inputId
    • Params:
      • location
        • String. location of the value to read in the store, e.g. midi.devices[1].channelData[1][144]

state and getter links are updated in loop.js

if (linkType === "getter" && linkArguments) {

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@2xAA thanks for this explanation!

const mutationTypeInputLinks = Object.values(inputLinks).filter(
link => link.type === "mutation"
);
const inputLinksLength = mutationTypeInputLinks.length;
for (let i = 0; i < inputLinksLength; ++i) {
const link = mutationTypeInputLinks[i];
const inputId = link.id;
const bind = inputs[inputId];

const { type, location, data } = bind;

const { type: linkType, location: linkLocation, match } = link;

if (linkType !== "mutation" || match.type !== mutationType) {
2xAA marked this conversation as resolved.
Show resolved Hide resolved
continue;
}

let payloadMatches = false;

if (match.payload) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is match?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const matchPayloadKeys = Object.keys(match.payload);
payloadMatches = matchPayloadKeys.every(key => {
const value = match.payload[key];
return value === mutationPayload[key];
});
} else {
payloadMatches = true;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this true if there is no payload?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because it's possible for mutations to have no payload, or we just want to update when a mutation, e.g. beats/SET_KICK, is committed.

Example here:

this.$modV.store.dispatch("inputs/createInputLink", {
inputId: this.inputId,
type: "mutation",
location: "beats.kick",
match: {
type: "beats/SET_KICK"
},
source: "meyda",
args: [this.feature]
});

}

if (!payloadMatches) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we have no payloadMatch, we continue? Why do we check if the payload is matching anyway? To see if there was a change?

Copy link
Member Author

@2xAA 2xAA Aug 19, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The payload may need to match to check for things like IDs or other unique parameters so we know the correct inputLink will be updated.

If we didn't check for the right ID on the MIDI input links, all MIDI input links would update on any MIDI input which would be wasteful in terms of postMessage.

continue;
}

const value = get(store.state, linkLocation);

if (type === "action") {
store.dispatch(location, { ...data, data: value });
} else if (type === "commit") {
store.commit(location, { ...data, data: value });
}
}

commitQueue.push(mutation);
});

function sendCommitQueue() {
if (commitQueue.length === 0) {
return;
} else {
console.log("commitQueueLength", commitQueue.length);
}

const commits = JSON.stringify(commitQueue);
commitQueue.splice(0, commitQueue.length);

self.postMessage({
type,
payload: JSON.stringify(payload)
type: "commitQueue",
payload: commits
});
});
}

store.dispatch("plugins/add", grabCanvasPlugin);

Expand Down Expand Up @@ -177,6 +246,7 @@ async function start() {
}

function frameActions(delta) {
sendCommitQueue();
self.postMessage({
type: "tick",
payload: delta
Expand Down Expand Up @@ -293,11 +363,20 @@ async function start() {
return JSON.stringify(preset);
}

if (identifier === "groups/REPLACE_GROUP_MODULES") {
2xAA marked this conversation as resolved.
Show resolved Hide resolved
console.log("message recieved");
}

/**
* @todo Don't JSON parse and stringify
*/
const value = await store[type](identifier, payload);

if (identifier === "groups/REPLACE_GROUP_MODULES") {
2xAA marked this conversation as resolved.
Show resolved Hide resolved
console.log("processed store shit");
debugger;
}

if (value) {
return JSON.parse(JSON.stringify(value));
}
Expand Down
15 changes: 14 additions & 1 deletion src/application/worker/loop.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,21 @@ function loop(delta, features, fftOutput) {
location: linkLocation,
args: linkArguments,
min,
max
max,
source
} = link;

const moduleId = store.state.inputs.inputs[inputId].data.moduleId;

if (
2xAA marked this conversation as resolved.
Show resolved Hide resolved
linkType === "mutation" ||
(source === "meyda" &&
moduleId &&
!store.state.modules.active[moduleId].meta.enabled)
) {
continue;
}

let value;

if (linkType === "getter" && linkArguments) {
Expand Down
12 changes: 11 additions & 1 deletion src/application/worker/store/modules/inputs.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ const actions = {
min = 0,
max = 1,
source,
match,
writeToSwap
}
) {
Expand All @@ -52,7 +53,16 @@ const actions = {
return false;
}

const inputLink = { id: inputId, location, type, args, min, max, source };
const inputLink = {
id: inputId,
location,
type,
args,
min,
max,
source,
match
};
if (!writeTo.inputs[inputId]) {
console.warn(
"Did not create inputLink. Could not find input with id",
Expand Down
5 changes: 4 additions & 1 deletion src/components/InputLinkComponents/AudioFeatures.vue
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,11 @@ export default {
if (this.feature === "kick") {
this.$modV.store.dispatch("inputs/createInputLink", {
inputId: this.inputId,
type: "state",
type: "mutation",
location: "beats.kick",
match: {
type: "beats/SET_KICK"
},
source: "meyda",
args: [this.feature]
});
Expand Down
10 changes: 9 additions & 1 deletion src/components/InputLinkComponents/MIDI.vue
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,17 @@ export default {

this.hasLink = await this.$modV.store.dispatch("inputs/createInputLink", {
inputId: this.inputId,
type: "state",
type: "mutation",
source: "midi",
location: `midi.devices['${id}-${name}-${manufacturer}'].channelData['${channel}']['${type}']`,
match: {
type: "midi/WRITE_DATA",
payload: {
id: `${id}-${name}-${manufacturer}`,
channel,
type
}
},
min: 0,
max: 1
});
Expand Down