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:
parent
285c6a0df3
commit
1d2603b53f
31
benchmark/os/tmpdir.js
Normal file
31
benchmark/os/tmpdir.js
Normal 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');
|
||||||
|
}
|
||||||
|
}
|
16
lib/os.js
16
lib/os.js
@ -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();
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user