Skip to content

Commit a9c52ac

Browse files
committed
cut FS activity down dramatically
* better logging * use mkdir-batch to group mkdirs together and do the less overall work (don’t attempt to re-create the same dirs repeatedly) * rather then writing to output and then doing a copyDereferenceSync to the cache, we just write to cache and link to output
1 parent 4473090 commit a9c52ac

File tree

2 files changed

+63
-21
lines changed

2 files changed

+63
-21
lines changed

index.js

+62-21
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
var fs = require('fs');
44
var path = require('path');
5+
var mkdirpBulk = require('mkdirp-bulk');
56
var mkdirp = require('mkdirp');
67
var Promise = require('rsvp').Promise;
78
var Plugin = require('broccoli-plugin');
@@ -50,28 +51,65 @@ function Filter(inputTree, options) {
5051
this._destFilePathCache = Object.create(null);
5152
}
5253

54+
Filter.prototype._resetStats = function() {
55+
this._stats = {
56+
paths: 0,
57+
stale: 0,
58+
mkdirp: 0,
59+
mkdirpCache: 0,
60+
processed: 0,
61+
unprocessed: 0,
62+
hits: 0,
63+
miss: 0,
64+
prime: 0,
65+
hash: 0,
66+
processedTime: 0
67+
};
68+
};
69+
5370
Filter.prototype.build = function build() {
5471
var self = this;
72+
var start = new Date();
73+
this._resetStats();
5574
var srcDir = this.inputPaths[0];
5675
var destDir = this.outputPath;
57-
var paths = walkSync(srcDir);
76+
var paths = walkSync(srcDir).filter(Boolean);
77+
78+
self._stats.paths = paths.length;
79+
self._stats.walkSyncTime = new Date() - start;
5880

5981
this._cache.deleteExcept(paths).forEach(function(key) {
82+
self._stats.stale++;
6083
fs.unlinkSync(this.cachePath + '/' + key);
6184
}, this);
6285

86+
self._stats.mkdirp += mkdirpBulk.sync(paths.map(function(p) {
87+
return self.outputPath + '/' + p;
88+
}));
89+
90+
if (this._cacheDirsPrimed === undefined) {
91+
this._cacheDirsPrimed = true;
92+
self._stats.mkdirp += mkdirpBulk.sync(paths.map(function(p) {
93+
return self.cachePath + '/' + p;
94+
}));
95+
}
96+
6397
return mapSeries(paths, function rebuildEntry(relativePath) {
6498
var destPath = destDir + '/' + relativePath;
6599
if (relativePath.slice(-1) === '/') {
66-
mkdirp.sync(destPath);
67100
} else {
68101
if (self.canProcessFile(relativePath)) {
102+
self._stats.processed++;
69103
return self.processAndCacheFile(srcDir, destDir, relativePath);
70104
} else {
105+
self._stats.unprocessed++;
71106
var srcPath = srcDir + '/' + relativePath;
72107
symlinkOrCopySync(srcPath, destPath);
73108
}
74109
}
110+
}).finally(function() {
111+
self._cacheDirsPrimed = false;
112+
self._debug('build %o in %dms', self._stats, new Date() - start);
75113
});
76114
};
77115

@@ -98,29 +136,34 @@ Filter.prototype.getDestFilePath = function getDestFilePath(relativePath) {
98136

99137
Filter.prototype.processAndCacheFile =
100138
function processAndCacheFile(srcDir, destDir, relativePath) {
139+
var start = new Date();
101140
var self = this;
102141
var cacheEntry = this._cache.get(relativePath);
142+
var result;
103143

104144
if (cacheEntry) {
145+
this._stats.hash++;
105146
var hashResult = hash(srcDir, cacheEntry.inputFile);
106147

107148
if (cacheEntry.hash.hash === hashResult.hash) {
108-
this._debug('cache hit: %s', relativePath);
149+
this._stats.hits++;
109150

110-
return symlinkOrCopyFromCache(cacheEntry, destDir, relativePath);
151+
symlinkOrCopySync(cacheEntry.cacheFile, destDir + '/' + relativePath);
152+
this._stats.processedTime += new Date() - start;
153+
return result;
111154
} else {
112-
this._debug('cache miss: %s \n - previous: %o \n - next: %o ', relativePath, cacheEntry.hash.key, hashResult.key);
155+
this._stats.miss++;
113156
}
114157

115158
} else {
116-
this._debug('cache prime: %s', relativePath);
159+
this._stats.prime++;
117160
}
118161

119162
return Promise.resolve().
120163
then(function asyncProcessFile() {
121164
return self.processFile(srcDir, destDir, relativePath);
122165
}).
123-
then(copyToCache,
166+
then(linkFromCache,
124167
// TODO(@caitp): error wrapper is for API compat, but is not particularly
125168
// useful.
126169
// istanbul ignore next
@@ -129,23 +172,28 @@ Filter.prototype.processAndCacheFile =
129172
e.file = relativePath;
130173
e.treeDir = srcDir;
131174
throw e;
132-
})
175+
}).finally(function() {
176+
self._stats.processedTime += new Date() - start;
177+
});
178+
179+
function linkFromCache() {
180+
self._stats.hash++;
133181

134-
function copyToCache() {
135182
var entry = {
136183
hash: hash(srcDir, relativePath),
137184
inputFile: relativePath,
138185
outputFile: destDir + '/' + self.getDestFilePath(relativePath),
139186
cacheFile: self.cachePath + '/' + relativePath
140187
};
141188

142-
if (fs.existsSync(entry.cacheFile)) {
143-
fs.unlinkSync(entry.cacheFile);
144-
} else {
189+
if (fs.existsSync(entry.outputFile)) {
190+
fs.unlinkSync(entry.outputFile);
191+
} else if (self._cacheDirsPrimed === false) {
192+
self._stats.mkdirpCache++;
145193
mkdirp.sync(path.dirname(entry.cacheFile));
146194
}
147195

148-
copyDereferenceSync(entry.outputFile, entry.cacheFile);
196+
symlinkOrCopySync(entry.cacheFile, entry.outputFile);
149197

150198
return self._cache.set(relativePath, entry);
151199
}
@@ -167,8 +215,7 @@ Filter.prototype.processFile =
167215
if (outputPath == null) {
168216
throw new Error('canProcessFile("' + relativePath + '") is true, but getDestFilePath("' + relativePath + '") is null');
169217
}
170-
outputPath = destDir + '/' + outputPath;
171-
mkdirp.sync(path.dirname(outputPath));
218+
outputPath = self.cachePath + '/' + outputPath;
172219
fs.writeFileSync(outputPath, outputString, {
173220
encoding: outputEncoding
174221
});
@@ -196,9 +243,3 @@ function hash(src, filePath) {
196243
])
197244
};
198245
}
199-
200-
function symlinkOrCopyFromCache(entry, dest, relativePath) {
201-
mkdirp.sync(path.dirname(entry.outputFile));
202-
203-
symlinkOrCopySync(entry.cacheFile, dest + '/' + relativePath);
204-
}

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
"copy-dereference": "^1.0.0",
3131
"debug": "^2.2.0",
3232
"mkdirp": "^0.5.1",
33+
"mkdirp-bulk": "^1.0.0",
3334
"promise-map-series": "^0.2.1",
3435
"rsvp": "^3.0.18",
3536
"symlink-or-copy": "^1.0.1",

0 commit comments

Comments
 (0)