os: improve tmpdir performance

PR-URL: https://github.com/nodejs/node/pull/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>
This commit is contained in:
Yagiz Nizipli 2024-09-11 10:46:30 -04:00 committed by GitHub
parent 285c6a0df3
commit 1d2603b53f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 63 additions and 11 deletions

31
benchmark/os/tmpdir.js Normal file
View File

@ -0,0 +1,31 @@
'use strict';
const common = require('../common.js');
const { tmpdir } = require('os');
const assert = require('assert');
const bench = common.createBenchmark(main, {
n: [1e6],
});
function main({ n }) {
// Warm up.
const length = 1024;
const array = [];
for (let i = 0; i < length; ++i) {
array.push(tmpdir());
}
bench.start();
for (let i = 0; i < n; ++i) {
const index = i % length;
array[index] = tmpdir();
}
bench.end(n);
// Verify the entries to prevent dead code elimination from making
// the benchmark invalid.
for (let i = 0; i < length; ++i) {
assert.strictEqual(typeof array[i], 'string');
}
}

View File

@ -31,7 +31,7 @@ const {
SymbolToPrimitive, SymbolToPrimitive,
} = primordials; } = primordials;
const { safeGetenv } = internalBinding('credentials'); const { getTempDir } = internalBinding('credentials');
const constants = internalBinding('constants').os; const constants = internalBinding('constants').os;
const isWindows = process.platform === 'win32'; const isWindows = process.platform === 'win32';
@ -179,24 +179,18 @@ platform[SymbolToPrimitive] = () => process.platform;
* @returns {string} * @returns {string}
*/ */
function tmpdir() { function tmpdir() {
let path;
if (isWindows) { if (isWindows) {
path = process.env.TEMP || let path = process.env.TEMP ||
process.env.TMP || process.env.TMP ||
(process.env.SystemRoot || process.env.windir) + '\\temp'; (process.env.SystemRoot || process.env.windir) + '\\temp';
if (path.length > 1 && StringPrototypeEndsWith(path, '\\') && if (path.length > 1 && StringPrototypeEndsWith(path, '\\') &&
!StringPrototypeEndsWith(path, ':\\')) !StringPrototypeEndsWith(path, ':\\'))
path = StringPrototypeSlice(path, 0, -1); path = StringPrototypeSlice(path, 0, -1);
} else {
path = safeGetenv('TMPDIR') ||
safeGetenv('TMP') ||
safeGetenv('TEMP') ||
'/tmp';
if (path.length > 1 && StringPrototypeEndsWith(path, '/'))
path = StringPrototypeSlice(path, 0, -1);
}
return path; return path;
}
return getTempDir() || '/tmp';
} }
tmpdir[SymbolToPrimitive] = () => tmpdir(); tmpdir[SymbolToPrimitive] = () => tmpdir();

View File

@ -109,6 +109,31 @@ static void SafeGetenv(const FunctionCallbackInfo<Value>& args) {
args.GetReturnValue().Set(result); args.GetReturnValue().Set(result);
} }
static void GetTempDir(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
Isolate* isolate = env->isolate();
std::string dir;
// Let's wrap SafeGetEnv since it returns true for empty string.
auto get_env = [&dir, &env](std::string_view key) {
USE(SafeGetenv(key.data(), &dir, env->env_vars()));
return !dir.empty();
};
// Try TMPDIR, TMP, and TEMP in that order.
if (!get_env("TMPDIR") && !get_env("TMP") && !get_env("TEMP")) {
return;
}
if (dir.size() > 1 && dir.ends_with("/")) {
dir.pop_back();
}
args.GetReturnValue().Set(
ToV8Value(isolate->GetCurrentContext(), dir).ToLocalChecked());
}
#ifdef NODE_IMPLEMENTS_POSIX_CREDENTIALS #ifdef NODE_IMPLEMENTS_POSIX_CREDENTIALS
static const uid_t uid_not_found = static_cast<uid_t>(-1); static const uid_t uid_not_found = static_cast<uid_t>(-1);
@ -456,6 +481,7 @@ static void InitGroups(const FunctionCallbackInfo<Value>& args) {
void RegisterExternalReferences(ExternalReferenceRegistry* registry) { void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
registry->Register(SafeGetenv); registry->Register(SafeGetenv);
registry->Register(GetTempDir);
#ifdef NODE_IMPLEMENTS_POSIX_CREDENTIALS #ifdef NODE_IMPLEMENTS_POSIX_CREDENTIALS
registry->Register(GetUid); registry->Register(GetUid);
@ -478,6 +504,7 @@ static void Initialize(Local<Object> target,
Local<Context> context, Local<Context> context,
void* priv) { void* priv) {
SetMethod(context, target, "safeGetenv", SafeGetenv); SetMethod(context, target, "safeGetenv", SafeGetenv);
SetMethod(context, target, "getTempDir", GetTempDir);
#ifdef NODE_IMPLEMENTS_POSIX_CREDENTIALS #ifdef NODE_IMPLEMENTS_POSIX_CREDENTIALS
Environment* env = Environment::GetCurrent(context); Environment* env = Environment::GetCurrent(context);