├── .gitignore ├── .mds-list ├── sync-en.sh ├── readme.md └── en.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .DS_Store 3 | fork 4 | source -------------------------------------------------------------------------------- /.mds-list: -------------------------------------------------------------------------------- 1 | ./source/README.md 2 | ./source/readme.zh.md 3 | -------------------------------------------------------------------------------- /sync-en.sh: -------------------------------------------------------------------------------- 1 | cat './.mds-list' | while read line 2 | do 3 | testseq="zh.md" 4 | if [[ $line =~ $testseq || "$line" == "" ]]; then 5 | echo "skip $line" 6 | else 7 | source_readme="./source/readme.md" 8 | lowline=`echo "$line" | awk '{print tolower($0)}'` 9 | zh=${line//source\//} 10 | dir=$(dirname $zh) 11 | # source/readme.md => en.md 12 | if [[ $lowline == $source_readme ]];then 13 | filename="en.md" 14 | else 15 | filename=$(basename $zh) 16 | fi 17 | echo "$line >> $dir/$filename" 18 | mkdir -p $dir && cp $line "$_/$filename" 19 | fi 20 | done -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # plasma-umass/BLeak [![explain]][source] [![translate-svg]][translate-list] 2 | 3 | 4 | 5 | [explain]: http://llever.com/explain.svg 6 | [source]: https://github.com/chinanf-boy/Source-Explain 7 | [translate-svg]: http://llever.com/translate.svg 8 | [translate-list]: https://github.com/chinanf-boy/chinese-translate-list 9 | [size-img]: https://packagephobia.now.sh/badge?p=Name 10 | [size]: https://packagephobia.now.sh/result?p=Name 11 | 12 | 「 在 Web 应用程序的客户端中,自动查找,排名和诊断内存泄漏. 」 13 | 14 | [中文](./readme.md) | [english](https://github.com/plasma-umass/BLeak) 15 | 16 | --- 17 | 18 | ## 校对 ✅ 19 | 20 | 21 | 22 | 23 | 24 | 翻译的原文 | 与日期 | 最新更新 | 更多 25 | ---|---|---|--- 26 | [commit] | ⏰ 2018-11-20 | ![last] | [中文翻译][translate-list] 27 | 28 | [last]: https://img.shields.io/github/last-commit/plasma-umass/BLeak.svg 29 | [commit]: https://github.com/plasma-umass/BLeak/tree/f9d3c14722e88edcda6520e57533d519b3cce405 30 | 31 | 32 | 33 | ### 贡献 34 | 35 | 欢迎 👏 勘误/校对/更新贡献 😊 [具体贡献请看](https://github.com/chinanf-boy/chinese-translate-list#贡献) 36 | 37 | ## 生活 38 | 39 | [If help, **buy** me coffee —— 营养跟不上了,给我来瓶营养快线吧! 💰](https://github.com/chinanf-boy/live-need-money) 40 | 41 | --- 42 | 43 | # BLeak v1.2.1 44 | 45 | [![Build Status](https://travis-ci.org/plasma-umass/BLeak.svg?branch=master)](https://travis-ci.org/plasma-umass/BLeak) 46 | [![Build status](https://ci.appveyor.com/api/projects/status/b92sknh0pu38943q/branch/master?svg=true)](https://ci.appveyor.com/project/jvilk/bleak/branch/master) 47 | [![npm version](https://badge.fury.io/js/bleak-detector.svg)](https://www.npmjs.com/package/bleak-detector) 48 | [![Coverage Status](https://coveralls.io/repos/github/plasma-umass/BLeak/badge.svg)](https://coveralls.io/github/plasma-umass/BLeak) 49 | 50 | [BLeak](http://bleak-detector.org/)会在 Web 应用程序的客户端中,自动查找,排名和诊断内存泄漏. 51 | 52 | BLeak 使用一个简短的开发人员提供的脚本,来通过特定的可视状态,循环驱动应用程序(例如,邮件客户端的收件箱视图和电子邮件视图)作为查找内存泄漏的标杆。根据我们的经验,BLeak 的精确度通常是**100%**(例如,没有误报),并且修复它发现的泄漏,**94%**会减少堆增长(平均而言)。对象都为真实生产网络应用程序。 53 | 54 | 有关详细信息,请参阅[BLeak 网站](http://bleak-detector.org/)和[我们的学术论文](https://github.com/plasma-umass/BLeak/blob/master/paper.pdf),出现在 PLDI 2018 年. 55 | 56 | ## 先决条件 57 | 58 | 必须安装以下内容,才能使 BLeak 工作: 59 | 60 | - [mitmproxy](https://mitmproxy.org/)V4(4.0.1 已测试) 61 | - Python 3.6 或更高版本 62 | - 我们的 mitmproxy 插件使用 Python 新的异步功能 63 | 64 | ## 安装 65 | 66 | ``` 67 | npm install -g bleak-detector 68 | ``` 69 | 70 | 安装后,您应该能够在命令行运行`bleak`. 71 | 72 | ## 运用 73 | 74 | 1. **构建-Build** BLeak(见上文). 75 | 2. **写-Write** 一个*配置文件*,为您的 Web 应用程序(见下文). 76 | 3. **运行-Run** `bleak run --config path/to/config.js --out path/to/where/you/want/output` 77 | - 对于此特定的 BLeak 运行,输出目录应该是唯一的,否则它将覆盖目录中的文件。如果需要,它将被创建. 78 | 4. **等待.-Wait** BLeak 通常在 <10 分钟 内运行,但其速度取决于循环中的状态数和 Web 应用程序的速度. 79 | 5. **运行 BLeak 结果查看器** 通过运行`bleak viewer`,并浏览器导航到[HTTP://本地主机:8889/](http://localhost:8889/)。上传`path/to/where/you/want/output/bleak_results.json`到 Web 应用程序查看结果! 80 | - 或者,BLeak 在同一目录中,打印出一份报告`bleak_report.log`,但结果查看器能显示该日志文件中未捕获的其他信息. 81 | 82 | ## 配置文件 83 | 84 | BLeak 使用配置文件,在 Web 应用程序的客户端查找内存泄漏.只需要几个字段. 85 | 86 | ```javascript 87 | // web 应用的 URL . 88 | exports.url = 'http://path/to/my/site'; 89 | // 可运行你的程序,在 一个 loop . 数组中的每个对象项都是一个 `state`. 每个 `state` 有一个 "check" 90 | // 函数, 和一个 "next" 函数 to transition to the next state in the loop. These run 91 | // in the global scope of your web app. 92 | // BLeak assumes that the app is in the first state when it navigates to the URL. If you specify 93 | // 可选 setup states, then it assumes that the final setup state transitions the web app to 94 | // the first state in the loop. 95 | // The last state in the loop must transition back to the first. 96 | exports.loop = [ 97 | // 第一个 状态(state) 98 | { 99 | // 返回 'true', 若 web 应用 已准备好`next`的运行 100 | check: function() { 101 | // 例: `group-listing` 必须在网页中 102 | return !!document.getElementById('group-listing'); 103 | }, 104 | // 过渡到下一状态 105 | next: function() { 106 | // 例: Navigate to the first thread 107 | document.getElementById('thread-001').click(); 108 | } 109 | }, 110 | // 第二个 (也是最后的 last) 状态 111 | { 112 | check: function() { 113 | // 例: 确保 ‘thread-body’ 已加载 114 | return !!document.getElementById('thread-body'); 115 | }, 116 | // 鉴于这就是loop的最后一步, 它会过渡回第一状态. 117 | next: function() { 118 | // 例: Click back to group listing 119 | document.getElementById('group-001').click(); 120 | } 121 | } 122 | ]; 123 | 124 | // (可选) 泄漏检测期间要执行的循环迭代次数 (默认: 8) 125 | exports.iterations = 8; 126 | 127 | // (可选) 数组状态,指明如何登录该应用. 执行 *一次* 128 | // 该会话. 看 'config.loop' 了解其状态的描述 129 | exports.login = [ 130 | { 131 | check: function() { 132 | // 返回 'true' ,若元素 'password-field' 存在. 133 | return !!document.getElementById('password-field'); 134 | }, 135 | next: function() { 136 | // 登入 应用. 137 | const pswd = document.getElementById('password-field'); 138 | const uname = document.getElementById('username-field'); 139 | const submitBtn = document.getElementById('submit'); 140 | uname.value = 'spongebob'; 141 | pswd.value = 'squarepants'; 142 | submitBtn.click(); 143 | } 144 | } 145 | ]; 146 | // (可选) An array of states describing how to get from config.url to the first state in 147 | // the loop. Executed each time the tool explicitly re-navigates to config.url. See 148 | // config.loop for a description of states. 149 | exports.setup = []; 150 | // (可选) 在报告一个错误之前,等待 一个状态完成过渡多久 (毫秒单位) 151 | // 默认: 10 分钟 152 | exports.timeout = 10 * 60 * 1000; 153 | // (可选) 在 一个 check() 返回 'true' 和 过渡到下一步或拿到一个堆快照 之间,等待多久 (毫秒单位) 154 | // 默认: 1000 155 | exports.postCheckSleep = 1000; 156 | // (可选) 在 过渡到下一步和第一时间运行check()之间,等待多久 (毫秒单位) 157 | // 默认: 0 158 | exports.postNextSleep = 0; 159 | // (可选) 在提交登入凭证 和重载运行页面,等待多久 (毫秒单位) 160 | // 默认: 5000 161 | exports.postLoginSleep = 5000; 162 | // (可选) 一组数字ID,用于识别代码中的修复漏洞. 被用来 163 | // 作为,不同的泄漏配置和错误修复的有效内存节省的评估. 164 | // 在代码中, 条件性修复 $$$SHOULDFIX$$$(ID), 或给 `exports.rewrite` 添加逻辑 (看下面), 165 | // 和 BLeak 会用修复的补丁运行 web应用. 166 | exports.fixedLeaks = [0, 1, 2]; 167 | // (可选) 重写的代理会在一个Node.js环境中运行,*不是* 在浏览器 168 | // 让你重写 web 应用的 you rewrite the web app's JavaScript/HTML/CSS ,可测试补丁的有效性. 169 | // 对评估web应用中不可控,特别有用 170 | // 返回一个包含替换资源内容的 Node.js Buffer, 或不修改的化,就返回源内容 171 | exports.rewrite = function( 172 | url /* 资源 URL */, 173 | type /* 资源 MIME type */, 174 | data /* 资源 Contents, 作为 一个 Node.js Buffer */, 175 | fixes /* 对应于活动会话期间的错误修复的数组数字ID (看 fixedLeaks) */ 176 | ) { 177 | function hasFix(n) { 178 | return fixes.indexOf(n) !== -1; 179 | } 180 | // 例: 过滤掉 非JavaScript 的资源. 181 | if (type.indexOf('javascript') !== -1) { 182 | if (url.indexOf('19/common.js') !== -1) { 183 | let src = data.toString(); 184 | // 例: 在 `19/common.js`,替换自定字符串,以修复 bug 0. 185 | if (hasFix(0)) { 186 | src = src.replace( 187 | `window.addEventListener("scroll",a,!1)`, 188 | 'window.onscroll=a' 189 | ); 190 | } 191 | return Buffer.from(src, 'utf8'); 192 | } 193 | } 194 | return data; 195 | }; 196 | ``` 197 | 198 | ## 发展 199 | 200 | 有兴趣修复 bug 或在 BLeak 上构建? 太好了! 请阅读以下有关如何从源代码构建 BLeak ,并运行我们的单元测试的信息. 201 | 202 | ### 先决条件 203 | 204 | - [yarn](https://yarnpkg.com/en/docs/install)包管理 205 | - npm*可以*工作,但我们并针对它做测试 206 | 207 | ### 建造 208 | 209 | ``` 210 | # Install NPM dependencies (only need to run once) 211 | yarn install 212 | # Build BLeak 213 | yarn run build 214 | ``` 215 | 216 | ### 测试 217 | 218 | ``` 219 | yarn test 220 | ``` 221 | 222 | ### 调试技巧 223 | 224 | bleak 的可执行文件(一旦构建,可通过`./bleak`运行)有许多有用的调试命令。例如,使用`proxy-session`调试 BLeak 的代理/诊断阶段的问题. 225 | -------------------------------------------------------------------------------- /en.md: -------------------------------------------------------------------------------- 1 | # BLeak v1.2.1 2 | 3 | [![Build Status](https://travis-ci.org/plasma-umass/BLeak.svg?branch=master)](https://travis-ci.org/plasma-umass/BLeak) 4 | [![Build status](https://ci.appveyor.com/api/projects/status/b92sknh0pu38943q/branch/master?svg=true)](https://ci.appveyor.com/project/jvilk/bleak/branch/master) 5 | [![npm version](https://badge.fury.io/js/bleak-detector.svg)](https://www.npmjs.com/package/bleak-detector) 6 | [![Coverage Status](https://coveralls.io/repos/github/plasma-umass/BLeak/badge.svg)](https://coveralls.io/github/plasma-umass/BLeak) 7 | 8 | [BLeak](http://bleak-detector.org/) automatically finds, ranks, and diagnoses memory leaks in the client-side of web applications. 9 | 10 | BLeak uses a short developer-provided script to drive the application in a loop through specific visual states (e.g., the inbox view and email view of a mail client) as an oracle to find memory leaks. In our experience, BLeak's precision is often **100%** (e.g., no false positives), and fixing the leaks it finds reduces heap growth by **94%** on average on a corpus of real production web apps. 11 | 12 | For more information please see [the BLeak website](http://bleak-detector.org/) and the [our academic paper](https://github.com/plasma-umass/BLeak/blob/master/paper.pdf), which appeared at PLDI 2018. 13 | 14 | ## Prerequisites 15 | 16 | The following must be installed for BLeak to work: 17 | 18 | * [mitmproxy](https://mitmproxy.org/) V4 (Tested with 4.0.1) 19 | * Python 3.6 or greater 20 | * Our mitmproxy plugin uses new Python async features 21 | 22 | ## Installing 23 | 24 | ``` 25 | npm install -g bleak-detector 26 | ``` 27 | 28 | After installing, you should be able to run `bleak` from the command line. 29 | 30 | 31 | ## Using 32 | 33 | 1. **Build** BLeak (see above). 34 | 1. **Write** a *configuration file* for your web application (see below). 35 | 2. **Run** `bleak run --config path/to/config.js --out path/to/where/you/want/output` 36 | * The output directory should be unique for this specific run of BLeak, otherwise it will overwrite files in the directory. It will be created if needed. 37 | 3. **Wait.** BLeak typically runs in <10 minutes, but its speed depends on the number of states in your loop and the speed of your web application. 38 | 4. **Run the BLeak Results Viewer** by running `bleak viewer` and navigating to http://localhost:8889/ in a web browser. Upload `path/to/where/you/want/output/bleak_results.json` to the web application to view the results! 39 | * Alternatively, BLeak prints out a report in `bleak_report.log` in the same directory, but the results viewer presents additional information not captured in that log file. 40 | 41 | ## Configuration File 42 | 43 | BLeak uses a configuration file to find memory leaks in the client-side of a web application. Only a few fields are required. 44 | 45 | ```javascript 46 | // URL to the web application. 47 | exports.url = "http://path/to/my/site"; 48 | // Runs your program in a loop. Each item in the array is a `state`. Each `state` has a "check" 49 | // function, and a "next" function to transition to the next state in the loop. These run 50 | // in the global scope of your web app. 51 | // BLeak assumes that the app is in the first state when it navigates to the URL. If you specify 52 | // optional setup states, then it assumes that the final setup state transitions the web app to 53 | // the first state in the loop. 54 | // The last state in the loop must transition back to the first. 55 | exports.loop = [ 56 | // First state 57 | { 58 | // Return 'true' if the web application is ready for `next` to be run. 59 | check: function() { 60 | // Example: `group-listing` must be on the webpage 61 | return !!document.getElementById('group-listing'); 62 | }, 63 | // Transitions to the next state. 64 | next: function() { 65 | // Example: Navigate to the first thread 66 | document.getElementById("thread-001").click(); 67 | } 68 | }, 69 | // Second (and last) state 70 | { 71 | check: function() { 72 | // Example: Make sure the body of the thread has loaded. 73 | return !!document.getElementById('thread-body'); 74 | }, 75 | // Since this is the last state in the loop, it must transition back to the first state. 76 | next: function() { 77 | // Example: Click back to group listing 78 | document.getElementById('group-001').click(); 79 | } 80 | } 81 | ]; 82 | 83 | // (Optional) Number of loop iterations to perform during leak detection (default: 8) 84 | exports.iterations = 8; 85 | 86 | // (Optional) An array of states describing how to login to the application. Executed *once* 87 | // to set up the session. See 'config.loop' for a description of a state. 88 | exports.login = [ 89 | { 90 | check: function() { 91 | // Return 'true' if the element 'password-field' exists. 92 | return !!document.getElementById('password-field'); 93 | }, 94 | next: function() { 95 | // Log in to the application. 96 | const pswd = document.getElementById('password-field'); 97 | const uname = document.getElementById('username-field'); 98 | const submitBtn = document.getElementById('submit'); 99 | uname.value = 'spongebob'; 100 | pswd.value = 'squarepants'; 101 | submitBtn.click(); 102 | } 103 | } 104 | ]; 105 | // (Optional) An array of states describing how to get from config.url to the first state in 106 | // the loop. Executed each time the tool explicitly re-navigates to config.url. See 107 | // config.loop for a description of states. 108 | exports.setup = [ 109 | 110 | ]; 111 | // (Optional) How long (in milliseconds) to wait for a state transition to finish before declaring an error. 112 | // Defaults to 10 minutes 113 | exports.timeout = 10 * 60 * 1000; 114 | // (Optional) How long (in milliseconds) to wait between a check() returning 'true' and transitioning to the next step or taking a heap snapshot. 115 | // Default: 1000 116 | exports.postCheckSleep = 1000; 117 | // (Optional) How long (in milliseconds) to wait between transitioning to the next step and running check() for the first time. 118 | // Default: 0 119 | exports.postNextSleep = 0; 120 | // (Optional) How long (in milliseconds) to wait between submitting login credentials and reloading the page for a run. 121 | // Default: 5000 122 | exports.postLoginSleep = 5000; 123 | // (Optional) An array of numerical IDs identifying leaks with fixes in your code. Used to 124 | // evaluate memory savings with different leak configurations and the effectiveness of bug fixes. 125 | // In the code, condition the fix on $$$SHOULDFIX$$$(ID), or add logic to `exports.rewrite` (see below), 126 | // and BLeak will run the web app with the fixes applied. 127 | exports.fixedLeaks = [0, 1, 2]; 128 | // (Optional) Proxy re-write rule that runs in a Node.js environment, *not* in the browser. 129 | // Lets you rewrite the web app's JavaScript/HTML/CSS to test bug fixes. Especially useful for evaluating 130 | // fixes on web apps you do not control. 131 | // Return a Node.js Buffer containing the replacement resource contents, or the original contents if not 132 | // modifying. 133 | exports.rewrite = function(url /* URL of the resource */, 134 | type /* MIME type of resource */, 135 | data /* Contents of resource, as a Node.js Buffer */, 136 | fixes /* Array of numerical IDs corresponding to bug fixes that are active during the session (see fixedLeaks) */) { 137 | function hasFix(n) { 138 | return fixes.indexOf(n) !== -1; 139 | } 140 | // Example: Filter out non-JavaScript resources. 141 | if (type.indexOf("javascript") !== -1) { 142 | if (url.indexOf("19/common.js") !== -1) { 143 | let src = data.toString(); 144 | // Example: Replace a specific string in `19/common.js` to fix bug 0. 145 | if (hasFix(0)) { 146 | src = src.replace(`window.addEventListener("scroll",a,!1)`, 'window.onscroll=a'); 147 | } 148 | return Buffer.from(src, 'utf8'); 149 | } 150 | } 151 | return data; 152 | }; 153 | ``` 154 | 155 | ## Developing 156 | 157 | Interested in fixing bugs or building on BLeak? Excellent! Read below on how to build BLeak from source and run our unit tests. 158 | 159 | ### Prerequisites 160 | 161 | * [Yarn](https://yarnpkg.com/en/docs/install) package manager 162 | * NPM *may* work, but we do not test against it 163 | 164 | ### Building 165 | 166 | ``` 167 | # Install NPM dependencies (only need to run once) 168 | yarn install 169 | # Build BLeak 170 | yarn run build 171 | ``` 172 | 173 | ### Testing 174 | 175 | ``` 176 | yarn test 177 | ``` 178 | 179 | ### Debugging Tips 180 | 181 | The bleak executable (runnable via `./bleak` once built) has a number of useful debug commands. For example, use `proxy-session` to debug issues with BLeak's proxy / diagnoses phase. 182 | --------------------------------------------------------------------------------