Troika: Warnung „Große Anzahl offener WorkerModule-Anforderungen, einige werden möglicherweise nicht zurückgegeben“.

Erstellt am 30. März 2021  ·  14Kommentare  ·  Quelle: protectwise/troika

Hallo, ich sehe eine große Anzahl von Warnungen, die von troika-worker.utils.esm.js mit dieser Nachricht kommen.

Screen Shot 2021-03-29 at 8 19 42 PM

Alles scheint aber gut zu funktionieren

irgendeine Idee?

Alle 14 Kommentare

Hmm, diese Warnung wird erst ausgelöst, wenn >1000 offene Worker-Anfragen vorliegen. Haben Sie sehr viele Textinstanzen?

Ich tue es, aber nicht über 1000 (zumindest nicht absichtlich)

eher ein paar hundert

Hier ist, was ich rendere

Screen Shot 2021-03-30 at 11 03 39 AM

Aber was sagen Sie damit, dass es vielleicht einen Fehler auf meiner Seite gibt, bei dem ich mehr Instanzen erstelle, als ich tatsächlich brauche, und sobald ich die 1000-Zählung überschreite, fängt es an, einen Fehler zu werfen?

Ich habe Instanzen ohne Inhalt auf .visible = false gesetzt

aber ich denke, das bedeutet immer noch, dass die Instanz existiert

würden Sie empfehlen, anstatt die .visible-Prop zu verwenden, um nicht verwendete Instanzen vollständig zu entfernen?

Ahh, das könnte es erklären. Alle Aufrufe von .sync() werden weiterhin im Hintergrund an den Worker ausgegeben, selbst wenn visible:false , und sie häufen sich.

Ich denke, ich persönlich würde mich dafür entscheiden, die Labels bei Bedarf zu erstellen/entsorgen oder zumindest .sync()-Aufrufe für versteckte zu verhindern. Diese Worker-Anfragen verwenden alle denselben Worker. Wenn er also damit beschäftigt ist, versteckte Labels zu verarbeiten, kann dies die Verarbeitung Ihrer sichtbaren Labels verzögern.

Ich mache jedoch einige Annahmen, da ich Ihren genauen LabelView-Code nicht gesehen habe. Es ist immer noch möglich, dass es einen Fehler auf meiner Seite gibt, also LMK, was Sie finden.

Habe gerade versucht, .sync() nur aufzurufen, wenn .visible === true

aber immer noch die Warnungen

Wenn ich stattdessen nur Instanzen für sichtbare Objekte erstelle und unbenutzte lösche, verschwinden die Warnungen

Hmm, Text selbst ruft nur sync() in onBeforeRender auf, was _nicht_ ausgelöst werden sollte, wenn visible=false.

Ist Ihr LabelView-Wrapper-Code überall verfügbar, wo ich einen Blick darauf werfen kann?

Es ist Teil eines Closed-Source-Projekts

aber hier ist die relevante Klasse, die ausreichen könnte

import {Mesh, MeshBasicMaterial} from "three";
import R from "../../../../../../../../../../resources/Namespace";
import BaseView, {ViewType} from "./BaseView";
import {Text} from "troika-three-text";
import {GeometryInstances} from "../instances/GeometryInstances";
import {MaterialInstances} from "../instances/MaterialInstances";

export enum TextAlign {
    left = "left",
    right = "right",
    center = "center",
    justify = "justify",
}

export enum HorizontalAlign {
    left = "left",
    right = "right",
    center = "center",
}

export enum VerticalAlign {
    top = "top",
    topBaseline = "top-baseline",
    middle = "middle",
    bottomBaseline = "bottom-baseline",
    bottom = "bottom",
}

export interface ILabelData {
    content: string;
    fontFace?: string;
    fontSize?: number;
    alignment?: TextAlign;
    horizontalAlign?: HorizontalAlign;
    verticalAlign?: VerticalAlign;
    color?: string;
    opacity?: number;
    backgroundColor?: string;
    highlightable: boolean;
}

