Home | History | Annotate | Download | only in template
      1 <!--
      2   Copyright 2014 The Chromium Authors. All rights reserved.
      3   Use of this source code is governed by a BSD-style license that can be
      4   found in the LICENSE file.
      5 -->
      6 <html>
      7 <head>
      8 <title>Binary Size Analysis</title>
      9 <script src="d3/d3.js" charset="utf-8"></script>
     10 <script src="D3SymbolTreeMap.js" charset="utf-8"></script>
     11 <script src="data.js" charset="utf-8"></script>
     12 <style>
     13 body {
     14     margin: 0px;
     15     padding: 5px;
     16 }
     17 .swatch {
     18     border: 1px solid rgb(100,100,100);
     19     -webkit-user-select: none;
     20     cursor: default;
     21 }
     22 </style>
     23 <script>
     24 var treemap;
     25 var filterChanging = false;
     26 var savedSettings = {};
     27 
     28 function init() {
     29     if (window.metadata !== undefined && window.metadata.subtitle) {
     30         document.getElementById('subtitle').innerHTML = ': ' + escape(metadata.subtitle);
     31     }
     32     initFilterOptions();
     33     treemap = new D3SymbolTreeMap(
     34         savedSettings.width,
     35         savedSettings.height,
     36         savedSettings.maxLevels);
     37     treemap.init();
     38 }
     39 
     40 function getIdealSizes() {
     41     var width = window.innerWidth - 20;
     42     var height = window.innerHeight - 70;
     43     return {'width': width, 'height': height};
     44 }
     45 
     46 function showReport(title, data, headers, dataFunction, styleFunction) {
     47     var div =  d3.select('body').append('div')
     48         .style('margin', '0')
     49         .style('padding', '5px')
     50         .style('position', 'absolute')
     51         .style('top', '10%')
     52         .style('left', '10%')
     53         .style('background-color', 'rgba(255,255,255,0.9)')
     54         .style('width', '80%')
     55         .style('height', '80%')
     56         .style('z-index', '2147483647')
     57         .style('border', '3px ridge grey')
     58         .style('box-shadow', '10px 10px 5px rgba(80,80,80,0.7)')
     59         .style('text-align', 'center')
     60         .style('border-radius', '10px');
     61     var titlebar = div.append('div')
     62         .style('margin', '0')
     63         .style('padding', '5px')
     64         .style('position', 'absolute')
     65         .style('top', '0%')
     66         .style('left', '0%')
     67         .style('width', '100%')
     68         .style('height', '10%')
     69         .style('font-size', 'x-large');
     70     titlebar.text(title);
     71     var controls = div.append('div')
     72         .style('margin', '0')
     73         .style('padding', '5px')
     74         .style('position', 'absolute')
     75         .style('top', '90%')
     76         .style('left', '0%')
     77         .style('width', '100%')
     78         .style('height', '10%');
     79     controls.append('input').attr('type', 'button')
     80         .attr('value', 'Dismiss')
     81         .on('click', function(){div.remove();});
     82 
     83     var tableDiv = div.append('div')
     84         .style('overflow', 'auto')
     85         .style('position', 'absolute')
     86         .style('top', '10%')
     87         .style('left', '0%')
     88         .style('width', '100%')
     89         .style('height', '80%')
     90         .style('border-top', '1px solid rgb(230,230,230)')
     91         .style('border-bottom', '1px solid rgb(230,230,230)');
     92     var table = tableDiv.append('table')
     93         .attr('border', '1')
     94         .attr('cellspacing', '0')
     95         .attr('cellpadding', '2')
     96         .style('margin-left', 'auto')
     97         .style('margin-right', 'auto');
     98     var header = table.append('tr');
     99     for (var i = 0; i < headers.length; i++) {
    100         header.append('th').text(headers[i]);
    101     }
    102 
    103     for (var i = 0; i < data.length; i++) {
    104         var row = table.append('tr');
    105         for (j = 0; j < headers.length; j++) {
    106             var td = row.append('td');
    107             if (styleFunction) {
    108                 styleFunction.call(this, td, j);
    109             }
    110             dataFunction.call(this, data[i], j, td);
    111         }
    112     }
    113 }
    114 
    115 function bigSymbolsReport() {
    116     var list = treemap.biggestSymbols(100);
    117     var headers = ['Rank', 'Size (Bytes)', 'Type', 'Location'];
    118     var styleFunction = function(selection, index) {
    119         if (index === 3) {
    120             selection.style('font-family', 'monospace');
    121         }
    122     };
    123     var recordIndex = 1;
    124     var dataFunction = function(record, index, cell) {
    125         if (index === 0) {
    126             cell.text(recordIndex++);
    127         } else if (index === 1) {
    128             cell.text(D3SymbolTreeMap._pretty(record.value));
    129         } else if (index === 2) {
    130             cell.text(record.t);
    131         } else {
    132             if (treemap.pathFor(record).indexOf('/out') == 0) {
    133                 cell.append('span').text(treemap.pathFor(record));
    134                 cell.append('br');
    135                 cell.append('span').text('Symbol: ');
    136                 cell.append('span').text(record.n);
    137             } else {
    138                 var href = 'https://code.google.com/p/chromium/codesearch#chromium/src'
    139                     + treemap.pathFor(record)
    140                     + '&q='
    141                     + record.n;
    142                 cell.append('a')
    143                     .attr('href', href)
    144                     .attr('target', '_blank')
    145                     .text(treemap.pathFor(record));
    146                 cell.append('br');
    147                 cell.append('span').text('Symbol: ');
    148                 cell.append('span').text(record.n);
    149             }
    150         }
    151     };
    152     showReport('100 Largest Symbols', list, headers, dataFunction, styleFunction);
    153 }
    154 
    155 function bigPathsReport() {
    156     var list = treemap.biggestPaths(100);
    157     var headers = ['Rank', 'Size (Bytes)', 'Location'];
    158     var styleFunction = function(selection, index) {
    159         if (index === 2) {
    160             selection.style('font-family', 'monospace');
    161         }
    162     };
    163     var recordIndex = 1;
    164     var dataFunction = function(record, index, cell) {
    165         if (index === 0) {
    166             cell.text(recordIndex++);
    167         } else if (index === 1) {
    168             cell.text(D3SymbolTreeMap._pretty(record.value));
    169         } else if (index === 2) {
    170             if (treemap.pathFor(record).indexOf('/out') == 0) {
    171                 cell.text(treemap.pathFor(record));
    172             } else {
    173                 var href = 'https://code.google.com/p/chromium/codesearch#chromium/src' + treemap.pathFor(record);
    174                 cell.append('a')
    175                     .attr('href', href)
    176                     .attr('target', '_blank')
    177                     .text(treemap.pathFor(record));
    178             }
    179 
    180         }
    181     };
    182     showReport('100 Largest Paths', list, headers, dataFunction, styleFunction);
    183 }
    184 
    185 function symbolFilterTextChanged() {
    186     if (filterChanging) return true;
    187     filterChanging = true;
    188     var enabled = document.getElementById('symbol_types_filter').value;
    189     for (var x=0; x<=25; x++) {
    190         var checkBox = document.getElementById('check_' + x);
    191         checkBox.checked = (enabled.indexOf(checkBox.value) != -1);
    192     }
    193     filterChanging = false;
    194 }
    195 
    196 function updateFilterText() {
    197     if (filterChanging) return true;
    198     filterChanging = true;
    199     var text = '';
    200     for (var x=0; x<=25; x++) {
    201         var checkBox = document.getElementById('check_' + x);
    202         if (checkBox.checked) {
    203             text += checkBox.value;
    204         }
    205     }
    206     document.getElementById('symbol_types_filter').value=text;
    207     filterChanging = false;
    208 }
    209 
    210 function initFilterOptions() {
    211     updateFilterText();
    212     for (var x=0; x<=25; x++) {
    213         var checkBox = document.getElementById('check_' + x);
    214         checkBox.onchange=updateFilterText;
    215         var swatch = document.getElementById('swatch_' + x);
    216         swatch.style.backgroundColor = D3SymbolTreeMap.getColorForType(checkBox.value).toString();
    217     }
    218     var gteCheckbox = document.getElementById('check_gte');
    219     gteCheckbox.onchange = function() {
    220         document.getElementById('symbol_filter_gte').disabled = !gteCheckbox.checked;
    221     }
    222     var regexCheckbox = document.getElementById('check_regex');
    223     regexCheckbox.onchange = function() {
    224         document.getElementById('symbol_filter_regex').disabled = !regexCheckbox.checked;
    225     }
    226     var excludeRegexCheckbox = document.getElementById('check_exclude_regex');
    227     excludeRegexCheckbox.onchange = function() {
    228         document.getElementById('symbol_filter_exclude_regex').disabled = !excludeRegexCheckbox.checked;
    229     }
    230     var idealSizes = getIdealSizes();
    231     document.getElementById('width').value = idealSizes.width;
    232     document.getElementById('height').value = idealSizes.height;
    233     saveFilterSettings();
    234 }
    235 
    236 function filterSetAll(enabled) {
    237     for (var x=0; x<=25; x++) {
    238         var checkBox = document.getElementById('check_' + x);
    239         checkBox.checked = enabled;
    240     }
    241     updateFilterText();
    242 }
    243 
    244 function showOptions() {
    245     loadFilterSettings();
    246     var container = document.getElementById('options_container');
    247     var w = container.offsetWidth;
    248     var h = container.offsetHeight;
    249     container.style.margin = '-' + (h/2) + 'px 0 0 -' + (w/2) + 'px';
    250     container.style.visibility = 'visible';
    251 }
    252 
    253 function hideOptions() {
    254     var container = document.getElementById('options_container');
    255     container.style.visibility = 'hidden';
    256 }
    257 
    258 function applySettings() {
    259     hideOptions();
    260     var oldWidth = savedSettings.width;
    261     var oldHeight = savedSettings.height;
    262     var oldSymbols = savedSettings.symbolTypes;
    263     var oldRegex = savedSettings.regex;
    264     var oldExcludeRegex = savedSettings.excludeRegex;
    265     var oldGte = savedSettings.gte;
    266     var oldMaxLevels = savedSettings.maxLevels;
    267     saveFilterSettings();
    268     var resizeNeeded = oldWidth !== savedSettings.width || oldHeight !== savedSettings.height;
    269     var regexChanged = oldRegex !== savedSettings.regex;
    270     var excludeRegexChanged = oldExcludeRegex !== savedSettings.excludeRegex;
    271     var symbolsChanged = oldSymbols !== savedSettings.symbolTypes;
    272     var gteChanged = oldGte !== savedSettings.gte;
    273     var filterChanged = regexChanged || excludeRegexChanged || symbolsChanged || gteChanged;
    274     var maxLevelsChanged = oldMaxLevels !== savedSettings.maxLevels;
    275 
    276     if (filterChanged) {
    277         // Type filters
    278         typeFilter = function(datum) {
    279             if (datum.depth === 0) return true; // root node
    280             if (datum.t === undefined) return true;
    281             return savedSettings.symbolTypes !== undefined &&
    282                 savedSettings.symbolTypes.indexOf(datum.t) !== -1;
    283         }
    284 
    285         // Regex filter
    286         var regexFilter = undefined;
    287         if (savedSettings.regex !== undefined && savedSettings.regex.length > 0) {
    288             console.log('filter: regex is "' + savedSettings.regex + '"');
    289             var regex = new RegExp(savedSettings.regex);
    290             regexFilter = function(datum) {
    291                 if (datum.depth === 0) return true; // root node
    292                 var fullName = this.pathFor(datum);
    293                 if (datum.children === undefined) { // it is a leaf node (symbol)
    294                     fullName += ':' + datum.n;
    295                 }
    296                 return regex.test(fullName);
    297             }
    298         }
    299 
    300         // Exclude regex filter
    301         var excludeRegexFilter = undefined;
    302         if (savedSettings.excludeRegex !== undefined && savedSettings.excludeRegex.length > 0) {
    303             console.log('filter: exclude-regex is "' + savedSettings.excludeRegex + '"');
    304             var excludeRegex = new RegExp(savedSettings.excludeRegex);
    305             excludeRegexFilter = function(datum) {
    306                 if (datum.depth === 0) return true; // root node
    307                 var fullName = this.pathFor(datum);
    308                 if (datum.children === undefined) { // it is a leaf node (symbol)
    309                     fullName += ':' + datum.n;
    310                 }
    311                 return !excludeRegex.test(fullName);
    312             }
    313         }
    314 
    315         // Size filter
    316         var sizeFilter = undefined;
    317         if (savedSettings.gte !== undefined) {
    318             console.log('filter: minimum size is ' + savedSettings.gte + ' bytes');
    319             sizeFilter = function(datum) {
    320                 if (datum.children !== undefined) return true; // non-leaf
    321                 if (datum.value === undefined) console.log('whoops');
    322                 return datum.value >= savedSettings.gte;
    323             }
    324         }
    325 
    326         // Make a filter to apply to the tree
    327         var filter = function(datum) {
    328             if (typeFilter && !typeFilter.call(this, datum)) return false;
    329             if (regexFilter && !regexFilter.call(this, datum)) return false;
    330             if (excludeRegexFilter && !excludeRegexFilter.call(this, datum)) return false;
    331             if (sizeFilter && !sizeFilter.call(this, datum)) return false;
    332             return true;
    333         };
    334         treemap.filter(filter);
    335     }
    336 
    337     // Adjust levels if needed.
    338     if (maxLevelsChanged) {
    339         treemap.setMaxLevels(savedSettings.maxLevels);
    340     }
    341 
    342     // Resize map if necessary.
    343     if (resizeNeeded) {
    344         console.log('desired treemap dimensions have changed, requesting resize');
    345         treemap.resize(savedSettings.width, savedSettings.height);
    346     }
    347 }
    348 
    349 function cancelSettings() {
    350     hideOptions();
    351     loadFilterSettings();
    352 }
    353 
    354 function saveFilterSettings() {
    355     savedSettings.symbolTypes = document.getElementById('symbol_types_filter').value;
    356     if (document.getElementById('check_regex').checked) {
    357         savedSettings.regex = document.getElementById('symbol_filter_regex').value;
    358     } else {
    359         savedSettings.regex = undefined;
    360     }
    361     if (document.getElementById('check_exclude_regex').checked) {
    362         savedSettings.excludeRegex = document.getElementById('symbol_filter_exclude_regex').value;
    363     } else {
    364         savedSettings.excludeRegex = undefined;
    365     }
    366     if (document.getElementById('check_gte').checked) {
    367         savedSettings.gte = parseInt(document.getElementById('symbol_filter_gte').value);
    368     } else {
    369         savedSettings.gte = undefined;
    370     }
    371     savedSettings.width = parseInt(document.getElementById('width').value);
    372     savedSettings.height = parseInt(document.getElementById('height').value);
    373     savedSettings.maxLevels = parseInt(document.getElementById('max_levels').value);
    374 }
    375 
    376 function loadFilterSettings() {
    377     document.getElementById('symbol_types_filter').value = savedSettings.symbolTypes;
    378     symbolFilterTextChanged();
    379     if (savedSettings.regex !== undefined) {
    380         document.getElementById('check_regex').checked = true;
    381         document.getElementById('symbol_filter_regex').value = savedSettings.regex;
    382     } else {
    383         document.getElementById('check_regex').checked = false;
    384     }
    385     if (savedSettings.excludeRegex !== undefined) {
    386         document.getElementById('check_exclude_regex').checked = true;
    387         document.getElementById('symbol_filter_exclude_regex').value = savedSettings.excludeRegex;
    388     } else {
    389         document.getElementById('check_exclude_regex').checked = false;
    390     }
    391     if (savedSettings.gte !== undefined) {
    392         document.getElementById('check_gte').checked = true;
    393         document.getElementById('symbol_filter_gte').value = savedSettings.gte;
    394     } else {
    395         document.getElementById('check_gte').checked = false;
    396     }
    397     document.getElementById('width').value = savedSettings.width;
    398     document.getElementById('height').value = savedSettings.height;
    399     document.getElementById('max_levels').value = savedSettings.maxLevels;
    400 }
    401 
    402 function escape(str) {
    403     return str.replace(/&/g, '&amp;')
    404               .replace(/"/g, '&quot;')
    405               .replace(/</g, '&lt;')
    406               .replace(/>/g, '&gt;');
    407 }
    408 </script>
    409 </head>
    410 <body onload='init()'>
    411 <div style='position: absolute; top: 5px; left: 5px;'>
    412   <input type='button' onclick='showOptions()' value='Options &amp; Legend...'>
    413   <span style='-webkit-user-select: none; cursor: help;' title='Click to view the symbol legend or to configure filters and options for the treemap'>[?]</span>
    414 </div>
    415 <div style='position: absolute; right: 5px; top: 5px; white-space: nowrap;'>
    416     Reports:
    417     <input type='button' onclick='bigSymbolsReport()' value='Large Symbols' title='Click to view a report of the largest 100 symbols that are with the bounds of the treemap that is currently displayed.'>
    418     <input type='button' onclick='bigPathsReport()' value='Large Files' title='Click to view a report of the largest 100 source files that are with the bounds of the treemap that is currently displayed.'>
    419 </div>
    420 <div style='text-align: center; margin-bottom: 5px;'>
    421     <span style='font-size: x-large; font-weight: bold; font-variant: small-caps'>Binary Size Analysis<span id='subtitle'></span></span>
    422     <br><span style='font-size: small; font-style: italic;'>Double-click a box to zoom in, double-click outermost title to zoom out.</span>
    423 </div>
    424 <table id='options_container' style='visibility: hidden; border: 3px ridge grey; padding: 0px; top: 50%; left: 50%; position: fixed; z-index: 2147483646; overflow: auto; background-color: rgba(255,255,255,0.9); border-radius: 10px; box-shadow: 10px 10px 5px rgba(80,80,80,0.7);'><tr><td style='vertical-align: top'>
    425     <table cellspacing=0 cellborder=0 style='width:100%'>
    426         <tr><th colspan=3 style='padding-bottom: .25em; text-decoration: underline;'>Symbol Types To Show</th></tr>
    427         <tr>
    428             <td style='width: 33%; white-space: nowrap; vertical-align: top;'>
    429                     <span class='swatch' id='swatch_0'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_0' value='A'>Global absolute (A)
    430                 <br><span class='swatch' id='swatch_1'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_1' value='B'>Global uninitialized data (B)
    431                 <br><span class='swatch' id='swatch_2'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_2' value='b'>Local uninitialized data (b)
    432                 <br><span class='swatch' id='swatch_3'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_3' value='C'>Global uninitialized common (C)
    433                 <br><span class='swatch' id='swatch_4'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_4' value='D'>Global initialized data (D)
    434                 <br><span class='swatch' id='swatch_5'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_5' value='d'>Local initialized data (d)
    435                 <br><span class='swatch' id='swatch_6'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_6' value='G'>Global small initialized data (G)
    436                 <br><span class='swatch' id='swatch_7'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_7' value='g'>Local small initialized data (g)
    437                 <br><span class='swatch' id='swatch_8'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_8' value='i'>Indirect function (i)
    438             </td>
    439             <td style='width: 33%; white-space: nowrap; vertical-align: top;'>
    440                     <span class='swatch' id='swatch_9'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_9' value='N'>Debugging (N)
    441                 <br><span class='swatch' id='swatch_10'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_10' value='p'>Stack unwind (p)
    442                 <br><span class='swatch' id='swatch_11'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_11' value='R'>Global read-only data (R)
    443                 <br><span class='swatch' id='swatch_12'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_12' value='r'>Local read-only data (r)
    444                 <br><span class='swatch' id='swatch_13'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_13' value='S'>Global small uninitialized data (S)
    445                 <br><span class='swatch' id='swatch_14'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_14' value='s'>Local small uninitialized data (s)
    446                 <br><span class='swatch' id='swatch_15'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_15' value='T'>Global code (T)
    447                 <br><span class='swatch' id='swatch_16'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_16' value='t'>Local code (t)
    448                 <br><span class='swatch' id='swatch_17'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_17' value='U'>Undefined (U)
    449             </td>
    450             <td style='width: 33%; white-space: nowrap; vertical-align: top;'>
    451                     <span class='swatch' id='swatch_18'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_18' value='u'>Unique (u)
    452                 <br><span class='swatch' id='swatch_19'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_19' value='V'>Global weak object (V)
    453                 <br><span class='swatch' id='swatch_20'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_20' value='v'>Local weak object (v)
    454                 <br><span class='swatch' id='swatch_21'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_21' value='W'>Global weak symbol (W)
    455                 <br><span class='swatch' id='swatch_22'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_22' value='w'>Local weak symbol (w)
    456                 <br><span class='swatch' id='swatch_23'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_23' value='@'>Vtable entry (@)
    457                 <br><span class='swatch' id='swatch_24'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_24' value='-'>STABS debugging (-)
    458                 <br><span class='swatch' id='swatch_25'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_25' value='?'>Unrecognized (?)
    459             </td>
    460         </tr>
    461         <tr><td colspan=3 style='text-align: center; white-space: nowrap; padding-top: 1em;'>
    462             Select <input type='button' onclick='filterSetAll(true)' value='All'>,
    463             <input type='button' onclick='filterSetAll(false)' value='None'>,
    464             or type a string: <input id='symbol_types_filter' size=30 value='' onkeyup='symbolFilterTextChanged()' onblur='updateFilterText()'>
    465             <span style='-webkit-user-select: none; cursor: help;' title='Enter codes from the list above for the symbols you want to see. The checkboxes will update automatically to match the string that you enter.'>[?]</span>
    466         </td></tr>
    467    </table>
    468 </td></tr><tr><td style='vertical-align: top; padding-top: 10px; border-top: 1px solid grey;'>
    469     <table cellspacing=0 cellborder=0 style='width: 100%'>
    470         <tr><th colspan=2 style='padding-bottom: .25em; text-decoration: underline;'>Advanced Options</th></tr>
    471         <tr>
    472             <td style='white-space: nowrap; vertical-align: top;'>
    473                 <input type='checkbox' id='check_regex'>
    474                 Only include symbols matching this regex:
    475             </td>
    476             <td style='text-align: right; vertical-align: top;'>
    477                 <input disabled id='symbol_filter_regex' size=30 value='' style='text-align: right;'>
    478                 <span style='-webkit-user-select: none; cursor: help;' title='Enter a javascript regex. Only symbols that match this regex will be shown. This filter applies before any exclusion regex specified below. The format of each symbol is [path]:[symbol_name]'>[?]</span>
    479             </td>
    480         </tr>
    481         <tr>
    482             <td style='white-space: nowrap; vertical-align: top;'>
    483                 <input type='checkbox' id='check_exclude_regex'>
    484                 Exclude all symbols matching this regex:
    485             </td>
    486             <td style='text-align: right; vertical-align: top;'>
    487                 <input disabled id='symbol_filter_exclude_regex' size=30 value='' style='text-align: right;'>
    488                 <span style='-webkit-user-select: none; cursor: help;' title='Enter a javascript regex. Symbols that match this tegex will not be shown. This filter applies after any inclusion filter specified above. The format of each symbol is [path]:[symbol_name]'>[?]</span>
    489             </td>
    490         </tr>
    491         <tr>
    492             <td style='white-space: nowrap; vertical-align: top;'>
    493                 <input type='checkbox' id='check_gte'>
    494                 Only include symbols that are at least <span style='font-style: italic;'>n</span> bytes:
    495             </td>
    496             <td style='text-align: right; vertical-align: top;'>
    497                 <input disabled id='symbol_filter_gte' size=8 value='' style='text-align: right;'>
    498                 <span style='-webkit-user-select: none; cursor: help;' title='Symbols whose size is less than this value will be hidden.'>[?]</span>
    499             </td>
    500         </tr>
    501         <tr>
    502             <td style='white-space: nowrap vertical-align: top;;'>
    503                 Show at most <span style='font-style: italic;'>n</span> levels of detail at a time:
    504             </td>
    505             <td style='text-align: right; vertical-align: top;'>
    506                 <input id='max_levels' size=4 value='2' style='text-align: right;'><span style='-webkit-user-select: none; cursor: help;' title='Increasing this value shows more detail without the need to zoom, but uses more computing power.'>[?]</span>
    507             </td>
    508         </tr>
    509         <tr>
    510             <td style='white-space: nowrap vertical-align: top;;'>
    511                 Set the size of the treemap to <span style='font-style: italic;'>W x H</span> pixels:
    512             </td>
    513             <td style='text-align: right; vertical-align: top;'>
    514                 <input id='width' size=4 value='' style='text-align: right;'>
    515                 &nbsp;x&nbsp;<input id='height' size=4 value='' style='text-align: right;'>
    516             </td>
    517         </tr>
    518     </table>
    519 </td></tr>
    520 <tr><td style='padding-top: 10px; text-align: right; border-top: 1px solid grey'>
    521     <input type='button' value='Apply' onclick='applySettings()'>
    522     <input type='button' value='Cancel' onclick='cancelSettings()'>
    523 </td></tr></table>
    524 </body>
    525 </html>
    526