BloatView 编辑

BloatView is a tool that shows information about cumulative memory usage and leaks. If it finds leaks, you can use refcount tracing and balancing to discover the root cause.

How to build with BloatView

Build with --enable-debug or --enable-logrefcnt.

How to run with BloatView

The are two environment variables that can be used.

XPCOM_MEM_BLOAT_LOG
If set, this causes a bloat log to be printed on program exit, and each time nsTraceRefcnt::DumpStatistics is called. This log contains data on leaks and bloat (a.k.a. usage).
XPCOM_MEM_LEAK_LOG
This is similar to XPCOM_MEM_BLOAT_LOG, but restricts the log to only show data on leaks.

You can set these environment variables to any of the following values.

  • 1 - log to stdout.
  • 2 - log to stderr.
  • filename - write log to a file.

Reading individual bloat logs

Full BloatView output contains per-class statistics on allocations and refcounts, and provides gross numbers on the amount of memory being leaked broken down by class. Here's a sample of the BloatView output.

== BloatView: ALL (cumulative) LEAK AND BLOAT STATISTICS, tab process 1862
    |<----------------Class--------------->|<-----Bytes------>|<----Objects---->|
    |                                      | Per-Inst   Leaked|   Total      Rem|
  0 |TOTAL                                 |       17     2484|253953338       38|
 17 |AsyncTransactionTrackersHolder        |       40       40|   10594        1|
 78 |CompositorChild                       |      472      472|       1        1|
 79 |CondVar                               |       24       48|    3086        2|
279 |MessagePump                           |        8        8|      30        1|
285 |Mutex                                 |       20       60|   89987        3|
302 |PCompositorChild                      |      412      412|       1        1|
308 |PImageBridgeChild                     |      416      416|       1        1|

The first line tells you the pid of the leaking process, along with the type of process.

