-
Notifications
You must be signed in to change notification settings - Fork 29.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
src: improve node:os
userInfo performance
#55719
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -287,21 +287,29 @@ static void GetUserInfo(const FunctionCallbackInfo<Value>& args) { | |||||
encoding = UTF8; | ||||||
} | ||||||
|
||||||
const int err = uv_os_get_passwd(&pwd); | ||||||
|
||||||
if (err) { | ||||||
if (const int err = uv_os_get_passwd(&pwd)) { | ||||||
CHECK_GE(args.Length(), 2); | ||||||
env->CollectUVExceptionInfo(args[args.Length() - 1], err, | ||||||
"uv_os_get_passwd"); | ||||||
return args.GetReturnValue().SetUndefined(); | ||||||
} | ||||||
|
||||||
auto free_passwd = OnScopeLeave([&]() { uv_os_free_passwd(&pwd); }); | ||||||
auto free_passwd = OnScopeLeave([&] { uv_os_free_passwd(&pwd); }); | ||||||
|
||||||
Local<Value> error; | ||||||
|
||||||
#ifdef _WIN32 | ||||||
Local<Value> uid = Number::New( | ||||||
env->isolate(), | ||||||
static_cast<double>(static_cast<int32_t>(pwd.uid & 0xFFFFFFFF))); | ||||||
Local<Value> gid = Number::New( | ||||||
env->isolate(), | ||||||
static_cast<double>(static_cast<int32_t>(pwd.gid & 0xFFFFFFFF))); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
#else | ||||||
Local<Value> uid = Number::New(env->isolate(), pwd.uid); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The cast to double is implicit, but for Windows you make it explicit... if so then I would suggest making it explicit here:
Suggested change
|
||||||
Local<Value> gid = Number::New(env->isolate(), pwd.gid); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
#endif | ||||||
|
||||||
MaybeLocal<Value> username = StringBytes::Encode(env->isolate(), | ||||||
pwd.username, | ||||||
encoding, | ||||||
|
@@ -323,21 +331,22 @@ static void GetUserInfo(const FunctionCallbackInfo<Value>& args) { | |||||
return; | ||||||
} | ||||||
|
||||||
Local<Object> entry = Object::New(env->isolate()); | ||||||
|
||||||
entry->Set(env->context(), env->uid_string(), uid).Check(); | ||||||
entry->Set(env->context(), env->gid_string(), gid).Check(); | ||||||
entry->Set(env->context(), | ||||||
env->username_string(), | ||||||
username.ToLocalChecked()).Check(); | ||||||
entry->Set(env->context(), | ||||||
env->homedir_string(), | ||||||
homedir.ToLocalChecked()).Check(); | ||||||
entry->Set(env->context(), | ||||||
env->shell_string(), | ||||||
shell.ToLocalChecked()).Check(); | ||||||
|
||||||
args.GetReturnValue().Set(entry); | ||||||
constexpr size_t kRetLength = 5; | ||||||
std::array<Local<v8::Name>, kRetLength> names = {env->uid_string(), | ||||||
env->gid_string(), | ||||||
env->username_string(), | ||||||
env->homedir_string(), | ||||||
env->shell_string()}; | ||||||
std::array values = {uid, | ||||||
gid, | ||||||
username.ToLocalChecked(), | ||||||
homedir.ToLocalChecked(), | ||||||
shell.ToLocalChecked()}; | ||||||
args.GetReturnValue().Set(Object::New(env->isolate(), | ||||||
Null(env->isolate()), | ||||||
names.data(), | ||||||
values.data(), | ||||||
kRetLength)); | ||||||
} | ||||||
|
||||||
|
||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This has ben discussed and I don't want to block this... but this code might be too complicated. The following might suffice:
So that I understand... we start with this...
(source: libuv documentation.)
node/deps/uv/include/uv.h
Lines 1212 to 1218 in a243225
Under non-Windows systems.
But, for extra fun... under Windows, we have a different definition...
https://github.com/symplely/uv-ffi/blob/8e225f11537f9b34df7030652d00e1343d457ab1/headers/uv_windows.h#L2997C1-L3004C3
A long in Visual Studio is effectively an
int32_t
, it goes from -2,147,483,648 to 2,147,483,647. Whereas an unsigned long is an uint32_t.Most other compiler systems will have long be either int32_t or int64_t (depending on whether we have a 32-bit or 64-bit system). They will have long be either uint32_t or uint64_t.
Now, Number::New's function signature takes a double. So the cast to double is mostly just to show what is happening (as it would happen implicitly).
So, setting aside the cast to double, we are doing...
(If I got something wrong, please tell me.)
What is the purpose of the
0xFFFFFFFF
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I missed these reviews. I'll open another pull-request to apply the changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@anonrig That's fine. I think your code is correct. It was just nitpicking.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The purpose of
& 0xFFFFFFFF
here was to mask higher bits. Unless my knowledge is horribly outdated, casting with overflow here would be UB (even though i doubt existence of implementations that don't just discard extra bits).No strong opinion on casting to
double
, except for 'explicit > implicit' rule of thumb.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An unsigned long under Visual Studio is a 32-bit unsigned integer. So we are casting an uint32 to an int32.
https://learn.microsoft.com/en-us/cpp/cpp/data-type-ranges?view=msvc-170
Node is C++20 and in C++20 casting from unsigned to signed and back is well defined.
I do not care at all. I only remarked that @anonrig's code was not perfectly consistent. I did not ask for the code to change.