Skip to content

Commit 9836cf5

Browse files
sciolistrefack
authored andcommitted
lib: lazy instantiation of fs.Stats dates
The method used has code duplication but is the most performant PR-URL: #12818 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Refael Ackermann <[email protected]>
1 parent 485be99 commit 9836cf5

File tree

2 files changed

+92
-4
lines changed

2 files changed

+92
-4
lines changed

lib/fs.js

+70-4
Original file line numberDiff line numberDiff line change
@@ -196,13 +196,79 @@ function Stats(
196196
this.ino = ino;
197197
this.size = size;
198198
this.blocks = blocks;
199-
this.atime = new Date(atim_msec);
200-
this.mtime = new Date(mtim_msec);
201-
this.ctime = new Date(ctim_msec);
202-
this.birthtime = new Date(birthtim_msec);
199+
this._atim_msec = atim_msec;
200+
this._mtim_msec = mtim_msec;
201+
this._ctim_msec = ctim_msec;
202+
this._birthtim_msec = birthtim_msec;
203203
}
204204
fs.Stats = Stats;
205205

206+
// defining the properties in this fashion (explicitly with no loop or factory)
207+
// has been shown to be the most performant on V8 contemp.
208+
// Ref: https://github.com/nodejs/node/pull/12818
209+
Object.defineProperties(Stats.prototype, {
210+
atime: {
211+
configurable: true,
212+
enumerable: true,
213+
get() {
214+
return this._atime !== undefined ?
215+
this._atime :
216+
(this._atime = new Date(this._atim_msec + 0.5));
217+
},
218+
set(value) { return this._atime = value; }
219+
},
220+
mtime: {
221+
configurable: true,
222+
enumerable: true,
223+
get() {
224+
return this._mtime !== undefined ?
225+
this._mtime :
226+
(this._mtime = new Date(this._mtim_msec + 0.5));
227+
},
228+
set(value) { return this._mtime = value; }
229+
},
230+
ctime: {
231+
configurable: true,
232+
enumerable: true,
233+
get() {
234+
return this._ctime !== undefined ?
235+
this._ctime :
236+
(this._ctime = new Date(this._ctim_msec + 0.5));
237+
},
238+
set(value) { return this._ctime = value; }
239+
},
240+
birthtime: {
241+
configurable: true,
242+
enumerable: true,
243+
get() {
244+
return this._birthtime !== undefined ?
245+
this._birthtime :
246+
(this._birthtime = new Date(this._birthtim_msec + 0.5));
247+
},
248+
set(value) { return this._birthtime = value; }
249+
},
250+
});
251+
252+
Stats.prototype.toJSON = function toJSON() {
253+
return {
254+
dev: this.dev,
255+
mode: this.mode,
256+
nlink: this.nlink,
257+
uid: this.uid,
258+
gid: this.gid,
259+
rdev: this.rdev,
260+
blksize: this.blksize,
261+
ino: this.ino,
262+
size: this.size,
263+
blocks: this.blocks,
264+
atime: this.atime,
265+
ctime: this.ctime,
266+
mtime: this.mtime,
267+
birthtime: this.birthtime
268+
};
269+
};
270+
271+
206272
Stats.prototype._checkModeProperty = function(property) {
207273
return ((this.mode & S_IFMT) === property);
208274
};

test/parallel/test-fs-stat.js

+22
Original file line numberDiff line numberDiff line change
@@ -98,5 +98,27 @@ fs.stat(__filename, common.mustCall(function(err, s) {
9898
console.log(`isSymbolicLink: ${JSON.stringify(s.isSymbolicLink())}`);
9999
assert.strictEqual(false, s.isSymbolicLink());
100100

101+
assert.ok(s.atime instanceof Date);
101102
assert.ok(s.mtime instanceof Date);
103+
assert.ok(s.ctime instanceof Date);
104+
assert.ok(s.birthtime instanceof Date);
105+
}));
106+
107+
fs.stat(__filename, common.mustCall(function(err, s) {
108+
const json = JSON.parse(JSON.stringify(s));
109+
const keys = [
110+
'dev', 'mode', 'nlink', 'uid',
111+
'gid', 'rdev', 'ino',
112+
'size', 'atime', 'mtime',
113+
'ctime', 'birthtime'
114+
];
115+
if (!common.isWindows) {
116+
keys.push('blocks', 'blksize');
117+
}
118+
keys.forEach(function(k) {
119+
assert.ok(
120+
json[k] !== undefined && json[k] !== null,
121+
k + ' should not be null or undefined'
122+
);
123+
});
102124
}));

0 commit comments

Comments
 (0)