├── .gitignore ├── package.json ├── LICENSE ├── README.md └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | /bower_components/ 2 | /node_modules/ 3 | /tmp/ 4 | 5 | npm-debug.log 6 | 7 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ember-cli-ramdisk", 3 | "version": "0.0.7", 4 | "description": "Use a ramdisk as your tmp directory for speedy builds", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [ 10 | "ember-addon" 11 | ], 12 | "author": "Alex Matchneer ", 13 | "license": "MIT", 14 | "dependencies": { 15 | "execsyncs": "^0.1.1", 16 | "rimraf": "^2.2.8" 17 | }, 18 | "repository": { 19 | "type": "git", 20 | "url": "git://github.com/ExpressCheckout/ember-cli-ramdisk.git" 21 | }, 22 | "bugs": { 23 | "url": "https://github.com/ExpressCheckout/ember-cli-ramdisk/issues" 24 | }, 25 | "homepage": "https://github.com/ExpressCheckout/ember-cli-ramdisk" 26 | } 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Alex Matchneer 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NOTE: 2 | 3 | This addon isn't as useful as it use to be. See the Impact section 4 | below. 5 | 6 | ## ember-cli-ramdisk 7 | 8 | `ember-cli` addon that mounts your broccoli `tmp` folder in RAM 9 | for speedier builds. 10 | 11 | Presently only supports OS X (Darwin) and Linux. 12 | 13 | ## Installation 14 | 15 | From your ember-cli project folder: 16 | 17 | npm install ember-cli-ramdisk --save-dev 18 | 19 | ## Motivation 20 | 21 | `ember-cli` uses Broccoli as a build tool, and Broccoli uses a `tmp` 22 | folder in your project's directory for storing intermediate files during 23 | the build process, which means they are getting stored on your hard 24 | drive. 25 | 26 | Most operating systems allow you to mount file systems into memory, 27 | which results in faster read/write operations with the obvious tradeoff 28 | being that if your computer restarts, you'll lose any data mounted on 29 | the ramdisk. 30 | 31 | But for temporary folders that are often read/written into, you can get 32 | some performance gains by mounting them to a ramdisk, which is what this 33 | ember addon does. 34 | 35 | ## Impact 36 | 37 | At this point, if you're using an up-to-date version of ember-cli, you 38 | probably won't notice an improvement in build times from this addon. 39 | 40 | Another use case for this addon is to prevent things like: 41 | * [SSD thrash](https://github.com/ember-cli/ember-cli/issues/2226#issuecomment-62065304), 42 | * slow writes to magnetic drives 43 | * fragmenting on Copy-On-Write filesystems like btrfs - see (http://blog.ieugen.ro/2015/03/my-experience-with-btrfs-on-debian.html) 44 | 45 | ## Details 46 | 47 | This addon will: 48 | 49 | 1. Mount a ramdisk at 50 | - OS X - `/Volumes/EmberCliRamdisk` 51 | - Linux - `/mnt/EmberCliRamdisk` 52 | 2. Replace your project's `tmp` folder with a symlink to 53 | `/Volumes/EmberCliRamdisk/your-project-name` or `/mnt/EmberCliRamdisk/your-project-name` 54 | 55 | Multiple projects can use this addon and share the same ramdisk. 56 | 57 | The ramdisk does not automatically unmount after you kill broccoli, but 58 | can easily be unmounted from the side menu in Finder. 59 | 60 | To unmount the ramdisk in linux you must run `sudo umount /mnt/EmberCliRamdisk` and `sudo rm -R /mnt/EmberCliRamdisk/`. 61 | 62 | ## TODO 63 | 64 | 1. Tests 65 | 2. Support for OSs other than Mac (darwin) and Linux 66 | 3. Replace execSync with something nicer (can't right now since 67 | `include` doesn't wait for any returned promises) 68 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var fs = require('fs'); 4 | var execSync = require('execsyncs'); 5 | var rimraf = require('rimraf'); 6 | 7 | var RAMDISK_BYTES = 2 * 1024 * 1024 * 1024; 8 | var BLOCK_SIZE = 512; 9 | var RAMDISK_BLOCKS = RAMDISK_BYTES / BLOCK_SIZE; 10 | var RAMDISK_NAME = "EmberCliRamdisk"; 11 | var RAMDISK_PATH = (function(){ 12 | switch (process.platform){ 13 | case "darwin": 14 | return "/Volumes/" + RAMDISK_NAME; 15 | case "linux": 16 | return "/mnt/" + RAMDISK_NAME; 17 | } 18 | })(); 19 | 20 | function ramdiskExists() { 21 | return fs.existsSync(RAMDISK_PATH); 22 | } 23 | 24 | function runCommand(command) { 25 | console.log("ember-cli-ramdisk: " + command); 26 | try { 27 | return execSync(command).toString(); 28 | } catch(e) { 29 | throw new Error("ember-cli-ramdisk: error running command(" + command + "): " + e.message); 30 | } 31 | } 32 | 33 | function removeOldTmpDirectory(projectTmpPath, options) { 34 | if (fs.readdirSync(projectTmpPath).length > 0 && !options.removeTmp) { 35 | throw new Error("Your " + projectTmpPath + " directory isn't empty. Please empty it or remove it so that ember-cli-ramdisk can take its place."); 36 | } 37 | 38 | rimraf.sync(projectTmpPath); 39 | } 40 | 41 | function createRamdiskDevice() { 42 | switch (process.platform) { 43 | case "darwin": 44 | return runCommand('hdiutil attach -nomount ram://' + RAMDISK_BLOCKS).trim(); 45 | case "linux": 46 | return runCommand('sudo mkdir -p '+RAMDISK_PATH); 47 | } 48 | } 49 | 50 | function mountRamdiskDevice(devicePath) { 51 | switch (process.platform) { 52 | case "darwin": 53 | return runCommand("diskutil erasevolume HFS+ " + RAMDISK_NAME + " " + devicePath); 54 | case "linux": 55 | return runCommand('sudo mount -t tmpfs -o size='+RAMDISK_BYTES+' tmpfs '+RAMDISK_PATH); 56 | } 57 | } 58 | 59 | function createRamdiskIfNecessary() { 60 | if (ramdiskExists()) { 61 | return; 62 | } 63 | 64 | var devicePath = createRamdiskDevice(); 65 | mountRamdiskDevice(devicePath); 66 | } 67 | 68 | function createSymlink(projectTmpPath, projectName) { 69 | var ramdiskTmpPath = RAMDISK_PATH + "/" + projectName; 70 | 71 | try { fs.mkdirSync(ramdiskTmpPath); } catch(e) {} 72 | 73 | fs.symlinkSync(ramdiskTmpPath, projectTmpPath, 'dir'); 74 | } 75 | 76 | module.exports = { 77 | name: 'ember-cli-ramdisk', 78 | included: function(app) { 79 | var options = app.options.ramdisk || {}; 80 | 81 | if (options.disabled) { 82 | return; 83 | } 84 | 85 | var projectTmpPath = app.project.root + "/tmp"; 86 | 87 | if (process.platform !== 'darwin' && process.platform !== 'linux') { 88 | console.log("ember-cli-ramdisk presently only supports Mac and Linux. No ramdisk will be installed. Current: "+process.platform); 89 | return; 90 | } 91 | 92 | try { 93 | if (fs.existsSync(projectTmpPath)) { 94 | if (fs.lstatSync(projectTmpPath).isSymbolicLink()) { 95 | if (fs.readlinkSync(projectTmpPath).indexOf(RAMDISK_PATH) === -1) { 96 | throw new Error("It seems like you've already symlinked your tmp directory elsewhere; please rm it and try again."); 97 | } 98 | return; 99 | } 100 | removeOldTmpDirectory(projectTmpPath, options); 101 | } 102 | 103 | createRamdiskIfNecessary(); 104 | createSymlink(projectTmpPath, app.project.pkg.name); 105 | console.log("ember-cli-ramdisk: your ramdisk has been created at " + RAMDISK_PATH + ". Enjoy your speedy builds."); 106 | } catch(e) { 107 | console.log("ember-cli-ramdisk: WARNING: failed to install ramdisk: ", e.stack); 108 | } 109 | } 110 | }; 111 | --------------------------------------------------------------------------------