export default class LabelView extends BaseView {
    get viewObject() {
        return this._viewObject as any;
    }

    get content() {
        return this.textMesh.text;
    }

    set content(content: string) {
        if (content !== this.textMesh.text) {
            this.textMesh.text = content;
            this.textMesh.visible = !!content;

            this.syncIfVisible();
        }
    }

    private syncIfVisible() {
        // Better for perf: https://github.com/protectwise/troika/issues/112
        if (this.textMesh?.text && this.textMesh?.visible && this._isVisible) {
            this.textMesh.sync();
        }
    }

    set textAlign(alignment: TextAlign) {
        this.textMesh.textAlign = alignment;
        this.syncIfVisible();
    }

    set horizontalAlign(alignment: HorizontalAlign) {
        this.textMesh.anchorX = alignment;
        this.syncIfVisible();
    }

    set verticalAlign(alignment: VerticalAlign) {
        this.textMesh.anchorY = alignment;
        this.syncIfVisible();
    }

    private backgroundMesh: Mesh | undefined;
    private readonly textMesh: any;
    private readonly foregroundColor: string;
    private highlightable: boolean;

    constructor(labelData: ILabelData) {
        super(ViewType.Label);

        this.foregroundColor = labelData.color || R.colors.elements.labels.foreground;

        this.highlightable = labelData.highlightable;

        if (labelData.backgroundColor) {
            this.textMesh = this.createTextMesh(
                labelData.content,
                labelData.fontFace,
                labelData.fontSize,
                labelData.alignment,
                labelData.horizontalAlign,
                labelData.verticalAlign,
                this.foregroundColor,
                labelData.opacity,
                1);

            this.textMesh.addEventListener("synccomplete", () => {
                if (this.backgroundMesh) {
                    this._viewObject.remove(this.backgroundMesh);
                }

                if (this.textMesh.text) {
                    const bounds = this.textMesh.textRenderInfo.blockBounds;
                    this.backgroundMesh =
                        this.createBackgroundBox(bounds[0], bounds[1], bounds[2], bounds[3], 0);
                    this._viewObject.add(this.backgroundMesh);
                }
            });

        } else {
            this.textMesh = this.createTextMesh(
                labelData.content,
                labelData.fontFace,
                labelData.fontSize,
                labelData.alignment,
                labelData.horizontalAlign,
                labelData.verticalAlign,
                this.foregroundColor,
                labelData.opacity,
                0);
        }

        this.syncIfVisible();

        this._viewObject.add(this.textMesh);
    }

    public onFrameRendered(elapsedTime: number) {
        if (this.highlightable) {
            this.setLabelHighlightState();
        }
    }

    private setLabelHighlightState() {
        const labelMaterial = this.textMesh.material as MeshBasicMaterial;
        if (this._isHighlighted) {
            labelMaterial.color.set(R.colors.elements.labels.highlighted);
        } else {
            labelMaterial.color.set(this.foregroundColor);
        }
    }

    private createTextMesh(content: string,
                           fontFace = R.layout.labels.font_face.regular,
                           fontSize = R.layout.labels.font_size,
                           textAlign = TextAlign.center,
                           horizontalAlign = HorizontalAlign.center,
                           verticalAlign = VerticalAlign.middle,
                           color: string,
                           opacity = 1,
                           zLevel: number) {
        const labelMesh = new Text();

        labelMesh.font = fontFace;
        labelMesh.text = content || "";
        labelMesh.fontSize = fontSize;
        labelMesh.position.z = zLevel;
        labelMesh.color = color;
        labelMesh.textAlign = textAlign;
        labelMesh.anchorX = horizontalAlign;
        labelMesh.anchorY = verticalAlign;

        labelMesh.material.opacity = opacity;
        labelMesh.name = "LabelView";

        return labelMesh;
    }

