【问题标题】:How to find a particular object in DevTools memory snapshot if the type of the object is just "Object"?如果对象的类型只是“对象”,如何在 DevTools 内存快照中找到特定对象?
【发布时间】:2019-10-12 04:32:31
【问题描述】:

queryObjects 函数返回给定原型的实例。 我想检查这些实例的保留者。为此,我需要在 devtools 内存快照中找到它们。这些实例类型之一是“对象”,因此按类类型搜索没有帮助。他们太多了。

如何在快照中找到该特定实例?

【问题讨论】:

    标签: javascript debugging memory-leaks google-chrome-devtools


    【解决方案1】:

    如果可以修改这些对象,您可以尝试以下技巧。

    将从 queryObjects 获得的数组存储到一个临时变量中。您可以通过上下文菜单进行操作。然后运行以下代码给每个对象一个唯一的 id:

    temp1.forEach((t, i) => t.__id = String(i))
    

    然后拍摄堆快照。现在每个对象都应该可以通过 __id 字符串来识别。

    【讨论】:

    • 问题是我想找到类型为“对象”的那个。为此,我需要浏览分组为“对象”的对象列表,但即使我只查看最新的对象,仍有许多对象需要一一检查。
    • 如果你知道你在 JS 端寻找哪个对象,你可以在里面放一个大字符串。然后,一旦通过保留大小对堆快照进行排序,对象应该会弹出到顶部。
    【解决方案2】:

    添加显式字符串属性,例如let o = {type:'myType'} 然后在快照中使用ctrl+F

    保留器是您所有的 o 对象。

    【讨论】:

      【解决方案3】:

      很难将queryObjects 返回的普通“对象”与堆快照中的所有普通对象区分开来

      这是我为“标记”对象所做的工作,以便我可以轻松区分它们:

      1. 创建一个可以在开发工具中轻松找到的TaggedItem
      2. 创建要调用的包装函数来代替queryObjects
      3. 包装函数将返回值保存在 WeakMap
      • 关键是原始返回值
      • 值为TaggedItem
      • 当原始值不再保留在任何地方时 - 它会自动从WeakMap 垃圾收集
      queryObjects 上应用装饰器
      function queryObjects { /* Implementation */ }
      
      // or process.env.NODE_ENV == 'development'
      if (__DEV__) {
        export default wrapWithObjectTagging(queryObjects);
      }
      else {
        export default queryObjects;
      }
      
      装饰器实现
      function wrapWithObjectTagging(func) {
        function withObjectTagging(...args) {
           const originalReturnValue = func.apply(this, args);
      
           /* We're using Promise.resolve in case the original function returns a promise */
           Promise.resolve(originalReturnValue)
             .then((data) => {
               // Weak map keys can be objects only
               if (typeof data == 'object') {
                 const tag = new TaggedItem(data);
                 taggedItems.set(data, tag);
               }
           });
      
           return originalReturnValue;
        }
      
        return withObjectTagging;
      }
      
      /**
       * Capture tags in a weak map
       * When the original object (key) is no longer used anywhere in app - the data (TaggedItem)
       * is free for garbage collection and removed
       * Using dev tools we see which TaggedItems are still retained and what's using them - preventing GC
       * @type {WeakMap<object, TaggedItem>}
       */
      const taggedItems = new WeakMap();
      
      /**
       * Class instances are easily tracked by Dev tools memory snapshots
       * Wrapping a result with such instance allows us to track it without
       * incurring extra weight
       */
      class TaggedItem {
        constructor(data) {
          // This ref helps us inspect what is retaining the original data
          this.ref = data;
      
          /* This is not really necessary but makes the TaggedItem represent 
             Retained Memory more accurately */
          Object.assign(this, data);    
        }
      }
      

      TaggedItem 直接引用原始数据,但由于没有引用 TaggedItem - 我们从不公开它 - 它不会阻止 WeakMap 垃圾收集原始数据和捕获的 TaggedItem


      以下是 Chrome 开发工具中的工作示例:

      1. 拍摄堆快照
      2. 搜索对象类名(TaggedItem)
      3. 选择一个项目
      4. 查看保持器
      例子

      • 我们正在观察TaggedItem
      • 它由另一个使用原始数据的对象的report 属性保留

      更简单的方法是在原始对象上附加一个键

      通过附加自定义字段进行装饰
      function wrapWithObjectTagging(func) {
        function withObjectTagging(...args) {
           const originalReturnValue = func.apply(this, args);
           if (typeof originalReturnValue == 'object') {
             originalReturnValue.__tag = new TaggedItem();
           }
      
           return originalReturnValue;
        }
      
        return withObjectTagging;
      }
      
      class TaggedItem {}
      

      这样您仍然可以在开发工具中按TaggedItem 进行过滤,并查看保留了TaggedItem 和父对象的内容

      第一种方法可以更好地估计总保留内存,而简单的方法只允许您跟踪保留原始内存的内容

      【讨论】:

        猜你喜欢
        • 2011-10-16
        • 2022-11-18
        • 2022-11-19
        • 2021-06-05
        • 1970-01-01
        • 2022-08-15
        • 1970-01-01
        • 2017-04-22
        • 2015-02-08
        相关资源
        最近更新 更多