npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

bleak-detector

v1.2.2

Published

Automatically finds memory leaks in single page web applications.

Downloads

67

Readme

BLeak v1.2.2

Build Status Build status npm version Coverage Status

BLeak automatically finds, ranks, and diagnoses memory leaks in the client-side of web applications.

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.

For more information please see the BLeak website and the our academic paper, which appeared at PLDI 2018.

Prerequisites

The following must be installed for BLeak to work:

  • mitmproxy V4 (Tested with 4.0.1)
  • Python 3.6 or greater
    • Our mitmproxy plugin uses new Python async features

Installing

npm install -g bleak-detector

After installing, you should be able to run bleak from the command line.

Using

  1. Build BLeak (see above).
  2. Write a configuration file for your web application (see below).
  3. Run bleak run --config path/to/config.js --out path/to/where/you/want/output
    • 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.
  4. 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.
  5. 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!
    • 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.

Configuration File

BLeak uses a configuration file to find memory leaks in the client-side of a web application. Only a few fields are required.

// URL to the web application.
exports.url = "http://path/to/my/site";
// Runs your program in a loop. Each item in the array is a `state`. Each `state` has a "check"
// function, and a "next" function to transition to the next state in the loop. These run
// in the global scope of your web app.
// BLeak assumes that the app is in the first state when it navigates to the URL. If you specify
// optional setup states, then it assumes that the final setup state transitions the web app to
// the first state in the loop.
// The last state in the loop must transition back to the first.
exports.loop = [
  // First state
  {
    // Return 'true' if the web application is ready for `next` to be run.
    check: function() {
      // Example: `group-listing` must be on the webpage
      return !!document.getElementById('group-listing');
    },
    // Transitions to the next state.
    next: function() {
      // Example: Navigate to the first thread
      document.getElementById("thread-001").click();
    }
  },
  // Second (and last) state
  {
    check: function() {
      // Example: Make sure the body of the thread has loaded.
      return !!document.getElementById('thread-body');
    },
    // Since this is the last state in the loop, it must transition back to the first state.
    next: function() {
      // Example: Click back to group listing
      document.getElementById('group-001').click();
    }
  }
];

// (Optional) Number of loop iterations to perform during leak detection (default: 8)
exports.iterations = 8;

// (Optional) An array of states describing how to login to the application. Executed *once*
// to set up the session. See 'config.loop' for a description of a state.
exports.login = [
  {
    check: function() {
      // Return 'true' if the element 'password-field' exists.
      return !!document.getElementById('password-field');
    },
    next: function() {
      // Log in to the application.
      const pswd = document.getElementById('password-field');
      const uname = document.getElementById('username-field');
      const submitBtn = document.getElementById('submit');
      uname.value = 'spongebob';
      pswd.value = 'squarepants';
      submitBtn.click();
    }
  }
];
// (Optional) An array of states describing how to get from config.url to the first state in
// the loop. Executed each time the tool explicitly re-navigates to config.url. See
// config.loop for a description of states.
exports.setup = [

];
// (Optional) How long (in milliseconds) to wait for a state transition to finish before declaring an error.
// Defaults to 10 minutes
exports.timeout = 10 * 60 * 1000;
// (Optional) How long (in milliseconds) to wait between a check() returning 'true' and transitioning to the next step or taking a heap snapshot.
// Default: 1000
exports.postCheckSleep = 1000;
// (Optional) How long (in milliseconds) to wait between transitioning to the next step and running check() for the first time.
// Default: 0
exports.postNextSleep = 0;
// (Optional) How long (in milliseconds) to wait between submitting login credentials and reloading the page for a run.
// Default: 5000
exports.postLoginSleep = 5000;
// (Optional) An array of numerical IDs identifying leaks with fixes in your code. Used to
// evaluate memory savings with different leak configurations and the effectiveness of bug fixes.
// In the code, condition the fix on $$$SHOULDFIX$$$(ID), or add logic to `exports.rewrite` (see below),
// and BLeak will run the web app with the fixes applied.
exports.fixedLeaks = [0, 1, 2];
// (Optional) Proxy re-write rule that runs in a Node.js environment, *not* in the browser.
// Lets you rewrite the web app's JavaScript/HTML/CSS to test bug fixes. Especially useful for evaluating
// fixes on web apps you do not control.
// Return a Node.js Buffer containing the replacement resource contents, or the original contents if not
// modifying.
exports.rewrite = function(url /* URL of the resource */,
                  type /* MIME type of resource */,
                  data /* Contents of resource, as a Node.js Buffer */,
                  fixes /* Array of numerical IDs corresponding to bug fixes that are active during the session (see fixedLeaks) */) {
  function hasFix(n) {
    return fixes.indexOf(n) !== -1;
  }
  // Example: Filter out non-JavaScript resources.
  if (type.indexOf("javascript") !== -1) {
    if (url.indexOf("19/common.js") !== -1) {
      let src = data.toString();
      // Example: Replace a specific string in `19/common.js` to fix bug 0.
      if (hasFix(0)) {
        src = src.replace(`window.addEventListener("scroll",a,!1)`, 'window.onscroll=a');
      }
      return Buffer.from(src, 'utf8');
    }
  }
  return data;
};

Developing

Interested in fixing bugs or building on BLeak? Excellent! Read below on how to build BLeak from source and run our unit tests.

Prerequisites

  • Yarn package manager
    • NPM may work, but we do not test against it

Building

# Install NPM dependencies (only need to run once)
yarn install
# Build BLeak
yarn run build

Testing

yarn test

Debugging Tips

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.