Here's how you interpret the columns.

  • The first, numerical column is the index of the leaking class.
  • Class - The name of the class in question (truncated to 20 characters).
  • Bytes Per-Inst - The number of bytes returned if you were to write sizeof(Class). Note that this number does not reflect any memory held onto by the class, such as internal buffers, etc. (E.g. for nsString you'll see the size of the header struct, not the size of the string contents!)
  • Bytes Leaked - The number of bytes per instance times the number of objects leaked: (Bytes Per-Inst) x (Objects Rem). Use this number to look for the worst offenders. (Should be zero!)
  • Objects Total - The total count of objects allocated of a given class.
  • Objects Rem - The number of objects allocated of a given class that weren't deleted. (Should be zero!)

Interesting things to look for:

  • Are your classes in the list? - Look! If they aren't, then you're not using the NS_IMPL_ADDREF and NS_IMPL_RELEASE (or NS_IMPL_ISUPPORTS which calls them) for xpcom objects, or MOZ_COUNT_CTOR and MOZ_COUNT_DTOR for non-xpcom objects. Not having your classes in the list is not ok. That means no one is looking at them, and we won't be able to tell if someone introduces a leak. (See below for how to fix this.)
  • The Bytes Leaked for your classes should be zero! - Need I say more? If it isn't, you should use the other tools to fix it.
  • The number of objects remaining might not be equal to the total number of objects. This could indicate a hand-written Release method (that doesn't use the NS_LOG_RELEASE macro from nsTraceRefcnt.h), or perhaps you're just not freeing any of the instances you've allocated. These sorts of leaks are easy to fix.
  • The total number of objects might be 1. This might indicate a global variable or service. Usually this will have a large number of refcounts.

If you find leaks, you can use refcount tracing and balancing to discover the root cause.

Combining and sorting bloat logs

You can view one or more bloat logs in your browser by running the following program.

perl tools/bloatview/bloattable.pl log1 log2 ... logn > htmlfile

This will produce an HTML file that contains a table similar to the following (but with added JavaScript so you can sort the data by column).

Byte Bloats
NameFileDate
blankblank.txtTue Aug 29 14:17:40 2000
mozillamozilla.txtTue Aug 29 14:18:42 2000
yahooyahoo.txtTue Aug 29 14:19:32 2000
netscapenetscape.txtTue Aug 29 14:20:14 2000

The numbers do not include malloc 'd data such as string contents.

Click on a column heading to sort by that column. Click on a class name to see details for that class.

Class NameInstance SizeBytes allocatedBytes allocated but not freed

blank

mozilla

yahoo

netscape

Total

blank

mozilla

yahoo

netscape

Total

TOTAL

      17544084325561798284041842770976

nsStr

20626160037819001120920179134012955760222760487601328076160360960

nsHashKey

8610568184240024578721134592604543232000536568121634320

nsTextTransformer

548822046908814149361532756342500000000

nsStyleContextData

7362598083253124894403385601413120141312220800-1104094944446016

nsLineLayout

11002200225500402600562100119240000000

nsLocalFile

4245588321992816961272581728720801272424-42473352

The first set of columns, Bytes allocated, shows the amount of memory allocated for the first log file (blank.txt), the difference between the first log file and the second (mozilla.txt), the difference between the second log file and the third (yahoo.txt), the difference between the third log file and the fourth (netscape.txt), and the total amount of memory allocated in the fourth log file. These columns provide an idea of how hard the memory allocator has to work, but they do not indicate the size of the working set.

The second set of columns, Bytes allocated but not freed, shows the net memory gain or loss by subtracting the amount of memory freed from the amount allocated.

The Show Objects and Show References buttons show the same statistics but counting objects or AddRef'd references rather than bytes.

Comparing Bloat Logs

You can also compare any two bloat logs (either those produced when the program shuts down, or written to the bloatlogs directory) by running the following program.

perl tools/bloatview/bloatdiff.pl <previous-log> <current-log>

This will give you output of the form:

Bloat/Leak Delta Report
 Current file:  dist/win32_D.OBJ/bin/bloatlogs/all-1999-10-22-133450.txt
 Previous file: dist/win32_D.OBJ/bin/bloatlogs/all-1999-10-16-010302.txt
 --------------------------------------------------------------------------
 CLASS                     LEAKS       delta      BLOAT       delta
 --------------------------------------------------------------------------
 TOTAL                   6113530       2.79%   67064808       9.18%
 StyleContextImpl         265440      81.19%     283584     -26.99%
 CToken                   236500      17.32%     306676      20.64%
 nsStr                    217760      14.94%    5817060       7.63%
 nsXULAttribute           113048     -70.92%     113568     -71.16%
 LiteralImpl               53280      26.62%      75840      19.40%
 nsXULElement              51648       0.00%      51648       0.00%
 nsProfile                 51224       0.00%      51224       0.00%
 nsFrame                   47568     -26.15%      48096     -50.49%
 CSSDeclarationImpl        42984       0.67%      43488       0.67%

This "delta report" shows the leak offenders, sorted from most leaks to fewest. The delta numbers show the percentage change between runs for the amount of leaks and amount of bloat (negative numbers are better!). The bloat number is a metric determined by multiplying the total number of objects allocated of a given class by the class size. Note that although this isn't necessarily the amount of memory consumed at any given time, it does give an indication of how much memory we're consuming. The more memory in general, the worse the performance and footprint. The percentage 99999.99% will show up indicating an "infinite" amount of leakage. This happens when something that didn't leak before is now leaking.

BloatView and continuous integration

BloatView runs on debug builds for many of the test suites Mozilla has running under continuous integration. If a new leak occurs, it will trigger a test job failure.

BloatView's output file can also show you where the leaked objects are allocated.  To do so, the XPCOM_MEM_LOG_CLASSES environment variable should be set to the name of the class from the BloatView table:

XPCOM_MEM_LOG_CLASSES=MyClass mach mochitest [options]

Multiple class names can be specified by setting XPCOM_MEM_LOG_CLASSES to a comma-separated list of names:

XPCOM_MEM_LOG_CLASSES=MyClass,MyOtherClass,DeliberatelyLeakedClass mach mochitest [options]

Test harness scripts typically accept a --setenv option for specifying environment variables, which may be more convenient in some cases:

mach mochitest --setenv=XPCOM_MEM_LOG_CLASSES=MyClass [options]

For getting allocation stacks in automation, you can add the appropriate --setenv options to the test configurations for the platforms you're interested in.  Those configurations are located in testing/mozharness/configs/.  The most likely configs you'll want to modify are listed below:

  • Linux: unittests/linux_unittest.py
  • Mac: unittests/mac_unittest.py
  • Windows: unittests/win_unittest.py
  • Android: android/androidarm_4_3.py

How to instrument your objects for BloatView

First, if your object is an xpcom object and you use the NS_IMPL_ADDREF and NS_IMPL_RELEASE (or a variation thereof) macro to implement your AddRef and Release methods, then there is nothing you need do. By default, those macros support refcnt logging directly.

If your object is not an xpcom object then some manual editing is in order. The following sample code shows what must be done:

MyType::MyType()
{
  MOZ_COUNT_CTOR(MyType);
  ...
}
MyType::~MyType()
{
  MOZ_COUNT_DTOR(MyType);
  ...
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

词条统计

浏览:129 次

字数:16605

最后编辑:7 年前

编辑次数:0 次

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文