    private createBackgroundBox(startX: number, startY: number, endX: number, endY: number, zLevel: number) {
        const paddingLeft = 1;
        const paddingRight = 2;
        const paddingTop = 1;
        const paddingBottom = 0;

        const width = Math.abs(startX) + Math.abs(endX) + paddingLeft + paddingRight;
        const height = Math.abs(startY) + Math.abs(endY) + (paddingTop + paddingBottom);

        const geometry = GeometryInstances.getInstance().getPlaneGeometryInstance(width, height);
        const material = MaterialInstances.getInstance().backgroundColorMaterial;
        const mesh = new Mesh(geometry, material);

        const posX = ((startX + endX) / 2) + (paddingLeft / 4);
        const posY = ((startY + endY) / 2) - (paddingBottom);

        // The z level of element in accordance with standards defined in resources
        mesh.position.set(posX, posY, zLevel);
        mesh.name = "LabelBackgroundBox";

        return mesh;
    }
}

Hmm, meine Vermutung wäre, dass syncIfVisible() aufgerufen wird, bevor .visible auf false gesetzt wird, aber es ist schwer zu sagen, ohne zu wissen, wie Ihr Ansichtssystem funktioniert.

Etwas anderes, das mir auffällt, ist, dass Sie syncIfVisible-Aufrufe nach jeder einzelnen Eigenschaftsänderung (content, textAlign, horizontalAlign usw.) ausgeben, wodurch mehr Aufrufe an den Worker als nötig ausgegeben werden. Wenn Ihr Ansichtssystem über einen Lebenszyklus verfügt, in dem Sie einen einzelnen Synchronisierungsaufruf ausführen können, nachdem alle einzelnen Eigenschaften festgelegt wurden, wäre dies viel besser.

Nach dem, was Sie beschrieben haben, verhält sich diese Warnung meiner Meinung nach wie erwartet. es hat ein Leistungsproblem richtig hervorgehoben. Ich schließe dieses Thema; Fühlen Sie sich frei, es wieder zu öffnen, wenn Sie anderer Meinung sind. Danke!

Ich komme nur darauf zurück

Es stellt sich also heraus, dass ich leicht über 1000 Textinstanzen in meiner Szene habe. Aber es sind einfach nicht alle gleichzeitig sichtbar

Viele von ihnen erscheinen nur, wenn Sie mit der Maus über bestimmte Objekte fahren

Daher frage ich mich, wie ich hier am besten vorgehe:

  1. Instanzen nur für sichtbaren Text erstellen und dann aushängen, sobald er unsichtbar wird?
  2. stattdessen ThreeJS CSS-Objekte verwenden?

Ich persönlich würde mich für die erste Option entscheiden. Ich könnte mich irren, aber ich glaube nicht, dass es einen Vorteil bringt, all diese versteckten Label-Objekte im Szenendiagramm zu haben.

Habe es

Ich muss in der Lage sein, sie schnell anzuzeigen, wenn ich mit der Maus über Objekte schwebe

Würden Sie empfehlen, sie nach Gebrauch einfach zu zerstören und beim Hover neue zu erstellen oder sie stattdessen einfach aus der Dreier-Szene zu entfernen?

Ehrlich gesagt glaube ich nicht, dass es so oder so einen merklichen Unterschied geben wird. Ich würde mit dem beginnen, was am einfachsten zu verwalten und zu optimieren ist, nur wenn Sie ein Problem bemerken.

Persönlich habe ich den Create/Destroy-Ansatz oft verwendet, und er ist immer sehr bissig für mich.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

drcmda picture drcmda  ·  11Kommentare

stephencorwin picture stephencorwin  ·  39Kommentare

Ocelyn picture Ocelyn  ·  13Kommentare

asbjornlystrup picture asbjornlystrup  ·  7Kommentare

lojjic picture lojjic  ·  18Kommentare