Skip to content

Commit 4993694

Browse files
anonrigtpoisseau
authored andcommitted
os: improve tmpdir performance
PR-URL: nodejs#54709 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com> Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
1 parent 7e0d76c commit 4993694

File tree

3 files changed

+63
-11
lines changed

3 files changed

+63
-11
lines changed

benchmark/os/tmpdir.js

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
'use strict';
2+
3+
const common = require('../common.js');
4+
const { tmpdir } = require('os');
5+
const assert = require('assert');
6+
7+
const bench = common.createBenchmark(main, {
8+
n: [1e6],
9+
});
10+
11+
function main({ n }) {
12+
// Warm up.
13+
const length = 1024;
14+
const array = [];
15+
for (let i = 0; i < length; ++i) {
16+
array.push(tmpdir());
17+
}
18+
19+
bench.start();
20+
for (let i = 0; i < n; ++i) {
21+
const index = i % length;
22+
array[index] = tmpdir();
23+
}
24+
bench.end(n);
25+
26+
// Verify the entries to prevent dead code elimination from making
27+
// the benchmark invalid.
28+
for (let i = 0; i < length; ++i) {
29+
assert.strictEqual(typeof array[i], 'string');
30+
}
31+
}

lib/os.js

+5-11
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ const {
3131
SymbolToPrimitive,
3232
} = primordials;
3333

34-
const { safeGetenv } = internalBinding('credentials');
34+
const { getTempDir } = internalBinding('credentials');
3535
const constants = internalBinding('constants').os;
3636
const isWindows = process.platform === 'win32';
3737

@@ -179,24 +179,18 @@ platform[SymbolToPrimitive] = () => process.platform;
179179
* @returns {string}
180180
*/
181181
function tmpdir() {
182-
let path;
183182
if (isWindows) {
184-
path = process.env.TEMP ||
183+
let path = process.env.TEMP ||
185184
process.env.TMP ||
186185
(process.env.SystemRoot || process.env.windir) + '\\temp';
187186
if (path.length > 1 && StringPrototypeEndsWith(path, '\\') &&
188187
!StringPrototypeEndsWith(path, ':\\'))
189188
path = StringPrototypeSlice(path, 0, -1);
190-
} else {
191-
path = safeGetenv('TMPDIR') ||
192-
safeGetenv('TMP') ||
193-
safeGetenv('TEMP') ||
194-
'/tmp';
195-
if (path.length > 1 && StringPrototypeEndsWith(path, '/'))
196-
path = StringPrototypeSlice(path, 0, -1);
189+
190+
return path;
197191
}
198192

199-
return path;
193+
return getTempDir() || '/tmp';
200194
}
201195
tmpdir[SymbolToPrimitive] = () => tmpdir();
202196

src/node_credentials.cc

+27
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,31 @@ static void SafeGetenv(const FunctionCallbackInfo<Value>& args) {
109109
args.GetReturnValue().Set(result);
110110
}
111111

112+
static void GetTempDir(const FunctionCallbackInfo<Value>& args) {
113+
Environment* env = Environment::GetCurrent(args);
114+
Isolate* isolate = env->isolate();
115+
116+
std::string dir;
117+
118+
// Let's wrap SafeGetEnv since it returns true for empty string.
119+
auto get_env = [&dir, &env](std::string_view key) {
120+
USE(SafeGetenv(key.data(), &dir, env->env_vars()));
121+
return !dir.empty();
122+
};
123+
124+
// Try TMPDIR, TMP, and TEMP in that order.
125+
if (!get_env("TMPDIR") && !get_env("TMP") && !get_env("TEMP")) {
126+
return;
127+
}
128+
129+
if (dir.size() > 1 && dir.ends_with("/")) {
130+
dir.pop_back();
131+
}
132+
133+
args.GetReturnValue().Set(
134+
ToV8Value(isolate->GetCurrentContext(), dir).ToLocalChecked());
135+
}
136+
112137
#ifdef NODE_IMPLEMENTS_POSIX_CREDENTIALS
113138

114139
static const uid_t uid_not_found = static_cast<uid_t>(-1);
@@ -456,6 +481,7 @@ static void InitGroups(const FunctionCallbackInfo<Value>& args) {
456481

457482
void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
458483
registry->Register(SafeGetenv);
484+
registry->Register(GetTempDir);
459485

460486
#ifdef NODE_IMPLEMENTS_POSIX_CREDENTIALS
461487
registry->Register(GetUid);
@@ -478,6 +504,7 @@ static void Initialize(Local<Object> target,
478504
Local<Context> context,
479505
void* priv) {
480506
SetMethod(context, target, "safeGetenv", SafeGetenv);
507+
SetMethod(context, target, "getTempDir", GetTempDir);
481508

482509
#ifdef NODE_IMPLEMENTS_POSIX_CREDENTIALS
483510
Environment* env = Environment::GetCurrent(context);

0 commit comments

Comments
 (0)