Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Conversation

@janvorli
Copy link
Member

This change removes dependency on the libuuid library that is used for GUID creation only.
It implements it using a random generator instead.

It also modifies return type of PAL_Random to VOID since it was always
returning TRUE and none of the existing callers were checking it.

Close #16642

This change removes dependency on the libuuid library that is used for GUID creation only.
It implements it using a random generator instead.

It also modifies return type of PAL_Random to VOID since it was always
returning TRUE and none of the existing callers were checking it.
@janvorli janvorli added this to the 2.1.0 milestone Feb 28, 2018
@janvorli janvorli self-assigned this Feb 28, 2018
@janvorli
Copy link
Member Author

CC: @Petermarcu

PAL_TerminateEx
PAL_IsDebuggerPresent
PAL_ProbeMemory
PAL_Random
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to export PAL_Random here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because the CoCreateGuid depends on it and it is now in palrt. I've moved CoCreateGuid to palrt.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be more precise mscordbi depends on symbols exported by mscordac and mscordbi uses CoCreateGuid, so it needs access to the underlying PAL_Random.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok


; Win32 API and other PAL functions used by the mscorlib
CloseHandle
CoCreateGuid
Copy link
Member

@jkotas jkotas Feb 28, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CoreLib is still PInvoking this one. The CI tests are failing on Unix because of it. I think we should:

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good idea, I will do it.

// time_hi_and_version
pguid->Data3 = (pguid->Data3 & ~VersionMask) | RandomGuidVersion;
// clock_seq_hi_and_reserved
pguid->Data4[0] = (pguid->Data4[0] & ~ClockSeqHiAndReservedMask) | ClockSeqHiAndReservedValue;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At one point we had an issue related to guid perf:
https://github.com/dotnet/corefx/issues/3573
Have you looked to see how this compares to the previous implementation?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, I've completely forgotten that we were using PAL_Random and had that perf issue in the past. I'll make the change recommended by @jkotas and try to make sure the perf doesn't degrade.

1. Port the GUID creation to managed code.
2. Modify the PAL_Random to have 6 times better perf so that the perf of the
   CoCreateGuid that is used in the native runtime doesn't degrade that much
   w.r.t the previous state when the libuuid was used.
@janvorli
Copy link
Member Author

janvorli commented Mar 1, 2018

@jkotas, @stephentoub I've added the managed implementation and also improved the performance of the native implementation (by improving the PAL_random performance 6 times). The largest part of the improvement was achieved by reading all the bytes at once instead of byte by byte. A smaller part by dropping the usage of /dev/random and using only /dev/urandom. It seems there was a myth about the /dev/random being "better" random, but I've found a document that demystifies that and also a recent change to the man page of the /dev/random and /dev/urandom that made it clearer that there is nothing wrong with just using the /dev/urandom. See https://www.2uo.de/myths-about-urandom/ if you are interested.

