Как увидеть достижимость указанного c JS объекта - PullRequest
0 голосов
/ 19 февраля 2020

У меня есть экземпляр WebAssembly, который создает контекст WebGL2. В идеале, при выходе из той части страницы, где отображается контекст, я хотел бы уничтожить контекст и позволить модулю и текстурам и т. Д. c. быть мусором Проблема в том, что я не могу отследить, что сохраняет ссылку на объект WebAssembly.

Как определить все места (свойства, замыкания) со ссылкой на этот объект? (Chrome devtools или другие легкодоступные инструменты)

1 Ответ

1 голос
/ 19 февраля 2020

Я не уверен, если это ответ на ваш вопрос или нет, но ... в ваших данных вы написали

Я хотел бы уничтожить контекст и позволить модулю и текстуры и др. c. быть сборщиком мусора.

Сбор текстур и т.д. c сборка мусора - неправильный способ очистки ресурсов WebGL. См. Собирается ли мусор объектов WebGL?

Если вы знаете, когда WebAssembly выполняется, вы можете отслеживать ресурсы из JavaScript, расширяя контекст. Пример

const allWebGL2ContextsResources = new Map();

HTMLCanvasElement.prototype.getContext = function(origFn) {
  return function(type, attribs) {
    const ctx = origFn.call(this, type, attribs);
    if (type === 'webgl2') {
      if (!allWebGL2ContextsResources.has(ctx)) {
        allWebGL2ContextsResources.set(ctx, new Set());
      }
    }
    return ctx;
  };
}(HTMLCanvasElement.prototype.getContext);

const types = ['Buffer', 'Texture', 'Renderbuffer', 'Framebuffer', 'Shader', 'Program', 'Sampler', 'TransformFeedback'];
for (const type of types) {
  const createName = `create${type}`;
  const deleteName = `delete${type}`;

  WebGL2RenderingContext.prototype[createType] = function(origFn) {
    return function(...args) {
      const obj = orignFn.call(this, ...args);
      allWebGL2ContextsResources.get(this).add(obj);
      return obj;
    };
  }(WebGL2RenderingContext.prototype[createType]);

  WebGL2RenderingContext.prototype[deleteType] = function(origFn) {
    return function(obj) {
      const obj = origFn.call(this, obj);
      allWebGL2ContextsResources(this).delete(obj);
    };
  }(WebGL2RenderingContext.prototype[deleteType]);
}

Учитывая, что при запуске кода WebAssembly новый контекст WebGL2 будет добавлен в allWebGL2Contexts, чтобы вы могли выполнить разбор копии перед тем, как найти добавленный контекст. Или измените код для генерации события, или для обратного вызова, или для того, что вам нужно для обнаружения контекста.

Когда вы закончите с кодом WebAssembly, вы сможете go просмотреть ресурсы и удалить их. Пример

for (const obj of allWebGL2ContextsResources.get(someContext).entries()) {
  for (const type of types) {
    const Type = `WebGL${type}`;
    if (obj instanceof window[Type]) {
      someContext[`delete${type}`](obj);
      continue;
    }
  }
}
allWebGL2ContextsResources.delete(someContext);

Или вы можете потерять контекст. См. Как очистить и выгрузить контекст холста WebGL из графического процессора после использования?

Если вы используете emscripten, то другой вариант - emscripten уже отслеживает ресурсы, чтобы вы могли измените библиотеку emscripten WebGL2 , чтобы открыть контекст и отслеживание, или добавьте некоторую функцию очистки, чтобы освободить все, что отслеживается, или потерять контекст.

...