Skip to content

Commit b85d5db

Browse files
lukecotterisomorphic-git-bot
authored andcommitted
fix: perf: general performance improvements (#2063)
* refactor: avoid extra call to entry.content() * refactor: avoid extra object creation * perf: combine two map function calls * perf: avoid stat call when savedStats is null
1 parent bb542e4 commit b85d5db

File tree

5 files changed

+83
-61
lines changed

5 files changed

+83
-61
lines changed

js/isomorphic-git/index.cjs

Lines changed: 40 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -979,8 +979,11 @@ function createCache() {
979979
}
980980

981981
async function updateCachedIndexFile(fs, filepath, cache) {
982-
const stat = await fs.lstat(filepath);
983-
const rawIndexFile = await fs.read(filepath);
982+
const [stat, rawIndexFile] = await Promise.all([
983+
fs.lstat(filepath),
984+
fs.read(filepath),
985+
]);
986+
984987
const index = await GitIndex.from(rawIndexFile);
985988
// cache the GitIndex object so we don't need to re-read it every time.
986989
cache.map.set(filepath, index);
@@ -992,8 +995,9 @@ async function updateCachedIndexFile(fs, filepath, cache) {
992995
async function isIndexStale(fs, filepath, cache) {
993996
const savedStats = cache.stats.get(filepath);
994997
if (savedStats === undefined) return true
995-
const currStats = await fs.lstat(filepath);
996998
if (savedStats === null) return false
999+
1000+
const currStats = await fs.lstat(filepath);
9971001
if (currStats === null) return false
9981002
return compareStats(savedStats, currStats)
9991003
}
@@ -1009,7 +1013,9 @@ class GitIndexManager {
10091013
* @param {function(GitIndex): any} closure
10101014
*/
10111015
static async acquire({ fs, gitdir, cache, allowUnmerged = true }, closure) {
1012-
if (!cache[IndexCache]) cache[IndexCache] = createCache();
1016+
if (!cache[IndexCache]) {
1017+
cache[IndexCache] = createCache();
1018+
}
10131019

10141020
const filepath = `${gitdir}/index`;
10151021
if (lock === null) lock = new AsyncLock({ maxPending: Infinity });
@@ -1020,10 +1026,11 @@ class GitIndexManager {
10201026
// to make sure other processes aren't writing to it
10211027
// simultaneously, which could result in a corrupted index.
10221028
// const fileLock = await Lock(filepath)
1023-
if (await isIndexStale(fs, filepath, cache[IndexCache])) {
1024-
await updateCachedIndexFile(fs, filepath, cache[IndexCache]);
1029+
const theIndexCache = cache[IndexCache];
1030+
if (await isIndexStale(fs, filepath, theIndexCache)) {
1031+
await updateCachedIndexFile(fs, filepath, theIndexCache);
10251032
}
1026-
const index = cache[IndexCache].map.get(filepath);
1033+
const index = theIndexCache.map.get(filepath);
10271034
unmergedPaths = index.unmergedPaths;
10281035

10291036
if (unmergedPaths.length && !allowUnmerged)
@@ -1036,7 +1043,7 @@ class GitIndexManager {
10361043
const buffer = await index.toObject();
10371044
await fs.write(filepath, buffer);
10381045
// Update cached stat value
1039-
cache[IndexCache].stats.set(filepath, await fs.lstat(filepath));
1046+
theIndexCache.stats.set(filepath, await fs.lstat(filepath));
10401047
index._dirty = false;
10411048
}
10421049
});
@@ -4261,7 +4268,7 @@ class GitWalkerFs {
42614268
oid = undefined;
42624269
} else {
42634270
oid = await shasum(
4264-
GitObject.wrap({ type: 'blob', object: await entry.content() })
4271+
GitObject.wrap({ type: 'blob', object: content })
42654272
);
42664273
// Update the stats in the index so we will get a "cache hit" next time
42674274
// 1) if we can (because the oid and mode are the same)
@@ -4452,15 +4459,20 @@ async function _walk({
44524459
const range = arrayRange(0, walkers.length);
44534460
const unionWalkerFromReaddir = async entries => {
44544461
range.map(i => {
4455-
entries[i] = entries[i] && new walkers[i].ConstructEntry(entries[i]);
4462+
const entry = entries[i];
4463+
entries[i] = entry && new walkers[i].ConstructEntry(entry);
44564464
});
44574465
const subdirs = await Promise.all(
4458-
range.map(i => (entries[i] ? walkers[i].readdir(entries[i]) : []))
4466+
range.map(i => {
4467+
const entry = entries[i];
4468+
return entry ? walkers[i].readdir(entry) : []
4469+
})
44594470
);
44604471
// Now process child directories
4461-
const iterators = subdirs
4462-
.map(array => (array === null ? [] : array))
4463-
.map(array => array[Symbol.iterator]());
4472+
const iterators = subdirs.map(array => {
4473+
return (array === null ? [] : array)[Symbol.iterator]()
4474+
});
4475+
44644476
return {
44654477
entries,
44664478
children: unionOfIterators(iterators),
@@ -15288,11 +15300,9 @@ async function updateIndex({
1528815300
return await GitIndexManager.acquire(
1528915301
{ fs, gitdir, cache },
1529015302
async function(index) {
15291-
let fileStats;
15292-
1529315303
if (!force) {
1529415304
// Check if the file is still present in the working directory
15295-
fileStats = await fs.lstat(pathBrowserify.join(dir, filepath));
15305+
const fileStats = await fs.lstat(pathBrowserify.join(dir, filepath));
1529615306

1529715307
if (fileStats) {
1529815308
if (fileStats.isDirectory()) {
@@ -15342,18 +15352,7 @@ async function updateIndex({
1534215352
)
1534315353
}
1534415354

15345-
// By default we use 0 for the stats of the index file
15346-
let stats = {
15347-
ctime: new Date(0),
15348-
mtime: new Date(0),
15349-
dev: 0,
15350-
ino: 0,
15351-
mode,
15352-
uid: 0,
15353-
gid: 0,
15354-
size: 0,
15355-
};
15356-
15355+
let stats;
1535715356
if (!oid) {
1535815357
stats = fileStats;
1535915358

@@ -15369,6 +15368,18 @@ async function updateIndex({
1536915368
format: 'content',
1537015369
object,
1537115370
});
15371+
} else {
15372+
// By default we use 0 for the stats of the index file
15373+
stats = {
15374+
ctime: new Date(0),
15375+
mtime: new Date(0),
15376+
dev: 0,
15377+
ino: 0,
15378+
mode,
15379+
uid: 0,
15380+
gid: 0,
15381+
size: 0,
15382+
};
1537215383
}
1537315384

1537415385
index.insert({

js/isomorphic-git/index.js

Lines changed: 40 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -973,8 +973,11 @@ function createCache() {
973973
}
974974

975975
async function updateCachedIndexFile(fs, filepath, cache) {
976-
const stat = await fs.lstat(filepath);
977-
const rawIndexFile = await fs.read(filepath);
976+
const [stat, rawIndexFile] = await Promise.all([
977+
fs.lstat(filepath),
978+
fs.read(filepath),
979+
]);
980+
978981
const index = await GitIndex.from(rawIndexFile);
979982
// cache the GitIndex object so we don't need to re-read it every time.
980983
cache.map.set(filepath, index);
@@ -986,8 +989,9 @@ async function updateCachedIndexFile(fs, filepath, cache) {
986989
async function isIndexStale(fs, filepath, cache) {
987990
const savedStats = cache.stats.get(filepath);
988991
if (savedStats === undefined) return true
989-
const currStats = await fs.lstat(filepath);
990992
if (savedStats === null) return false
993+
994+
const currStats = await fs.lstat(filepath);
991995
if (currStats === null) return false
992996
return compareStats(savedStats, currStats)
993997
}
@@ -1003,7 +1007,9 @@ class GitIndexManager {
10031007
* @param {function(GitIndex): any} closure
10041008
*/
10051009
static async acquire({ fs, gitdir, cache, allowUnmerged = true }, closure) {
1006-
if (!cache[IndexCache]) cache[IndexCache] = createCache();
1010+
if (!cache[IndexCache]) {
1011+
cache[IndexCache] = createCache();
1012+
}
10071013

10081014
const filepath = `${gitdir}/index`;
10091015
if (lock === null) lock = new AsyncLock({ maxPending: Infinity });
@@ -1014,10 +1020,11 @@ class GitIndexManager {
10141020
// to make sure other processes aren't writing to it
10151021
// simultaneously, which could result in a corrupted index.
10161022
// const fileLock = await Lock(filepath)
1017-
if (await isIndexStale(fs, filepath, cache[IndexCache])) {
1018-
await updateCachedIndexFile(fs, filepath, cache[IndexCache]);
1023+
const theIndexCache = cache[IndexCache];
1024+
if (await isIndexStale(fs, filepath, theIndexCache)) {
1025+
await updateCachedIndexFile(fs, filepath, theIndexCache);
10191026
}
1020-
const index = cache[IndexCache].map.get(filepath);
1027+
const index = theIndexCache.map.get(filepath);
10211028
unmergedPaths = index.unmergedPaths;
10221029

10231030
if (unmergedPaths.length && !allowUnmerged)
@@ -1030,7 +1037,7 @@ class GitIndexManager {
10301037
const buffer = await index.toObject();
10311038
await fs.write(filepath, buffer);
10321039
// Update cached stat value
1033-
cache[IndexCache].stats.set(filepath, await fs.lstat(filepath));
1040+
theIndexCache.stats.set(filepath, await fs.lstat(filepath));
10341041
index._dirty = false;
10351042
}
10361043
});
@@ -4255,7 +4262,7 @@ class GitWalkerFs {
42554262
oid = undefined;
42564263
} else {
42574264
oid = await shasum(
4258-
GitObject.wrap({ type: 'blob', object: await entry.content() })
4265+
GitObject.wrap({ type: 'blob', object: content })
42594266
);
42604267
// Update the stats in the index so we will get a "cache hit" next time
42614268
// 1) if we can (because the oid and mode are the same)
@@ -4446,15 +4453,20 @@ async function _walk({
44464453
const range = arrayRange(0, walkers.length);
44474454
const unionWalkerFromReaddir = async entries => {
44484455
range.map(i => {
4449-
entries[i] = entries[i] && new walkers[i].ConstructEntry(entries[i]);
4456+
const entry = entries[i];
4457+
entries[i] = entry && new walkers[i].ConstructEntry(entry);
44504458
});
44514459
const subdirs = await Promise.all(
4452-
range.map(i => (entries[i] ? walkers[i].readdir(entries[i]) : []))
4460+
range.map(i => {
4461+
const entry = entries[i];
4462+
return entry ? walkers[i].readdir(entry) : []
4463+
})
44534464
);
44544465
// Now process child directories
4455-
const iterators = subdirs
4456-
.map(array => (array === null ? [] : array))
4457-
.map(array => array[Symbol.iterator]());
4466+
const iterators = subdirs.map(array => {
4467+
return (array === null ? [] : array)[Symbol.iterator]()
4468+
});
4469+
44584470
return {
44594471
entries,
44604472
children: unionOfIterators(iterators),
@@ -15282,11 +15294,9 @@ async function updateIndex({
1528215294
return await GitIndexManager.acquire(
1528315295
{ fs, gitdir, cache },
1528415296
async function(index) {
15285-
let fileStats;
15286-
1528715297
if (!force) {
1528815298
// Check if the file is still present in the working directory
15289-
fileStats = await fs.lstat(join(dir, filepath));
15299+
const fileStats = await fs.lstat(join(dir, filepath));
1529015300

1529115301
if (fileStats) {
1529215302
if (fileStats.isDirectory()) {
@@ -15336,18 +15346,7 @@ async function updateIndex({
1533615346
)
1533715347
}
1533815348

15339-
// By default we use 0 for the stats of the index file
15340-
let stats = {
15341-
ctime: new Date(0),
15342-
mtime: new Date(0),
15343-
dev: 0,
15344-
ino: 0,
15345-
mode,
15346-
uid: 0,
15347-
gid: 0,
15348-
size: 0,
15349-
};
15350-
15349+
let stats;
1535115350
if (!oid) {
1535215351
stats = fileStats;
1535315352

@@ -15363,6 +15362,18 @@ async function updateIndex({
1536315362
format: 'content',
1536415363
object,
1536515364
});
15365+
} else {
15366+
// By default we use 0 for the stats of the index file
15367+
stats = {
15368+
ctime: new Date(0),
15369+
mtime: new Date(0),
15370+
dev: 0,
15371+
ino: 0,
15372+
mode,
15373+
uid: 0,
15374+
gid: 0,
15375+
size: 0,
15376+
};
1536615377
}
1536715378

1536815379
index.insert({

js/isomorphic-git/index.umd.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

js/isomorphic-git/index.umd.min.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

js/isomorphic-git/size_report.html

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)