{
partial struct Guid
{
static Random _random = new Random();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not think that Random is good enough for GUID generation. It needs to go to PAL Random, like this: https://github.com/dotnet/corert/blob/master/src/System.Private.CoreLib/src/System/Guid.Unix.cs

// how extensively it checks for known values.

Guid g;
int hr = Interop.mincore.CoCreateGuid(out g);
Copy link
Member

@jkotas jkotas Mar 1, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mincore should be renamed to Ole32 to follow the current naming conventions. (CoreRT is using the obsolete naming convention for this. Was not cleaned up yet.)

else
{
for( ; i < dwLength; i++)
size_t index = 0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have copy of this for the corelib/framework use here: https://github.com/dotnet/corefx/blob/master/src/Native/Unix/System.Native/pal_random.cpp

Could you please update that one as well?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Created PR for the change: dotnet/corefx#27601

// we need a method that allows users to create a guid.
public static Guid NewGuid()
{
// CoCreateGuid should never return Guid.Empty, since it attempts to maintain some
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I looked at CoCreateGuid and I do not see any place it checks for known GUIDs.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file was copied from CoreRT. That part of the comment isn't supported by anything in the MSDN doc either. I'll remove it.

janvorli added 3 commits March 1, 2018 11:11
By keeping the file descriptor for /dev/urandom open permanently,
another 2x perf improvement was achieved. The total perf improvement
measured on my physical machine is now 13.75x.
@janvorli janvorli force-pushed the remove-libuuid-usage branch from 847257a to f623c66 Compare March 1, 2018 13:23

Guid g;
int hr = Interop.mincore.CoCreateGuid(out g);
int hr = Microsoft.Win32.Win32Native.CoCreateGuid(out g);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will break CoreRT. Could you please copy over https://github.com/dotnet/corert/blob/master/src/Common/src/Interop/Windows/mincore/Interop.CoCreateGuid.cs, rename it Ole32, and delete Microsoft.Win32.Win32Native.CoCreateGuid ?

{
partial struct Guid
{
// This will create a new guid. Since we've now decided that constructors should 0-init,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we've now decided that constructors should 0-init

Is this comment from, like, 1999? 😄

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No idea :-) Came from CoreRT as well

Guid g = new Guid(randomData);
const int GuidSize = 16;
byte* randomData = stackalloc byte[GuidSize];
Interop.GetRandomBytes(randomData, GuidSize);
Copy link
Member

@jkotas jkotas Mar 1, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be better to do:

Guid g;
Interop.GetRandomBytes(&g, sizeof(Guid));

// in case /dev/urandom is not really random

for(i = 0; i < dwLength; i++)
for (i = 0; i < dwLength; i++)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can someone help me understand why this loop with xor'ing with mrand48 is necessary? My understanding is that /dev/urandom will produce as much cryptographically-strong random data as it can and then fall back to pseudo-random data. How does then mixing it with other prng data from mrand48 help?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it would help. In fact, looking at the man page, it is not thread safe. The main reason why it was here was to work as a fallback in case the /dev/urandom is not present or cannot be opened for some reason.
I guess we can just say that the /dev/urandom is required to be present and if opening it fails, just abort the process. Then we can remove this loop.

@jkotas
Copy link
Member

jkotas commented Mar 1, 2018

What is the performance of NewGuid with all these changes, compared to Windows and uuid implementation?

@janvorli
Copy link
Member Author

janvorli commented Mar 1, 2018

It is 35% faster than the previous uuid version. It is still 8 times slower than on Windows (I've two identical machines, one running Linux and one Windows).

{
partial struct Guid
{
// This will create a new guid. Since we've now decided that constructors should 0-init,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment can be deleted here as well.

// This will create a new random guid based on the https://www.ietf.org/rfc/rfc4122.txt
public static unsafe Guid NewGuid()
{
Guid g = new Guid();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I do not think you need = new Guid() part

do
{
ASSERT("PAL__open() failed, errno:%d (%s)\n", errno, strerror(errno));
fd = open("/dev/urandom", O_RDONLY, O_CLOEXEC);
Copy link
Member

@jkotas jkotas Mar 1, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not think PAL_Random is used for anything perf critical in the runtime itself. I do not think that the caching is worth it in this version.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't any CoCreateGuid call in the runtime perf sensitive? I really cannot tell in some of the cases.
And is it worth having a slightly different implementation in corefx and coreclr just to save one open handle? I've answered your question on the count of open handles in simple hello world app - it is 21 without my change.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If CoCreateGuid is used for anything perf sensitive, then the 8x perf difference between Windows and Unix is still quite a bit of a problem.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same actually true for the framework side of the implementation. 8x is still better than 16x compared to Windows, but you probably do not want to be calling it in too often in any case.

I guess if we wanted to make this better, we would need to cache (read say 256 bytes at a time) or have a local random number generator (with larger seed than the 32-bits of built-in one).

@jkotas
Copy link
Member

jkotas commented Mar 1, 2018

LGTM modulo a few nits

And fixing a little nits.
@janvorli
Copy link
Member Author

janvorli commented Mar 1, 2018

@dotnet-bot test OSX10.12 x64 Checked Innerloop Build and Test

@janvorli
Copy link
Member Author

janvorli commented Mar 1, 2018

@dotnet-bot test Windows_NT arm Cross Checked Innerloop Build and Test

@janvorli
Copy link
Member Author

janvorli commented Mar 1, 2018

@dotnet-bot Windows_NT arm64 Cross Checked Innerloop Build and Test

1 similar comment
@janvorli
Copy link
Member Author

janvorli commented Mar 1, 2018

@dotnet-bot Windows_NT arm64 Cross Checked Innerloop Build and Test

@janvorli
Copy link
Member Author

janvorli commented Mar 1, 2018

@dotnet-bot Windows_NT armlb Cross Checked Innerloop Build and Test

@janvorli
Copy link
Member Author

janvorli commented Mar 1, 2018

@dotnet-bot test Windows_NT arm64 Cross Checked Innerloop Build and Test

@janvorli
Copy link
Member Author

janvorli commented Mar 1, 2018

@dotnet-bot test Windows_NT armlb Cross Checked Innerloop Build and Test

@janvorli
Copy link
Member Author

janvorli commented Mar 2, 2018

@dotnet-bot test OSX10.12 x64 Checked Innerloop Build and Test

@janvorli
Copy link
Member Author

janvorli commented Mar 2, 2018

@dotnet-bot test Windows_NT armlb Cross Checked Innerloop Build and Test

@janvorli
Copy link
Member Author

janvorli commented Mar 2, 2018

@dotnet-bot test Windows_NT arm64 Cross Checked Innerloop Build and Test

@janvorli
Copy link
Member Author

janvorli commented Mar 2, 2018

@dotnet-bot test Windows_NT arm Cross Checked Innerloop Build and Test

1 similar comment
@janvorli
Copy link
Member Author

janvorli commented Mar 2, 2018

@dotnet-bot test Windows_NT arm Cross Checked Innerloop Build and Test

@janvorli
Copy link
Member Author

janvorli commented Mar 5, 2018

@dotnet-bot test Windows_NT arm64 Cross Checked Innerloop Build and Test

@janvorli
Copy link
Member Author

janvorli commented Mar 5, 2018

@dotnet-bot test Windows_NT armlb Cross Checked Innerloop Build and Test

@janvorli
Copy link
Member Author

janvorli commented Mar 5, 2018

@dotnet-bot test OSX10.12 x64 Checked Innerloop Build and Test

@janvorli janvorli merged commit 76245a3 into dotnet:master Mar 6, 2018
@janvorli janvorli deleted the remove-libuuid-usage branch March 6, 2018 01:21
dotnet-bot pushed a commit to dotnet/corert that referenced this pull request Mar 6, 2018
* Remove libuuid usage

This change removes dependency on the libuuid library that is used for GUID creation only.
It implements it using a random generator instead.

It also modifies return type of PAL_Random to VOID since it was always
returning TRUE and none of the existing callers were checking it.

1. Port the GUID creation to managed code.
2. Modify the PAL_Random to have 6 times better perf so that the perf of the
   CoCreateGuid that is used in the native runtime doesn't degrade that much
   w.r.t the previous state when the libuuid was used.
3. Use Interop.GetRandomBytes on Unix and fix Windows

Signed-off-by: dotnet-bot <[email protected]>
dotnet-bot pushed a commit to dotnet/corefx that referenced this pull request Mar 6, 2018
* Remove libuuid usage

This change removes dependency on the libuuid library that is used for GUID creation only.
It implements it using a random generator instead.

It also modifies return type of PAL_Random to VOID since it was always
returning TRUE and none of the existing callers were checking it.

1. Port the GUID creation to managed code.
2. Modify the PAL_Random to have 6 times better perf so that the perf of the
   CoCreateGuid that is used in the native runtime doesn't degrade that much
   w.r.t the previous state when the libuuid was used.
3. Use Interop.GetRandomBytes on Unix and fix Windows

Signed-off-by: dotnet-bot-corefx-mirror <[email protected]>
ahsonkhan pushed a commit to dotnet/corefx that referenced this pull request Mar 6, 2018
* Remove libuuid usage

This change removes dependency on the libuuid library that is used for GUID creation only.
It implements it using a random generator instead.

It also modifies return type of PAL_Random to VOID since it was always
returning TRUE and none of the existing callers were checking it.

1. Port the GUID creation to managed code.
2. Modify the PAL_Random to have 6 times better perf so that the perf of the
   CoCreateGuid that is used in the native runtime doesn't degrade that much
   w.r.t the previous state when the libuuid was used.
3. Use Interop.GetRandomBytes on Unix and fix Windows

Signed-off-by: dotnet-bot-corefx-mirror <[email protected]>
jkotas pushed a commit to dotnet/corert that referenced this pull request Mar 6, 2018
* Remove libuuid usage

This change removes dependency on the libuuid library that is used for GUID creation only.
It implements it using a random generator instead.

It also modifies return type of PAL_Random to VOID since it was always
returning TRUE and none of the existing callers were checking it.

1. Port the GUID creation to managed code.
2. Modify the PAL_Random to have 6 times better perf so that the perf of the
   CoCreateGuid that is used in the native runtime doesn't degrade that much
   w.r.t the previous state when the libuuid was used.
3. Use Interop.GetRandomBytes on Unix and fix Windows

Signed-off-by: dotnet-bot <[email protected]>
jkotas added a commit to dotnet/corert that referenced this pull request Mar 8, 2018
kbaladurin pushed a commit to kbaladurin/corert that referenced this pull request Mar 15, 2018
* Remove libuuid usage

This change removes dependency on the libuuid library that is used for GUID creation only.
It implements it using a random generator instead.

It also modifies return type of PAL_Random to VOID since it was always
returning TRUE and none of the existing callers were checking it.

1. Port the GUID creation to managed code.
2. Modify the PAL_Random to have 6 times better perf so that the perf of the
   CoCreateGuid that is used in the native runtime doesn't degrade that much
   w.r.t the previous state when the libuuid was used.
3. Use Interop.GetRandomBytes on Unix and fix Windows

Signed-off-by: dotnet-bot <[email protected]>
kbaladurin pushed a commit to kbaladurin/corert that referenced this pull request Mar 15, 2018
stephencleary-comments added a commit to StephenCleary/comments.stephencleary.com that referenced this pull request May 23, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants