Skip to content

Commit

Permalink
Improve performance on Linux (#90)
Browse files Browse the repository at this point in the history
  • Loading branch information
Yanis Benson authored and sindresorhus committed Nov 17, 2019
1 parent 2e460f6 commit 7f31f41
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 16 deletions.
59 changes: 43 additions & 16 deletions lib/linux.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,26 @@ const xdgTrashdir = require('xdg-trashdir');
const pMap = require('p-map');
const makeDir = require('make-dir');
const moveFile = require('move-file');
const {procfs} = require('@stroncium/procfs');

const pWriteFile = promisify(fs.writeFile);
const lstat = promisify(fs.lstat);
const writeFile = promisify(fs.writeFile);

const trash = async filePath => {
const trashDirectory = await xdgTrashdir(filePath);
// Educated guess, values of 16 to 64 seem to be optimal for modern SSD, 8-16 and 64-128 can be a bit slower.
// We should be ok as long as ssdCount <= cpuCount <= ssdCount*16.
// For slower media this is not as important and we rely on OS handling it for us.
const concurrency = os.cpus().length * 8;

const trash = async (filePath, trashPaths) => {
const name = uuid.v4();
const destination = path.join(trashDirectory, 'files', name);
const trashInfoPath = path.join(trashDirectory, 'info', `${name}.trashinfo`);
const destination = path.join(trashPaths.filesPath, name);
const trashInfoPath = path.join(trashPaths.infoPath, `${name}.trashinfo`);

const trashInfoData = `
[Trash Info]
Path=${filePath.replace(/\s/g, '%20')}
DeletionDate=${(new Date()).toISOString()}
`.trim();
const trashInfoData = `[Trash Info]\nPath=${filePath.replace(/\s/g, '%20')}\nDeletionDate=${(new Date()).toISOString()}`;

await Promise.all([
moveFile(filePath, destination),
(async () => {
// TODO: Use the `fs.mkdir` with `recursive` option when targeting Node.js 12.
await makeDir(path.dirname(trashInfoPath));
await pWriteFile(trashInfoPath, trashInfoData);
})()
writeFile(trashInfoPath, trashInfoData)
]);

return {
Expand All @@ -38,4 +36,33 @@ DeletionDate=${(new Date()).toISOString()}
};
};

module.exports = async paths => pMap(paths, trash, {concurrency: os.cpus().length});
module.exports = async paths => {
const mountPointMap = new Map(procfs.processMountinfo().map(info => [info.devId, info.mountPoint]));
const trashPathsCache = new Map();

const getDeviceTrashPaths = async devId => {
let trashPathsPromise = trashPathsCache.get(devId);
if (trashPathsPromise === undefined) {
trashPathsPromise = (async () => {
const trashPath = await xdgTrashdir(mountPointMap.get(devId));
const paths = {
filesPath: path.join(trashPath, 'files'),
infoPath: path.join(trashPath, 'info')
};
// TODO: Use the `fs.mkdir` with `recursive` option when targeting Node.js 12.
await makeDir(paths.filesPath);
await makeDir(paths.infoPath);
return paths;
})();
trashPathsCache.set(devId, trashPathsPromise);
}

return trashPathsPromise;
};

return pMap(paths, async filePath => {
const stats = await lstat(filePath);
const trashPaths = await getDeviceTrashPaths(stats.dev);
return trash(filePath, trashPaths);
}, {concurrency});
};
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
"xdg"
],
"dependencies": {
"@stroncium/procfs": "^1.0.0",
"globby": "^7.1.1",
"is-path-inside": "^2.0.0",
"make-dir": "^3.0.0",
Expand Down

0 comments on commit 7f31f41

Please sign in to comment.