Fix #91958: use mach_timebase_info to determine process time coefficient on macOS - #92185

Merged
adamsitnik merged 7 commits into
dotnet:mainfrom
ForNeVeR:bugfix/91958.macos-cpu-time
Oct 16, 2023
Merged

Fix #91958: use mach_timebase_info to determine process time coefficient on macOS#92185
adamsitnik merged 7 commits into
dotnet:mainfrom
ForNeVeR:bugfix/91958.macos-cpu-time

Conversation

@ForNeVeR

@ForNeVeRForNeVeR commented Sep 16, 2023

Copy link
Copy Markdown
Contributor

Closes#91958.

I have compared the results of the process timing functions to the results of ps on my M2 MacBook device, and they seem to work properly after the changes.

The new tests were properly failing before the change (since we were returning values 42 times lower than the native results), and are, of course, green after the changes.

@ghostghost added area-System.Diagnostics.Process community-contribution Indicates that the PR has been added by a community member labels Sep 16, 2023
@ghost

Copy link
Copy Markdown

Tagging subscribers to this area: @dotnet/area-system-diagnostics-process
See info in area-owners.md if you want to be subscribed.

Issue Details

null

Author:ForNeVeR
Assignees:-
Labels:

area-System.Diagnostics.Process

Milestone:-

Comment threadsrc/libraries/System.Diagnostics.Process/tests/ProcessTests.Unix.cs Outdated

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Overall it looks good, but I found few places that could be polished a bit.

Thank you for your contribution @ForNeVeR !

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@jkoritzinsky@AaronRobinsonMSFT In terms of marshaller best practices, do we need to explicitly specify sequential layout for such structs?

Suggested change
publicstruct mach_timebase_info_data_t
[StructLayout(LayoutKind.Sequential)]
publicstruct mach_timebase_info_data_t

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Technically, no. Value types in .NET default to sequential layout. However, and this is annoying, there are some Roslyn warnings that are suppressed if one does explicitly mark the type with sequential layout. The reasoning here is historical, but the gist is if Roslyn complains about unreferenced fields, which can happen for types used in interop, then placing StructLayout(LayoutKind.Sequential) on the type will automatically suppress the warning.

The interop team's general guidance here has been to accept the defaults except where there is annoying friction with C# or where the tooling requires explicit details. This falls into the C# friction bucket, but only if a warning is emitted.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@AaronRobinsonMSFT thank you for a very detailed answer!

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I can't see any related warnings in the compilation (and also we seem to have warnings as errors enabled in this part?).

Does this mean this attribute is unnecessary? I am totally okay with adding that if required. Though, yeah, we all know that sequential is the default struct layout 😅

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Does this mean this attribute is unnecessary?

Yes.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It would be better to initialize this field lazily, when we need it for the first time. Otherwise this sys-call:

  • may be called even if we don't need it (during type initializaiton)
  • in theory it may fail and be very hard to handle properly

Since we use the following logic in 4 places:

returnnewTimeSpan(Convert.ToInt64($ulong*timeBase.numer/timeBase.denom/NanosecondsTo100NanosecondsFactor));

we could introduce a helper method that could take care of everything, something like this:

Suggested change
privatestaticreadonlyInterop.libSystem.mach_timebase_info_data_ttimeBase=GetTimeBase();
privatestaticvolatileuints_timeBase_numer,s_timeBase_denom;
privatestaticTimeSpanMap(ulongsysTime)
{
uintdenom=s_timeBase_denom;
if(denom==default)
{
Interop.libSystem.mach_timebase_info_data_ttimeBase=GetTimeBase();
s_timeBase_denom=denom=timeBase.denom;
s_timeBase_numer=timeBase.numer;
}
uintnumer=s_timeBase_numer;
returnnewTimeSpan(Convert.ToInt64(sysTime*numer/denom/NanosecondsTo100NanosecondsFactor));
}

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Yeah, agree with your reasoning and applied a bit modified version of this snippet (the only change is in naming, I like MapTime a little bit better).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

thank you for finding and updating all use cases! 👍

Comment threadsrc/libraries/System.Diagnostics.Process/tests/ProcessTests.Unix.cs Outdated
@adamsitnikadamsitnik added this to the 9.0.0 milestone Sep 22, 2023
@ForNeVeR

Copy link
Copy Markdown
ContributorAuthor

Build on CI is now failing due to something being wrong with SR on Windows. Have I broken that? I need help with resources, I don't think my changes to StringResourcesPath were right.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We have two options:

  1. Include the two keys in test resources:

     <dataname="CantGetAllPids"xml:space="preserve">
    <value>Could not get all running Process IDs.</value>
    </data>
    <dataname="RUsageFailure"xml:space="preserve">
    <value>Failed to set or retrieve rusage information. See the error code for OS-specific error information.</value>
    </data>

    in:


    and delete this hard-coded line.

  2. Include test resources alongside source ones -- separated by semicolon ;:

     <StringResourcesPath>$(MSBuildProjectDirectory)\Resources\Strings.resx;$(MSBuildProjectDirectory)\..\src\Resources\Strings.resx</StringResourcesPath>

    multiple resources seem to be supported.

Option 1 is probably much cleaner that avoids mixing stuff, but I'll defer to others. cc @ViktorHofer

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Agreed. Option 1 is cleaner while it adds some duplication.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should it do the last division first, like here?

https://chromium.googlesource.com/chromium/src/+/refs/tags/58.0.3029.141/base/time/time_mac.cc#43

(I don't know what values it typically returns)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Also I suppose you can store 1000 * denom

I'm sure someone will point out that won't necessarily give the exact same result @tannergooding 🙂

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

That's a good point, but I was concerned about losing some precision due to doing division first. Though I can't wrap my head around it right now. Will try to do more thorough analysis later today.

@ForNeVeRForNeVeRSep 25, 2023

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Ok, here are my thoughts.

Typical tick values are pretty large actually. For comparison, let's consider a program that was working on a single-core CPU for a year.

> [TimeSpan]::FromDays(365).Ticks
315360000000000
> [long]::MaxValue
9223372036854775807

(here I consider long since TimeSpan takes long in its ctor, not ulong)

This means we will overflow on a numer of 29248 (or if our tick value will get significantly bigger, i.e. we take 29000 years into account, or a CPU with 29k cores).

This is very far from being realistic, but it is also much closer than I expected. So, to be on the safe side, let's do the same as Chromium does: divide by our factor first, to get a hundred times more space, by losing some precision.

We may, of course, also do value / (denom * 100) * numer which is relatively the same, yet will lose a bit more precision as well.

@danmoseleydanmoseleySep 25, 2023

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm also OK with asserting that numer is reasonably small ( say < 1000) as an alternative, since we suspect that will always be true. Or assert that the math comes out almost the same in 128 bits.

If not we should try to quantify the rounding error and how much it matters.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

My current suggestion is to leave this as sysTime / NanosecondsTo100NanosecondsFactor * numer / denom.

I am not sure how useful an assertion would be in this code. Perhaps it'd be better to add checked, since we are concerned by overflow? We do not expect this code to be too performance sensitive, so checked might be good.

What do you think?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Not my area, but I"m not sure an exception would be an improvement. I'd be interested in thoughts of a numeric expert like @tannergooding . I'll step aside for area owners to sign off overall...

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I would say that an explicit exception might be an improvement (especially since it would be thrown from a member property such as TotalProcessorTime and not on class init).

But of course, I am ready to listen to other suggestions.

@ForNeVeR
ForNeVeRforce-pushed the bugfix/91958.macos-cpu-time branch from 861ef04 to d81a801CompareSeptember 25, 2023 20:21
@ForNeVeR
ForNeVeRforce-pushed the bugfix/91958.macos-cpu-time branch 2 times, most recently from 080428d to 1a57499CompareSeptember 25, 2023 20:29
@ForNeVeR

Copy link
Copy Markdown
ContributorAuthor

I believe that all the existing feedback is addressed, so I'm waiting for further feedback. Thank you so much for your time, folks.

@marek-safar

Copy link
Copy Markdown
Contributor

@dotnet/area-system-diagnostics-process please review

@EgorBo

Copy link
Copy Markdown
Member

Ping @dotnet/area-system-diagnostics-process

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM, thank you for your fix @ForNeVeR !

And apologies for the delay (I was on a parental leave).

<data name="Argv_IncludeDoubleQuote" xml:space="preserve">
<value>The argv[0] argument cannot include a double quote.</value>
</data>
<data name="CantGetAllPids" xml:space="preserve">

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The fix I've suggested in #92185 (comment) should just work, but I can take care of that in a separate PR to get the fix merged right now.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@adamsitnik
adamsitnik merged commit fb74d89 into dotnet:mainOct 16, 2023
@ForNeVeR

Copy link
Copy Markdown
ContributorAuthor

Thank you so much for help! ❤️

@ForNeVeR
ForNeVeR deleted the bugfix/91958.macos-cpu-time branch October 16, 2023 18:34
@ghostghost locked as resolved and limited conversation to collaborators Nov 15, 2023
@jeffhandley

Copy link
Copy Markdown
Member

/backport to release/8.0-staging

@github-actionsgithub-actionsBot unlocked this conversation Mar 22, 2024
@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/8.0-staging: https://github.com/dotnet/runtime/actions/runs/8385573189

@jeffhandley

Copy link
Copy Markdown
Member

Backporting this fix to 8.0 since this was reported again in #98121.

@github-actions

Copy link
Copy Markdown
Contributor

@jeffhandley backporting to release/8.0-staging failed, the patch most likely resulted in conflicts:

$ git am --3way --ignore-whitespace --keep-non-patch changes.patch
Applying: Fix #91958: use mach_timebase_info to determine process time coefficient on macOS
Using index info to reconstruct a base tree...
M	src/libraries/Common/src/Interop/OSX/Interop.Libraries.cs
Falling back to patching base and 3-way merge...
Auto-merging src/libraries/Common/src/Interop/OSX/Interop.Libraries.cs
CONFLICT (content): Merge conflict in src/libraries/Common/src/Interop/OSX/Interop.Libraries.cs
error: Failed to merge in the changes.
hint: Use 'git am --show-current-patch=diff' to see the failed patch
Patch failed at 0001 Fix #91958: use mach_timebase_info to determine process time coefficient on macOS
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".
Error: The process '/usr/bin/git' failed with exit code 128

Please backport manually!

@github-actions

Copy link
Copy Markdown
Contributor

@jeffhandley an error occurred while backporting to release/8.0-staging, please check the run log for details!

Error: git am failed, most likely due to a merge conflict.

@github-actionsgithub-actionsBot locked as resolved and limited conversation to collaborators Mar 22, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Diagnostics.Processcommunity-contributionIndicates that the PR has been added by a community memberos-mac-os-xmacOS aka OSX

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Process::TotalProcessorTime is about 42 times lower than expected on ARM64 Mac

10 participants

@ForNeVeR@marek-safar@EgorBo@jeffhandley@tmds@am11@adamsitnik@danmoseley@ViktorHofer@AaronRobinsonMSFT
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all \u003cpre\u003e\u003ccode\u003e blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks"); } } catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); } })(); (function(){ try { var __m = "github.com"; var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Fix #91958: use mach_timebase_info to determine process time coefficient on macOS - #92185

Merged
adamsitnik merged 7 commits into
dotnet:mainfrom
ForNeVeR:bugfix/91958.macos-cpu-time
Oct 16, 2023
Merged

Fix #91958: use mach_timebase_info to determine process time coefficient on macOS#92185
adamsitnik merged 7 commits into
dotnet:mainfrom
ForNeVeR:bugfix/91958.macos-cpu-time

Conversation

@ForNeVeR

@ForNeVeRForNeVeR commented Sep 16, 2023

Copy link
Copy Markdown
Contributor

Closes#91958.

I have compared the results of the process timing functions to the results of ps on my M2 MacBook device, and they seem to work properly after the changes.

The new tests were properly failing before the change (since we were returning values 42 times lower than the native results), and are, of course, green after the changes.

@ghostghost added area-System.Diagnostics.Process community-contribution Indicates that the PR has been added by a community member labels Sep 16, 2023
@ghost

Copy link
Copy Markdown

Tagging subscribers to this area: @dotnet/area-system-diagnostics-process
See info in area-owners.md if you want to be subscribed.

Issue Details

null

Author:ForNeVeR
Assignees:-
Labels:

area-System.Diagnostics.Process

Milestone:-

Comment threadsrc/libraries/System.Diagnostics.Process/tests/ProcessTests.Unix.cs Outdated

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Overall it looks good, but I found few places that could be polished a bit.

Thank you for your contribution @ForNeVeR !

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@jkoritzinsky@AaronRobinsonMSFT In terms of marshaller best practices, do we need to explicitly specify sequential layout for such structs?

Suggested change
publicstruct mach_timebase_info_data_t
[StructLayout(LayoutKind.Sequential)]
publicstruct mach_timebase_info_data_t

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Technically, no. Value types in .NET default to sequential layout. However, and this is annoying, there are some Roslyn warnings that are suppressed if one does explicitly mark the type with sequential layout. The reasoning here is historical, but the gist is if Roslyn complains about unreferenced fields, which can happen for types used in interop, then placing StructLayout(LayoutKind.Sequential) on the type will automatically suppress the warning.

The interop team's general guidance here has been to accept the defaults except where there is annoying friction with C# or where the tooling requires explicit details. This falls into the C# friction bucket, but only if a warning is emitted.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@AaronRobinsonMSFT thank you for a very detailed answer!

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I can't see any related warnings in the compilation (and also we seem to have warnings as errors enabled in this part?).

Does this mean this attribute is unnecessary? I am totally okay with adding that if required. Though, yeah, we all know that sequential is the default struct layout 😅

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Does this mean this attribute is unnecessary?

Yes.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It would be better to initialize this field lazily, when we need it for the first time. Otherwise this sys-call:

  • may be called even if we don't need it (during type initializaiton)
  • in theory it may fail and be very hard to handle properly

Since we use the following logic in 4 places:

returnnewTimeSpan(Convert.ToInt64($ulong*timeBase.numer/timeBase.denom/NanosecondsTo100NanosecondsFactor));

we could introduce a helper method that could take care of everything, something like this:

Suggested change
privatestaticreadonlyInterop.libSystem.mach_timebase_info_data_ttimeBase=GetTimeBase();
privatestaticvolatileuints_timeBase_numer,s_timeBase_denom;
privatestaticTimeSpanMap(ulongsysTime)
{
uintdenom=s_timeBase_denom;
if(denom==default)
{
Interop.libSystem.mach_timebase_info_data_ttimeBase=GetTimeBase();
s_timeBase_denom=denom=timeBase.denom;
s_timeBase_numer=timeBase.numer;
}
uintnumer=s_timeBase_numer;
returnnewTimeSpan(Convert.ToInt64(sysTime*numer/denom/NanosecondsTo100NanosecondsFactor));
}

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Yeah, agree with your reasoning and applied a bit modified version of this snippet (the only change is in naming, I like MapTime a little bit better).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

thank you for finding and updating all use cases! 👍

Comment threadsrc/libraries/System.Diagnostics.Process/tests/ProcessTests.Unix.cs Outdated
@adamsitnikadamsitnik added this to the 9.0.0 milestone Sep 22, 2023
@ForNeVeR

Copy link
Copy Markdown
ContributorAuthor

Build on CI is now failing due to something being wrong with SR on Windows. Have I broken that? I need help with resources, I don't think my changes to StringResourcesPath were right.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We have two options:

  1. Include the two keys in test resources:

     <dataname="CantGetAllPids"xml:space="preserve">
    <value>Could not get all running Process IDs.</value>
    </data>
    <dataname="RUsageFailure"xml:space="preserve">
    <value>Failed to set or retrieve rusage information. See the error code for OS-specific error information.</value>
    </data>

    in:


    and delete this hard-coded line.

  2. Include test resources alongside source ones -- separated by semicolon ;:

     <StringResourcesPath>$(MSBuildProjectDirectory)\Resources\Strings.resx;$(MSBuildProjectDirectory)\..\src\Resources\Strings.resx</StringResourcesPath>

    multiple resources seem to be supported.

Option 1 is probably much cleaner that avoids mixing stuff, but I'll defer to others. cc @ViktorHofer

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Agreed. Option 1 is cleaner while it adds some duplication.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should it do the last division first, like here?

https://chromium.googlesource.com/chromium/src/+/refs/tags/58.0.3029.141/base/time/time_mac.cc#43

(I don't know what values it typically returns)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Also I suppose you can store 1000 * denom

I'm sure someone will point out that won't necessarily give the exact same result @tannergooding 🙂

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

That's a good point, but I was concerned about losing some precision due to doing division first. Though I can't wrap my head around it right now. Will try to do more thorough analysis later today.

@ForNeVeRForNeVeRSep 25, 2023

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Ok, here are my thoughts.

Typical tick values are pretty large actually. For comparison, let's consider a program that was working on a single-core CPU for a year.

> [TimeSpan]::FromDays(365).Ticks
315360000000000
> [long]::MaxValue
9223372036854775807

(here I consider long since TimeSpan takes long in its ctor, not ulong)

This means we will overflow on a numer of 29248 (or if our tick value will get significantly bigger, i.e. we take 29000 years into account, or a CPU with 29k cores).

This is very far from being realistic, but it is also much closer than I expected. So, to be on the safe side, let's do the same as Chromium does: divide by our factor first, to get a hundred times more space, by losing some precision.

We may, of course, also do value / (denom * 100) * numer which is relatively the same, yet will lose a bit more precision as well.

@danmoseleydanmoseleySep 25, 2023

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm also OK with asserting that numer is reasonably small ( say < 1000) as an alternative, since we suspect that will always be true. Or assert that the math comes out almost the same in 128 bits.

If not we should try to quantify the rounding error and how much it matters.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

My current suggestion is to leave this as sysTime / NanosecondsTo100NanosecondsFactor * numer / denom.

I am not sure how useful an assertion would be in this code. Perhaps it'd be better to add checked, since we are concerned by overflow? We do not expect this code to be too performance sensitive, so checked might be good.

What do you think?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Not my area, but I"m not sure an exception would be an improvement. I'd be interested in thoughts of a numeric expert like @tannergooding . I'll step aside for area owners to sign off overall...

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I would say that an explicit exception might be an improvement (especially since it would be thrown from a member property such as TotalProcessorTime and not on class init).

But of course, I am ready to listen to other suggestions.

@ForNeVeR
ForNeVeRforce-pushed the bugfix/91958.macos-cpu-time branch from 861ef04 to d81a801CompareSeptember 25, 2023 20:21
@ForNeVeR
ForNeVeRforce-pushed the bugfix/91958.macos-cpu-time branch 2 times, most recently from 080428d to 1a57499CompareSeptember 25, 2023 20:29
@ForNeVeR

Copy link
Copy Markdown
ContributorAuthor

I believe that all the existing feedback is addressed, so I'm waiting for further feedback. Thank you so much for your time, folks.

@marek-safar

Copy link
Copy Markdown
Contributor

@dotnet/area-system-diagnostics-process please review

@EgorBo

Copy link
Copy Markdown
Member

Ping @dotnet/area-system-diagnostics-process

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM, thank you for your fix @ForNeVeR !

And apologies for the delay (I was on a parental leave).

<data name="Argv_IncludeDoubleQuote" xml:space="preserve">
<value>The argv[0] argument cannot include a double quote.</value>
</data>
<data name="CantGetAllPids" xml:space="preserve">

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The fix I've suggested in #92185 (comment) should just work, but I can take care of that in a separate PR to get the fix merged right now.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@adamsitnik
adamsitnik merged commit fb74d89 into dotnet:mainOct 16, 2023
@ForNeVeR

Copy link
Copy Markdown
ContributorAuthor

Thank you so much for help! ❤️

@ForNeVeR
ForNeVeR deleted the bugfix/91958.macos-cpu-time branch October 16, 2023 18:34
@ghostghost locked as resolved and limited conversation to collaborators Nov 15, 2023
@jeffhandley

Copy link
Copy Markdown
Member

/backport to release/8.0-staging

@github-actionsgithub-actionsBot unlocked this conversation Mar 22, 2024
@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/8.0-staging: https://github.com/dotnet/runtime/actions/runs/8385573189

@jeffhandley

Copy link
Copy Markdown
Member

Backporting this fix to 8.0 since this was reported again in #98121.

@github-actions

Copy link
Copy Markdown
Contributor

@jeffhandley backporting to release/8.0-staging failed, the patch most likely resulted in conflicts:

$ git am --3way --ignore-whitespace --keep-non-patch changes.patch
Applying: Fix #91958: use mach_timebase_info to determine process time coefficient on macOS
Using index info to reconstruct a base tree...
M	src/libraries/Common/src/Interop/OSX/Interop.Libraries.cs
Falling back to patching base and 3-way merge...
Auto-merging src/libraries/Common/src/Interop/OSX/Interop.Libraries.cs
CONFLICT (content): Merge conflict in src/libraries/Common/src/Interop/OSX/Interop.Libraries.cs
error: Failed to merge in the changes.
hint: Use 'git am --show-current-patch=diff' to see the failed patch
Patch failed at 0001 Fix #91958: use mach_timebase_info to determine process time coefficient on macOS
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".
Error: The process '/usr/bin/git' failed with exit code 128

Please backport manually!

@github-actions

Copy link
Copy Markdown
Contributor

@jeffhandley an error occurred while backporting to release/8.0-staging, please check the run log for details!

Error: git am failed, most likely due to a merge conflict.

@github-actionsgithub-actionsBot locked as resolved and limited conversation to collaborators Mar 22, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Diagnostics.Processcommunity-contributionIndicates that the PR has been added by a community memberos-mac-os-xmacOS aka OSX

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Process::TotalProcessorTime is about 42 times lower than expected on ARM64 Mac

10 participants

@ForNeVeR@marek-safar@EgorBo@jeffhandley@tmds@am11@adamsitnik@danmoseley@ViktorHofer@AaronRobinsonMSFT
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Fix #91958: use mach_timebase_info to determine process time coefficient on macOS - #92185

Merged
adamsitnik merged 7 commits into
dotnet:mainfrom
ForNeVeR:bugfix/91958.macos-cpu-time
Oct 16, 2023
Merged

Fix #91958: use mach_timebase_info to determine process time coefficient on macOS#92185
adamsitnik merged 7 commits into
dotnet:mainfrom
ForNeVeR:bugfix/91958.macos-cpu-time

Conversation

@ForNeVeR

@ForNeVeRForNeVeR commented Sep 16, 2023

Copy link
Copy Markdown
Contributor

Closes#91958.

I have compared the results of the process timing functions to the results of ps on my M2 MacBook device, and they seem to work properly after the changes.

The new tests were properly failing before the change (since we were returning values 42 times lower than the native results), and are, of course, green after the changes.

@ghostghost added area-System.Diagnostics.Process community-contribution Indicates that the PR has been added by a community member labels Sep 16, 2023
@ghost

Copy link
Copy Markdown

Tagging subscribers to this area: @dotnet/area-system-diagnostics-process
See info in area-owners.md if you want to be subscribed.

Issue Details

null

Author:ForNeVeR
Assignees:-
Labels:

area-System.Diagnostics.Process

Milestone:-

Comment threadsrc/libraries/System.Diagnostics.Process/tests/ProcessTests.Unix.cs Outdated

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Overall it looks good, but I found few places that could be polished a bit.

Thank you for your contribution @ForNeVeR !

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@jkoritzinsky@AaronRobinsonMSFT In terms of marshaller best practices, do we need to explicitly specify sequential layout for such structs?

Suggested change
publicstruct mach_timebase_info_data_t
[StructLayout(LayoutKind.Sequential)]
publicstruct mach_timebase_info_data_t

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Technically, no. Value types in .NET default to sequential layout. However, and this is annoying, there are some Roslyn warnings that are suppressed if one does explicitly mark the type with sequential layout. The reasoning here is historical, but the gist is if Roslyn complains about unreferenced fields, which can happen for types used in interop, then placing StructLayout(LayoutKind.Sequential) on the type will automatically suppress the warning.

The interop team's general guidance here has been to accept the defaults except where there is annoying friction with C# or where the tooling requires explicit details. This falls into the C# friction bucket, but only if a warning is emitted.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@AaronRobinsonMSFT thank you for a very detailed answer!

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I can't see any related warnings in the compilation (and also we seem to have warnings as errors enabled in this part?).

Does this mean this attribute is unnecessary? I am totally okay with adding that if required. Though, yeah, we all know that sequential is the default struct layout 😅

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Does this mean this attribute is unnecessary?

Yes.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It would be better to initialize this field lazily, when we need it for the first time. Otherwise this sys-call:

  • may be called even if we don't need it (during type initializaiton)
  • in theory it may fail and be very hard to handle properly

Since we use the following logic in 4 places:

returnnewTimeSpan(Convert.ToInt64($ulong*timeBase.numer/timeBase.denom/NanosecondsTo100NanosecondsFactor));

we could introduce a helper method that could take care of everything, something like this:

Suggested change
privatestaticreadonlyInterop.libSystem.mach_timebase_info_data_ttimeBase=GetTimeBase();
privatestaticvolatileuints_timeBase_numer,s_timeBase_denom;
privatestaticTimeSpanMap(ulongsysTime)
{
uintdenom=s_timeBase_denom;
if(denom==default)
{
Interop.libSystem.mach_timebase_info_data_ttimeBase=GetTimeBase();
s_timeBase_denom=denom=timeBase.denom;
s_timeBase_numer=timeBase.numer;
}
uintnumer=s_timeBase_numer;
returnnewTimeSpan(Convert.ToInt64(sysTime*numer/denom/NanosecondsTo100NanosecondsFactor));
}

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Yeah, agree with your reasoning and applied a bit modified version of this snippet (the only change is in naming, I like MapTime a little bit better).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

thank you for finding and updating all use cases! 👍

Comment threadsrc/libraries/System.Diagnostics.Process/tests/ProcessTests.Unix.cs Outdated
@adamsitnikadamsitnik added this to the 9.0.0 milestone Sep 22, 2023
@ForNeVeR

Copy link
Copy Markdown
ContributorAuthor

Build on CI is now failing due to something being wrong with SR on Windows. Have I broken that? I need help with resources, I don't think my changes to StringResourcesPath were right.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We have two options:

  1. Include the two keys in test resources:

     <dataname="CantGetAllPids"xml:space="preserve">
    <value>Could not get all running Process IDs.</value>
    </data>
    <dataname="RUsageFailure"xml:space="preserve">
    <value>Failed to set or retrieve rusage information. See the error code for OS-specific error information.</value>
    </data>

    in:


    and delete this hard-coded line.

  2. Include test resources alongside source ones -- separated by semicolon ;:

     <StringResourcesPath>$(MSBuildProjectDirectory)\Resources\Strings.resx;$(MSBuildProjectDirectory)\..\src\Resources\Strings.resx</StringResourcesPath>

    multiple resources seem to be supported.

Option 1 is probably much cleaner that avoids mixing stuff, but I'll defer to others. cc @ViktorHofer

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Agreed. Option 1 is cleaner while it adds some duplication.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should it do the last division first, like here?

https://chromium.googlesource.com/chromium/src/+/refs/tags/58.0.3029.141/base/time/time_mac.cc#43

(I don't know what values it typically returns)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Also I suppose you can store 1000 * denom

I'm sure someone will point out that won't necessarily give the exact same result @tannergooding 🙂

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

That's a good point, but I was concerned about losing some precision due to doing division first. Though I can't wrap my head around it right now. Will try to do more thorough analysis later today.

@ForNeVeRForNeVeRSep 25, 2023

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Ok, here are my thoughts.

Typical tick values are pretty large actually. For comparison, let's consider a program that was working on a single-core CPU for a year.

> [TimeSpan]::FromDays(365).Ticks
315360000000000
> [long]::MaxValue
9223372036854775807

(here I consider long since TimeSpan takes long in its ctor, not ulong)

This means we will overflow on a numer of 29248 (or if our tick value will get significantly bigger, i.e. we take 29000 years into account, or a CPU with 29k cores).

This is very far from being realistic, but it is also much closer than I expected. So, to be on the safe side, let's do the same as Chromium does: divide by our factor first, to get a hundred times more space, by losing some precision.

We may, of course, also do value / (denom * 100) * numer which is relatively the same, yet will lose a bit more precision as well.

@danmoseleydanmoseleySep 25, 2023

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm also OK with asserting that numer is reasonably small ( say < 1000) as an alternative, since we suspect that will always be true. Or assert that the math comes out almost the same in 128 bits.

If not we should try to quantify the rounding error and how much it matters.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

My current suggestion is to leave this as sysTime / NanosecondsTo100NanosecondsFactor * numer / denom.

I am not sure how useful an assertion would be in this code. Perhaps it'd be better to add checked, since we are concerned by overflow? We do not expect this code to be too performance sensitive, so checked might be good.

What do you think?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Not my area, but I"m not sure an exception would be an improvement. I'd be interested in thoughts of a numeric expert like @tannergooding . I'll step aside for area owners to sign off overall...

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I would say that an explicit exception might be an improvement (especially since it would be thrown from a member property such as TotalProcessorTime and not on class init).

But of course, I am ready to listen to other suggestions.

@ForNeVeR
ForNeVeRforce-pushed the bugfix/91958.macos-cpu-time branch from 861ef04 to d81a801CompareSeptember 25, 2023 20:21
@ForNeVeR
ForNeVeRforce-pushed the bugfix/91958.macos-cpu-time branch 2 times, most recently from 080428d to 1a57499CompareSeptember 25, 2023 20:29
@ForNeVeR

Copy link
Copy Markdown
ContributorAuthor

I believe that all the existing feedback is addressed, so I'm waiting for further feedback. Thank you so much for your time, folks.

@marek-safar

Copy link
Copy Markdown
Contributor

@dotnet/area-system-diagnostics-process please review

@EgorBo

Copy link
Copy Markdown
Member

Ping @dotnet/area-system-diagnostics-process

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM, thank you for your fix @ForNeVeR !

And apologies for the delay (I was on a parental leave).

<data name="Argv_IncludeDoubleQuote" xml:space="preserve">
<value>The argv[0] argument cannot include a double quote.</value>
</data>
<data name="CantGetAllPids" xml:space="preserve">

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The fix I've suggested in #92185 (comment) should just work, but I can take care of that in a separate PR to get the fix merged right now.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@adamsitnik
adamsitnik merged commit fb74d89 into dotnet:mainOct 16, 2023
@ForNeVeR

Copy link
Copy Markdown
ContributorAuthor

Thank you so much for help! ❤️

@ForNeVeR
ForNeVeR deleted the bugfix/91958.macos-cpu-time branch October 16, 2023 18:34
@ghostghost locked as resolved and limited conversation to collaborators Nov 15, 2023
@jeffhandley

Copy link
Copy Markdown
Member

/backport to release/8.0-staging

@github-actionsgithub-actionsBot unlocked this conversation Mar 22, 2024
@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/8.0-staging: https://github.com/dotnet/runtime/actions/runs/8385573189

@jeffhandley

Copy link
Copy Markdown
Member

Backporting this fix to 8.0 since this was reported again in #98121.

@github-actions

Copy link
Copy Markdown
Contributor

@jeffhandley backporting to release/8.0-staging failed, the patch most likely resulted in conflicts:

$ git am --3way --ignore-whitespace --keep-non-patch changes.patch
Applying: Fix #91958: use mach_timebase_info to determine process time coefficient on macOS
Using index info to reconstruct a base tree...
M	src/libraries/Common/src/Interop/OSX/Interop.Libraries.cs
Falling back to patching base and 3-way merge...
Auto-merging src/libraries/Common/src/Interop/OSX/Interop.Libraries.cs
CONFLICT (content): Merge conflict in src/libraries/Common/src/Interop/OSX/Interop.Libraries.cs
error: Failed to merge in the changes.
hint: Use 'git am --show-current-patch=diff' to see the failed patch
Patch failed at 0001 Fix #91958: use mach_timebase_info to determine process time coefficient on macOS
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".
Error: The process '/usr/bin/git' failed with exit code 128

Please backport manually!

@github-actions

Copy link
Copy Markdown
Contributor

@jeffhandley an error occurred while backporting to release/8.0-staging, please check the run log for details!

Error: git am failed, most likely due to a merge conflict.

@github-actionsgithub-actionsBot locked as resolved and limited conversation to collaborators Mar 22, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Diagnostics.Processcommunity-contributionIndicates that the PR has been added by a community memberos-mac-os-xmacOS aka OSX

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Process::TotalProcessorTime is about 42 times lower than expected on ARM64 Mac

10 participants

@ForNeVeR@marek-safar@EgorBo@jeffhandley@tmds@am11@adamsitnik@danmoseley@ViktorHofer@AaronRobinsonMSFT
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length \u003e 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Fix #91958: use mach_timebase_info to determine process time coefficient on macOS - #92185

Merged
adamsitnik merged 7 commits into
dotnet:mainfrom
ForNeVeR:bugfix/91958.macos-cpu-time
Oct 16, 2023
Merged

Fix #91958: use mach_timebase_info to determine process time coefficient on macOS#92185
adamsitnik merged 7 commits into
dotnet:mainfrom
ForNeVeR:bugfix/91958.macos-cpu-time

Conversation

@ForNeVeR

@ForNeVeRForNeVeR commented Sep 16, 2023

Copy link
Copy Markdown
Contributor

Closes#91958.

I have compared the results of the process timing functions to the results of ps on my M2 MacBook device, and they seem to work properly after the changes.

The new tests were properly failing before the change (since we were returning values 42 times lower than the native results), and are, of course, green after the changes.

@ghostghost added area-System.Diagnostics.Process community-contribution Indicates that the PR has been added by a community member labels Sep 16, 2023
@ghost

Copy link
Copy Markdown

Tagging subscribers to this area: @dotnet/area-system-diagnostics-process
See info in area-owners.md if you want to be subscribed.

Issue Details

null

Author:ForNeVeR
Assignees:-
Labels:

area-System.Diagnostics.Process

Milestone:-

Comment threadsrc/libraries/System.Diagnostics.Process/tests/ProcessTests.Unix.cs Outdated

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Overall it looks good, but I found few places that could be polished a bit.

Thank you for your contribution @ForNeVeR !

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@jkoritzinsky@AaronRobinsonMSFT In terms of marshaller best practices, do we need to explicitly specify sequential layout for such structs?

Suggested change
publicstruct mach_timebase_info_data_t
[StructLayout(LayoutKind.Sequential)]
publicstruct mach_timebase_info_data_t

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Technically, no. Value types in .NET default to sequential layout. However, and this is annoying, there are some Roslyn warnings that are suppressed if one does explicitly mark the type with sequential layout. The reasoning here is historical, but the gist is if Roslyn complains about unreferenced fields, which can happen for types used in interop, then placing StructLayout(LayoutKind.Sequential) on the type will automatically suppress the warning.

The interop team's general guidance here has been to accept the defaults except where there is annoying friction with C# or where the tooling requires explicit details. This falls into the C# friction bucket, but only if a warning is emitted.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@AaronRobinsonMSFT thank you for a very detailed answer!

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I can't see any related warnings in the compilation (and also we seem to have warnings as errors enabled in this part?).

Does this mean this attribute is unnecessary? I am totally okay with adding that if required. Though, yeah, we all know that sequential is the default struct layout 😅

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Does this mean this attribute is unnecessary?

Yes.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It would be better to initialize this field lazily, when we need it for the first time. Otherwise this sys-call:

  • may be called even if we don't need it (during type initializaiton)
  • in theory it may fail and be very hard to handle properly

Since we use the following logic in 4 places:

returnnewTimeSpan(Convert.ToInt64($ulong*timeBase.numer/timeBase.denom/NanosecondsTo100NanosecondsFactor));

we could introduce a helper method that could take care of everything, something like this:

Suggested change
privatestaticreadonlyInterop.libSystem.mach_timebase_info_data_ttimeBase=GetTimeBase();
privatestaticvolatileuints_timeBase_numer,s_timeBase_denom;
privatestaticTimeSpanMap(ulongsysTime)
{
uintdenom=s_timeBase_denom;
if(denom==default)
{
Interop.libSystem.mach_timebase_info_data_ttimeBase=GetTimeBase();
s_timeBase_denom=denom=timeBase.denom;
s_timeBase_numer=timeBase.numer;
}
uintnumer=s_timeBase_numer;
returnnewTimeSpan(Convert.ToInt64(sysTime*numer/denom/NanosecondsTo100NanosecondsFactor));
}

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Yeah, agree with your reasoning and applied a bit modified version of this snippet (the only change is in naming, I like MapTime a little bit better).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

thank you for finding and updating all use cases! 👍

Comment threadsrc/libraries/System.Diagnostics.Process/tests/ProcessTests.Unix.cs Outdated
@adamsitnikadamsitnik added this to the 9.0.0 milestone Sep 22, 2023
@ForNeVeR

Copy link
Copy Markdown
ContributorAuthor

Build on CI is now failing due to something being wrong with SR on Windows. Have I broken that? I need help with resources, I don't think my changes to StringResourcesPath were right.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We have two options:

  1. Include the two keys in test resources:

     <dataname="CantGetAllPids"xml:space="preserve">
    <value>Could not get all running Process IDs.</value>
    </data>
    <dataname="RUsageFailure"xml:space="preserve">
    <value>Failed to set or retrieve rusage information. See the error code for OS-specific error information.</value>
    </data>

    in:


    and delete this hard-coded line.

  2. Include test resources alongside source ones -- separated by semicolon ;:

     <StringResourcesPath>$(MSBuildProjectDirectory)\Resources\Strings.resx;$(MSBuildProjectDirectory)\..\src\Resources\Strings.resx</StringResourcesPath>

    multiple resources seem to be supported.

Option 1 is probably much cleaner that avoids mixing stuff, but I'll defer to others. cc @ViktorHofer

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Agreed. Option 1 is cleaner while it adds some duplication.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should it do the last division first, like here?

https://chromium.googlesource.com/chromium/src/+/refs/tags/58.0.3029.141/base/time/time_mac.cc#43

(I don't know what values it typically returns)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Also I suppose you can store 1000 * denom

I'm sure someone will point out that won't necessarily give the exact same result @tannergooding 🙂

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

That's a good point, but I was concerned about losing some precision due to doing division first. Though I can't wrap my head around it right now. Will try to do more thorough analysis later today.

@ForNeVeRForNeVeRSep 25, 2023

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Ok, here are my thoughts.

Typical tick values are pretty large actually. For comparison, let's consider a program that was working on a single-core CPU for a year.

> [TimeSpan]::FromDays(365).Ticks
315360000000000
> [long]::MaxValue
9223372036854775807

(here I consider long since TimeSpan takes long in its ctor, not ulong)

This means we will overflow on a numer of 29248 (or if our tick value will get significantly bigger, i.e. we take 29000 years into account, or a CPU with 29k cores).

This is very far from being realistic, but it is also much closer than I expected. So, to be on the safe side, let's do the same as Chromium does: divide by our factor first, to get a hundred times more space, by losing some precision.

We may, of course, also do value / (denom * 100) * numer which is relatively the same, yet will lose a bit more precision as well.

@danmoseleydanmoseleySep 25, 2023

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm also OK with asserting that numer is reasonably small ( say < 1000) as an alternative, since we suspect that will always be true. Or assert that the math comes out almost the same in 128 bits.

If not we should try to quantify the rounding error and how much it matters.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

My current suggestion is to leave this as sysTime / NanosecondsTo100NanosecondsFactor * numer / denom.

I am not sure how useful an assertion would be in this code. Perhaps it'd be better to add checked, since we are concerned by overflow? We do not expect this code to be too performance sensitive, so checked might be good.

What do you think?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Not my area, but I"m not sure an exception would be an improvement. I'd be interested in thoughts of a numeric expert like @tannergooding . I'll step aside for area owners to sign off overall...

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I would say that an explicit exception might be an improvement (especially since it would be thrown from a member property such as TotalProcessorTime and not on class init).

But of course, I am ready to listen to other suggestions.

@ForNeVeR
ForNeVeRforce-pushed the bugfix/91958.macos-cpu-time branch from 861ef04 to d81a801CompareSeptember 25, 2023 20:21
@ForNeVeR
ForNeVeRforce-pushed the bugfix/91958.macos-cpu-time branch 2 times, most recently from 080428d to 1a57499CompareSeptember 25, 2023 20:29
@ForNeVeR

Copy link
Copy Markdown
ContributorAuthor

I believe that all the existing feedback is addressed, so I'm waiting for further feedback. Thank you so much for your time, folks.

@marek-safar

Copy link
Copy Markdown
Contributor

@dotnet/area-system-diagnostics-process please review

@EgorBo

Copy link
Copy Markdown
Member

Ping @dotnet/area-system-diagnostics-process

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM, thank you for your fix @ForNeVeR !

And apologies for the delay (I was on a parental leave).

<data name="Argv_IncludeDoubleQuote" xml:space="preserve">
<value>The argv[0] argument cannot include a double quote.</value>
</data>
<data name="CantGetAllPids" xml:space="preserve">

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The fix I've suggested in #92185 (comment) should just work, but I can take care of that in a separate PR to get the fix merged right now.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@adamsitnik
adamsitnik merged commit fb74d89 into dotnet:mainOct 16, 2023
@ForNeVeR

Copy link
Copy Markdown
ContributorAuthor

Thank you so much for help! ❤️

@ForNeVeR
ForNeVeR deleted the bugfix/91958.macos-cpu-time branch October 16, 2023 18:34
@ghostghost locked as resolved and limited conversation to collaborators Nov 15, 2023
@jeffhandley

Copy link
Copy Markdown
Member

/backport to release/8.0-staging

@github-actionsgithub-actionsBot unlocked this conversation Mar 22, 2024
@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/8.0-staging: https://github.com/dotnet/runtime/actions/runs/8385573189

@jeffhandley

Copy link
Copy Markdown
Member

Backporting this fix to 8.0 since this was reported again in #98121.

@github-actions

Copy link
Copy Markdown
Contributor

@jeffhandley backporting to release/8.0-staging failed, the patch most likely resulted in conflicts:

$ git am --3way --ignore-whitespace --keep-non-patch changes.patch
Applying: Fix #91958: use mach_timebase_info to determine process time coefficient on macOS
Using index info to reconstruct a base tree...
M	src/libraries/Common/src/Interop/OSX/Interop.Libraries.cs
Falling back to patching base and 3-way merge...
Auto-merging src/libraries/Common/src/Interop/OSX/Interop.Libraries.cs
CONFLICT (content): Merge conflict in src/libraries/Common/src/Interop/OSX/Interop.Libraries.cs
error: Failed to merge in the changes.
hint: Use 'git am --show-current-patch=diff' to see the failed patch
Patch failed at 0001 Fix #91958: use mach_timebase_info to determine process time coefficient on macOS
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".
Error: The process '/usr/bin/git' failed with exit code 128

Please backport manually!

@github-actions

Copy link
Copy Markdown
Contributor

@jeffhandley an error occurred while backporting to release/8.0-staging, please check the run log for details!

Error: git am failed, most likely due to a merge conflict.

@github-actionsgithub-actionsBot locked as resolved and limited conversation to collaborators Mar 22, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Diagnostics.Processcommunity-contributionIndicates that the PR has been added by a community memberos-mac-os-xmacOS aka OSX

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Process::TotalProcessorTime is about 42 times lower than expected on ARM64 Mac

10 participants

@ForNeVeR@marek-safar@EgorBo@jeffhandley@tmds@am11@adamsitnik@danmoseley@ViktorHofer@AaronRobinsonMSFT
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Fix #91958: use mach_timebase_info to determine process time coefficient on macOS - #92185

Merged
adamsitnik merged 7 commits into
dotnet:mainfrom
ForNeVeR:bugfix/91958.macos-cpu-time
Oct 16, 2023
Merged

Fix #91958: use mach_timebase_info to determine process time coefficient on macOS#92185
adamsitnik merged 7 commits into
dotnet:mainfrom
ForNeVeR:bugfix/91958.macos-cpu-time

Conversation

@ForNeVeR

@ForNeVeRForNeVeR commented Sep 16, 2023

Copy link
Copy Markdown
Contributor

Closes#91958.

I have compared the results of the process timing functions to the results of ps on my M2 MacBook device, and they seem to work properly after the changes.

The new tests were properly failing before the change (since we were returning values 42 times lower than the native results), and are, of course, green after the changes.

@ghostghost added area-System.Diagnostics.Process community-contribution Indicates that the PR has been added by a community member labels Sep 16, 2023
@ghost

Copy link
Copy Markdown

Tagging subscribers to this area: @dotnet/area-system-diagnostics-process
See info in area-owners.md if you want to be subscribed.

Issue Details

null

Author:ForNeVeR
Assignees:-
Labels:

area-System.Diagnostics.Process

Milestone:-

Comment threadsrc/libraries/System.Diagnostics.Process/tests/ProcessTests.Unix.cs Outdated

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Overall it looks good, but I found few places that could be polished a bit.

Thank you for your contribution @ForNeVeR !

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@jkoritzinsky@AaronRobinsonMSFT In terms of marshaller best practices, do we need to explicitly specify sequential layout for such structs?

Suggested change
publicstruct mach_timebase_info_data_t
[StructLayout(LayoutKind.Sequential)]
publicstruct mach_timebase_info_data_t

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Technically, no. Value types in .NET default to sequential layout. However, and this is annoying, there are some Roslyn warnings that are suppressed if one does explicitly mark the type with sequential layout. The reasoning here is historical, but the gist is if Roslyn complains about unreferenced fields, which can happen for types used in interop, then placing StructLayout(LayoutKind.Sequential) on the type will automatically suppress the warning.

The interop team's general guidance here has been to accept the defaults except where there is annoying friction with C# or where the tooling requires explicit details. This falls into the C# friction bucket, but only if a warning is emitted.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@AaronRobinsonMSFT thank you for a very detailed answer!

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I can't see any related warnings in the compilation (and also we seem to have warnings as errors enabled in this part?).

Does this mean this attribute is unnecessary? I am totally okay with adding that if required. Though, yeah, we all know that sequential is the default struct layout 😅

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Does this mean this attribute is unnecessary?

Yes.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It would be better to initialize this field lazily, when we need it for the first time. Otherwise this sys-call:

  • may be called even if we don't need it (during type initializaiton)
  • in theory it may fail and be very hard to handle properly

Since we use the following logic in 4 places:

returnnewTimeSpan(Convert.ToInt64($ulong*timeBase.numer/timeBase.denom/NanosecondsTo100NanosecondsFactor));

we could introduce a helper method that could take care of everything, something like this:

Suggested change
privatestaticreadonlyInterop.libSystem.mach_timebase_info_data_ttimeBase=GetTimeBase();
privatestaticvolatileuints_timeBase_numer,s_timeBase_denom;
privatestaticTimeSpanMap(ulongsysTime)
{
uintdenom=s_timeBase_denom;
if(denom==default)
{
Interop.libSystem.mach_timebase_info_data_ttimeBase=GetTimeBase();
s_timeBase_denom=denom=timeBase.denom;
s_timeBase_numer=timeBase.numer;
}
uintnumer=s_timeBase_numer;
returnnewTimeSpan(Convert.ToInt64(sysTime*numer/denom/NanosecondsTo100NanosecondsFactor));
}

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Yeah, agree with your reasoning and applied a bit modified version of this snippet (the only change is in naming, I like MapTime a little bit better).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

thank you for finding and updating all use cases! 👍

Comment threadsrc/libraries/System.Diagnostics.Process/tests/ProcessTests.Unix.cs Outdated
@adamsitnikadamsitnik added this to the 9.0.0 milestone Sep 22, 2023
@ForNeVeR

Copy link
Copy Markdown
ContributorAuthor

Build on CI is now failing due to something being wrong with SR on Windows. Have I broken that? I need help with resources, I don't think my changes to StringResourcesPath were right.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We have two options:

  1. Include the two keys in test resources:

     <dataname="CantGetAllPids"xml:space="preserve">
    <value>Could not get all running Process IDs.</value>
    </data>
    <dataname="RUsageFailure"xml:space="preserve">
    <value>Failed to set or retrieve rusage information. See the error code for OS-specific error information.</value>
    </data>

    in:


    and delete this hard-coded line.

  2. Include test resources alongside source ones -- separated by semicolon ;:

     <StringResourcesPath>$(MSBuildProjectDirectory)\Resources\Strings.resx;$(MSBuildProjectDirectory)\..\src\Resources\Strings.resx</StringResourcesPath>

    multiple resources seem to be supported.

Option 1 is probably much cleaner that avoids mixing stuff, but I'll defer to others. cc @ViktorHofer

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Agreed. Option 1 is cleaner while it adds some duplication.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should it do the last division first, like here?

https://chromium.googlesource.com/chromium/src/+/refs/tags/58.0.3029.141/base/time/time_mac.cc#43

(I don't know what values it typically returns)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Also I suppose you can store 1000 * denom

I'm sure someone will point out that won't necessarily give the exact same result @tannergooding 🙂

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

That's a good point, but I was concerned about losing some precision due to doing division first. Though I can't wrap my head around it right now. Will try to do more thorough analysis later today.

@ForNeVeRForNeVeRSep 25, 2023

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Ok, here are my thoughts.

Typical tick values are pretty large actually. For comparison, let's consider a program that was working on a single-core CPU for a year.

> [TimeSpan]::FromDays(365).Ticks
315360000000000
> [long]::MaxValue
9223372036854775807

(here I consider long since TimeSpan takes long in its ctor, not ulong)

This means we will overflow on a numer of 29248 (or if our tick value will get significantly bigger, i.e. we take 29000 years into account, or a CPU with 29k cores).

This is very far from being realistic, but it is also much closer than I expected. So, to be on the safe side, let's do the same as Chromium does: divide by our factor first, to get a hundred times more space, by losing some precision.

We may, of course, also do value / (denom * 100) * numer which is relatively the same, yet will lose a bit more precision as well.

@danmoseleydanmoseleySep 25, 2023

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm also OK with asserting that numer is reasonably small ( say < 1000) as an alternative, since we suspect that will always be true. Or assert that the math comes out almost the same in 128 bits.

If not we should try to quantify the rounding error and how much it matters.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

My current suggestion is to leave this as sysTime / NanosecondsTo100NanosecondsFactor * numer / denom.

I am not sure how useful an assertion would be in this code. Perhaps it'd be better to add checked, since we are concerned by overflow? We do not expect this code to be too performance sensitive, so checked might be good.

What do you think?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Not my area, but I"m not sure an exception would be an improvement. I'd be interested in thoughts of a numeric expert like @tannergooding . I'll step aside for area owners to sign off overall...

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I would say that an explicit exception might be an improvement (especially since it would be thrown from a member property such as TotalProcessorTime and not on class init).

But of course, I am ready to listen to other suggestions.

@ForNeVeR
ForNeVeRforce-pushed the bugfix/91958.macos-cpu-time branch from 861ef04 to d81a801CompareSeptember 25, 2023 20:21
@ForNeVeR
ForNeVeRforce-pushed the bugfix/91958.macos-cpu-time branch 2 times, most recently from 080428d to 1a57499CompareSeptember 25, 2023 20:29
@ForNeVeR

Copy link
Copy Markdown
ContributorAuthor

I believe that all the existing feedback is addressed, so I'm waiting for further feedback. Thank you so much for your time, folks.

@marek-safar

Copy link
Copy Markdown
Contributor

@dotnet/area-system-diagnostics-process please review

@EgorBo

Copy link
Copy Markdown
Member

Ping @dotnet/area-system-diagnostics-process

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM, thank you for your fix @ForNeVeR !

And apologies for the delay (I was on a parental leave).

<data name="Argv_IncludeDoubleQuote" xml:space="preserve">
<value>The argv[0] argument cannot include a double quote.</value>
</data>
<data name="CantGetAllPids" xml:space="preserve">

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The fix I've suggested in #92185 (comment) should just work, but I can take care of that in a separate PR to get the fix merged right now.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@adamsitnik
adamsitnik merged commit fb74d89 into dotnet:mainOct 16, 2023
@ForNeVeR

Copy link
Copy Markdown
ContributorAuthor

Thank you so much for help! ❤️

@ForNeVeR
ForNeVeR deleted the bugfix/91958.macos-cpu-time branch October 16, 2023 18:34
@ghostghost locked as resolved and limited conversation to collaborators Nov 15, 2023
@jeffhandley

Copy link
Copy Markdown
Member

/backport to release/8.0-staging

@github-actionsgithub-actionsBot unlocked this conversation Mar 22, 2024
@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/8.0-staging: https://github.com/dotnet/runtime/actions/runs/8385573189

@jeffhandley

Copy link
Copy Markdown
Member

Backporting this fix to 8.0 since this was reported again in #98121.

@github-actions

Copy link
Copy Markdown
Contributor

@jeffhandley backporting to release/8.0-staging failed, the patch most likely resulted in conflicts:

$ git am --3way --ignore-whitespace --keep-non-patch changes.patch
Applying: Fix #91958: use mach_timebase_info to determine process time coefficient on macOS
Using index info to reconstruct a base tree...
M	src/libraries/Common/src/Interop/OSX/Interop.Libraries.cs
Falling back to patching base and 3-way merge...
Auto-merging src/libraries/Common/src/Interop/OSX/Interop.Libraries.cs
CONFLICT (content): Merge conflict in src/libraries/Common/src/Interop/OSX/Interop.Libraries.cs
error: Failed to merge in the changes.
hint: Use 'git am --show-current-patch=diff' to see the failed patch
Patch failed at 0001 Fix #91958: use mach_timebase_info to determine process time coefficient on macOS
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".
Error: The process '/usr/bin/git' failed with exit code 128

Please backport manually!

@github-actions

Copy link
Copy Markdown
Contributor

@jeffhandley an error occurred while backporting to release/8.0-staging, please check the run log for details!

Error: git am failed, most likely due to a merge conflict.

@github-actionsgithub-actionsBot locked as resolved and limited conversation to collaborators Mar 22, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Diagnostics.Processcommunity-contributionIndicates that the PR has been added by a community memberos-mac-os-xmacOS aka OSX

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Process::TotalProcessorTime is about 42 times lower than expected on ARM64 Mac

10 participants

@ForNeVeR@marek-safar@EgorBo@jeffhandley@tmds@am11@adamsitnik@danmoseley@ViktorHofer@AaronRobinsonMSFT
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Fix #91958: use mach_timebase_info to determine process time coefficient on macOS - #92185

Merged
adamsitnik merged 7 commits into
dotnet:mainfrom
ForNeVeR:bugfix/91958.macos-cpu-time
Oct 16, 2023
Merged

Fix #91958: use mach_timebase_info to determine process time coefficient on macOS#92185
adamsitnik merged 7 commits into
dotnet:mainfrom
ForNeVeR:bugfix/91958.macos-cpu-time

Conversation

@ForNeVeR

@ForNeVeRForNeVeR commented Sep 16, 2023

Copy link
Copy Markdown
Contributor

Closes#91958.

I have compared the results of the process timing functions to the results of ps on my M2 MacBook device, and they seem to work properly after the changes.

The new tests were properly failing before the change (since we were returning values 42 times lower than the native results), and are, of course, green after the changes.

@ghostghost added area-System.Diagnostics.Process community-contribution Indicates that the PR has been added by a community member labels Sep 16, 2023
@ghost

Copy link
Copy Markdown

Tagging subscribers to this area: @dotnet/area-system-diagnostics-process
See info in area-owners.md if you want to be subscribed.

Issue Details

null

Author:ForNeVeR
Assignees:-
Labels:

area-System.Diagnostics.Process

Milestone:-

Comment threadsrc/libraries/System.Diagnostics.Process/tests/ProcessTests.Unix.cs Outdated

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Overall it looks good, but I found few places that could be polished a bit.

Thank you for your contribution @ForNeVeR !

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@jkoritzinsky@AaronRobinsonMSFT In terms of marshaller best practices, do we need to explicitly specify sequential layout for such structs?

Suggested change
publicstruct mach_timebase_info_data_t
[StructLayout(LayoutKind.Sequential)]
publicstruct mach_timebase_info_data_t

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Technically, no. Value types in .NET default to sequential layout. However, and this is annoying, there are some Roslyn warnings that are suppressed if one does explicitly mark the type with sequential layout. The reasoning here is historical, but the gist is if Roslyn complains about unreferenced fields, which can happen for types used in interop, then placing StructLayout(LayoutKind.Sequential) on the type will automatically suppress the warning.

The interop team's general guidance here has been to accept the defaults except where there is annoying friction with C# or where the tooling requires explicit details. This falls into the C# friction bucket, but only if a warning is emitted.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@AaronRobinsonMSFT thank you for a very detailed answer!

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I can't see any related warnings in the compilation (and also we seem to have warnings as errors enabled in this part?).

Does this mean this attribute is unnecessary? I am totally okay with adding that if required. Though, yeah, we all know that sequential is the default struct layout 😅

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Does this mean this attribute is unnecessary?

Yes.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It would be better to initialize this field lazily, when we need it for the first time. Otherwise this sys-call:

  • may be called even if we don't need it (during type initializaiton)
  • in theory it may fail and be very hard to handle properly

Since we use the following logic in 4 places:

returnnewTimeSpan(Convert.ToInt64($ulong*timeBase.numer/timeBase.denom/NanosecondsTo100NanosecondsFactor));

we could introduce a helper method that could take care of everything, something like this:

Suggested change
privatestaticreadonlyInterop.libSystem.mach_timebase_info_data_ttimeBase=GetTimeBase();
privatestaticvolatileuints_timeBase_numer,s_timeBase_denom;
privatestaticTimeSpanMap(ulongsysTime)
{
uintdenom=s_timeBase_denom;
if(denom==default)
{
Interop.libSystem.mach_timebase_info_data_ttimeBase=GetTimeBase();
s_timeBase_denom=denom=timeBase.denom;
s_timeBase_numer=timeBase.numer;
}
uintnumer=s_timeBase_numer;
returnnewTimeSpan(Convert.ToInt64(sysTime*numer/denom/NanosecondsTo100NanosecondsFactor));
}

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Yeah, agree with your reasoning and applied a bit modified version of this snippet (the only change is in naming, I like MapTime a little bit better).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

thank you for finding and updating all use cases! 👍

Comment threadsrc/libraries/System.Diagnostics.Process/tests/ProcessTests.Unix.cs Outdated
@adamsitnikadamsitnik added this to the 9.0.0 milestone Sep 22, 2023
@ForNeVeR

Copy link
Copy Markdown
ContributorAuthor

Build on CI is now failing due to something being wrong with SR on Windows. Have I broken that? I need help with resources, I don't think my changes to StringResourcesPath were right.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We have two options:

  1. Include the two keys in test resources:

     <dataname="CantGetAllPids"xml:space="preserve">
    <value>Could not get all running Process IDs.</value>
    </data>
    <dataname="RUsageFailure"xml:space="preserve">
    <value>Failed to set or retrieve rusage information. See the error code for OS-specific error information.</value>
    </data>

    in:


    and delete this hard-coded line.

  2. Include test resources alongside source ones -- separated by semicolon ;:

     <StringResourcesPath>$(MSBuildProjectDirectory)\Resources\Strings.resx;$(MSBuildProjectDirectory)\..\src\Resources\Strings.resx</StringResourcesPath>

    multiple resources seem to be supported.

Option 1 is probably much cleaner that avoids mixing stuff, but I'll defer to others. cc @ViktorHofer

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Agreed. Option 1 is cleaner while it adds some duplication.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should it do the last division first, like here?

https://chromium.googlesource.com/chromium/src/+/refs/tags/58.0.3029.141/base/time/time_mac.cc#43

(I don't know what values it typically returns)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Also I suppose you can store 1000 * denom

I'm sure someone will point out that won't necessarily give the exact same result @tannergooding 🙂

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

That's a good point, but I was concerned about losing some precision due to doing division first. Though I can't wrap my head around it right now. Will try to do more thorough analysis later today.

@ForNeVeRForNeVeRSep 25, 2023

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Ok, here are my thoughts.

Typical tick values are pretty large actually. For comparison, let's consider a program that was working on a single-core CPU for a year.

> [TimeSpan]::FromDays(365).Ticks
315360000000000
> [long]::MaxValue
9223372036854775807

(here I consider long since TimeSpan takes long in its ctor, not ulong)

This means we will overflow on a numer of 29248 (or if our tick value will get significantly bigger, i.e. we take 29000 years into account, or a CPU with 29k cores).

This is very far from being realistic, but it is also much closer than I expected. So, to be on the safe side, let's do the same as Chromium does: divide by our factor first, to get a hundred times more space, by losing some precision.

We may, of course, also do value / (denom * 100) * numer which is relatively the same, yet will lose a bit more precision as well.

@danmoseleydanmoseleySep 25, 2023

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm also OK with asserting that numer is reasonably small ( say < 1000) as an alternative, since we suspect that will always be true. Or assert that the math comes out almost the same in 128 bits.

If not we should try to quantify the rounding error and how much it matters.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

My current suggestion is to leave this as sysTime / NanosecondsTo100NanosecondsFactor * numer / denom.

I am not sure how useful an assertion would be in this code. Perhaps it'd be better to add checked, since we are concerned by overflow? We do not expect this code to be too performance sensitive, so checked might be good.

What do you think?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Not my area, but I"m not sure an exception would be an improvement. I'd be interested in thoughts of a numeric expert like @tannergooding . I'll step aside for area owners to sign off overall...

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I would say that an explicit exception might be an improvement (especially since it would be thrown from a member property such as TotalProcessorTime and not on class init).

But of course, I am ready to listen to other suggestions.

@ForNeVeR
ForNeVeRforce-pushed the bugfix/91958.macos-cpu-time branch from 861ef04 to d81a801CompareSeptember 25, 2023 20:21
@ForNeVeR
ForNeVeRforce-pushed the bugfix/91958.macos-cpu-time branch 2 times, most recently from 080428d to 1a57499CompareSeptember 25, 2023 20:29
@ForNeVeR

Copy link
Copy Markdown
ContributorAuthor

I believe that all the existing feedback is addressed, so I'm waiting for further feedback. Thank you so much for your time, folks.

@marek-safar

Copy link
Copy Markdown
Contributor

@dotnet/area-system-diagnostics-process please review

@EgorBo

Copy link
Copy Markdown
Member

Ping @dotnet/area-system-diagnostics-process

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM, thank you for your fix @ForNeVeR !

And apologies for the delay (I was on a parental leave).

<data name="Argv_IncludeDoubleQuote" xml:space="preserve">
<value>The argv[0] argument cannot include a double quote.</value>
</data>
<data name="CantGetAllPids" xml:space="preserve">

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The fix I've suggested in #92185 (comment) should just work, but I can take care of that in a separate PR to get the fix merged right now.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@adamsitnik
adamsitnik merged commit fb74d89 into dotnet:mainOct 16, 2023
@ForNeVeR

Copy link
Copy Markdown
ContributorAuthor

Thank you so much for help! ❤️

@ForNeVeR
ForNeVeR deleted the bugfix/91958.macos-cpu-time branch October 16, 2023 18:34
@ghostghost locked as resolved and limited conversation to collaborators Nov 15, 2023
@jeffhandley

Copy link
Copy Markdown
Member

/backport to release/8.0-staging

@github-actionsgithub-actionsBot unlocked this conversation Mar 22, 2024
@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/8.0-staging: https://github.com/dotnet/runtime/actions/runs/8385573189

@jeffhandley

Copy link
Copy Markdown
Member

Backporting this fix to 8.0 since this was reported again in #98121.

@github-actions

Copy link
Copy Markdown
Contributor

@jeffhandley backporting to release/8.0-staging failed, the patch most likely resulted in conflicts:

$ git am --3way --ignore-whitespace --keep-non-patch changes.patch
Applying: Fix #91958: use mach_timebase_info to determine process time coefficient on macOS
Using index info to reconstruct a base tree...
M	src/libraries/Common/src/Interop/OSX/Interop.Libraries.cs
Falling back to patching base and 3-way merge...
Auto-merging src/libraries/Common/src/Interop/OSX/Interop.Libraries.cs
CONFLICT (content): Merge conflict in src/libraries/Common/src/Interop/OSX/Interop.Libraries.cs
error: Failed to merge in the changes.
hint: Use 'git am --show-current-patch=diff' to see the failed patch
Patch failed at 0001 Fix #91958: use mach_timebase_info to determine process time coefficient on macOS
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".
Error: The process '/usr/bin/git' failed with exit code 128

Please backport manually!

@github-actions

Copy link
Copy Markdown
Contributor

@jeffhandley an error occurred while backporting to release/8.0-staging, please check the run log for details!

Error: git am failed, most likely due to a merge conflict.

@github-actionsgithub-actionsBot locked as resolved and limited conversation to collaborators Mar 22, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Diagnostics.Processcommunity-contributionIndicates that the PR has been added by a community memberos-mac-os-xmacOS aka OSX

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Process::TotalProcessorTime is about 42 times lower than expected on ARM64 Mac

10 participants

@ForNeVeR@marek-safar@EgorBo@jeffhandley@tmds@am11@adamsitnik@danmoseley@ViktorHofer@AaronRobinsonMSFT
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Fix #91958: use mach_timebase_info to determine process time coefficient on macOS - #92185

Merged
adamsitnik merged 7 commits into
dotnet:mainfrom
ForNeVeR:bugfix/91958.macos-cpu-time
Oct 16, 2023
Merged

Fix #91958: use mach_timebase_info to determine process time coefficient on macOS#92185
adamsitnik merged 7 commits into
dotnet:mainfrom
ForNeVeR:bugfix/91958.macos-cpu-time

Conversation

@ForNeVeR

@ForNeVeRForNeVeR commented Sep 16, 2023

Copy link
Copy Markdown
Contributor

Closes#91958.

I have compared the results of the process timing functions to the results of ps on my M2 MacBook device, and they seem to work properly after the changes.

The new tests were properly failing before the change (since we were returning values 42 times lower than the native results), and are, of course, green after the changes.

@ghostghost added area-System.Diagnostics.Process community-contribution Indicates that the PR has been added by a community member labels Sep 16, 2023
@ghost

Copy link
Copy Markdown

Tagging subscribers to this area: @dotnet/area-system-diagnostics-process
See info in area-owners.md if you want to be subscribed.

Issue Details

null

Author:ForNeVeR
Assignees:-
Labels:

area-System.Diagnostics.Process

Milestone:-

Comment threadsrc/libraries/System.Diagnostics.Process/tests/ProcessTests.Unix.cs Outdated

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Overall it looks good, but I found few places that could be polished a bit.

Thank you for your contribution @ForNeVeR !

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@jkoritzinsky@AaronRobinsonMSFT In terms of marshaller best practices, do we need to explicitly specify sequential layout for such structs?

Suggested change
publicstruct mach_timebase_info_data_t
[StructLayout(LayoutKind.Sequential)]
publicstruct mach_timebase_info_data_t

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Technically, no. Value types in .NET default to sequential layout. However, and this is annoying, there are some Roslyn warnings that are suppressed if one does explicitly mark the type with sequential layout. The reasoning here is historical, but the gist is if Roslyn complains about unreferenced fields, which can happen for types used in interop, then placing StructLayout(LayoutKind.Sequential) on the type will automatically suppress the warning.

The interop team's general guidance here has been to accept the defaults except where there is annoying friction with C# or where the tooling requires explicit details. This falls into the C# friction bucket, but only if a warning is emitted.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@AaronRobinsonMSFT thank you for a very detailed answer!

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I can't see any related warnings in the compilation (and also we seem to have warnings as errors enabled in this part?).

Does this mean this attribute is unnecessary? I am totally okay with adding that if required. Though, yeah, we all know that sequential is the default struct layout 😅

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Does this mean this attribute is unnecessary?

Yes.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It would be better to initialize this field lazily, when we need it for the first time. Otherwise this sys-call:

  • may be called even if we don't need it (during type initializaiton)
  • in theory it may fail and be very hard to handle properly

Since we use the following logic in 4 places:

returnnewTimeSpan(Convert.ToInt64($ulong*timeBase.numer/timeBase.denom/NanosecondsTo100NanosecondsFactor));

we could introduce a helper method that could take care of everything, something like this:

Suggested change
privatestaticreadonlyInterop.libSystem.mach_timebase_info_data_ttimeBase=GetTimeBase();
privatestaticvolatileuints_timeBase_numer,s_timeBase_denom;
privatestaticTimeSpanMap(ulongsysTime)
{
uintdenom=s_timeBase_denom;
if(denom==default)
{
Interop.libSystem.mach_timebase_info_data_ttimeBase=GetTimeBase();
s_timeBase_denom=denom=timeBase.denom;
s_timeBase_numer=timeBase.numer;
}
uintnumer=s_timeBase_numer;
returnnewTimeSpan(Convert.ToInt64(sysTime*numer/denom/NanosecondsTo100NanosecondsFactor));
}

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Yeah, agree with your reasoning and applied a bit modified version of this snippet (the only change is in naming, I like MapTime a little bit better).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

thank you for finding and updating all use cases! 👍

Comment threadsrc/libraries/System.Diagnostics.Process/tests/ProcessTests.Unix.cs Outdated
@adamsitnikadamsitnik added this to the 9.0.0 milestone Sep 22, 2023
@ForNeVeR

Copy link
Copy Markdown
ContributorAuthor

Build on CI is now failing due to something being wrong with SR on Windows. Have I broken that? I need help with resources, I don't think my changes to StringResourcesPath were right.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We have two options:

  1. Include the two keys in test resources:

     <dataname="CantGetAllPids"xml:space="preserve">
    <value>Could not get all running Process IDs.</value>
    </data>
    <dataname="RUsageFailure"xml:space="preserve">
    <value>Failed to set or retrieve rusage information. See the error code for OS-specific error information.</value>
    </data>

    in:


    and delete this hard-coded line.

  2. Include test resources alongside source ones -- separated by semicolon ;:

     <StringResourcesPath>$(MSBuildProjectDirectory)\Resources\Strings.resx;$(MSBuildProjectDirectory)\..\src\Resources\Strings.resx</StringResourcesPath>

    multiple resources seem to be supported.

Option 1 is probably much cleaner that avoids mixing stuff, but I'll defer to others. cc @ViktorHofer

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Agreed. Option 1 is cleaner while it adds some duplication.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should it do the last division first, like here?

https://chromium.googlesource.com/chromium/src/+/refs/tags/58.0.3029.141/base/time/time_mac.cc#43

(I don't know what values it typically returns)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Also I suppose you can store 1000 * denom

I'm sure someone will point out that won't necessarily give the exact same result @tannergooding 🙂

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

That's a good point, but I was concerned about losing some precision due to doing division first. Though I can't wrap my head around it right now. Will try to do more thorough analysis later today.

@ForNeVeRForNeVeRSep 25, 2023

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Ok, here are my thoughts.

Typical tick values are pretty large actually. For comparison, let's consider a program that was working on a single-core CPU for a year.

> [TimeSpan]::FromDays(365).Ticks
315360000000000
> [long]::MaxValue
9223372036854775807

(here I consider long since TimeSpan takes long in its ctor, not ulong)

This means we will overflow on a numer of 29248 (or if our tick value will get significantly bigger, i.e. we take 29000 years into account, or a CPU with 29k cores).

This is very far from being realistic, but it is also much closer than I expected. So, to be on the safe side, let's do the same as Chromium does: divide by our factor first, to get a hundred times more space, by losing some precision.

We may, of course, also do value / (denom * 100) * numer which is relatively the same, yet will lose a bit more precision as well.

@danmoseleydanmoseleySep 25, 2023

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm also OK with asserting that numer is reasonably small ( say < 1000) as an alternative, since we suspect that will always be true. Or assert that the math comes out almost the same in 128 bits.

If not we should try to quantify the rounding error and how much it matters.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

My current suggestion is to leave this as sysTime / NanosecondsTo100NanosecondsFactor * numer / denom.

I am not sure how useful an assertion would be in this code. Perhaps it'd be better to add checked, since we are concerned by overflow? We do not expect this code to be too performance sensitive, so checked might be good.

What do you think?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Not my area, but I"m not sure an exception would be an improvement. I'd be interested in thoughts of a numeric expert like @tannergooding . I'll step aside for area owners to sign off overall...

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I would say that an explicit exception might be an improvement (especially since it would be thrown from a member property such as TotalProcessorTime and not on class init).

But of course, I am ready to listen to other suggestions.

@ForNeVeR
ForNeVeRforce-pushed the bugfix/91958.macos-cpu-time branch from 861ef04 to d81a801CompareSeptember 25, 2023 20:21
@ForNeVeR
ForNeVeRforce-pushed the bugfix/91958.macos-cpu-time branch 2 times, most recently from 080428d to 1a57499CompareSeptember 25, 2023 20:29
@ForNeVeR

Copy link
Copy Markdown
ContributorAuthor

I believe that all the existing feedback is addressed, so I'm waiting for further feedback. Thank you so much for your time, folks.

@marek-safar

Copy link
Copy Markdown
Contributor

@dotnet/area-system-diagnostics-process please review

@EgorBo

Copy link
Copy Markdown
Member

Ping @dotnet/area-system-diagnostics-process

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM, thank you for your fix @ForNeVeR !

And apologies for the delay (I was on a parental leave).

<data name="Argv_IncludeDoubleQuote" xml:space="preserve">
<value>The argv[0] argument cannot include a double quote.</value>
</data>
<data name="CantGetAllPids" xml:space="preserve">

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The fix I've suggested in #92185 (comment) should just work, but I can take care of that in a separate PR to get the fix merged right now.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@adamsitnik
adamsitnik merged commit fb74d89 into dotnet:mainOct 16, 2023
@ForNeVeR

Copy link
Copy Markdown
ContributorAuthor

Thank you so much for help! ❤️

@ForNeVeR
ForNeVeR deleted the bugfix/91958.macos-cpu-time branch October 16, 2023 18:34
@ghostghost locked as resolved and limited conversation to collaborators Nov 15, 2023
@jeffhandley

Copy link
Copy Markdown
Member

/backport to release/8.0-staging

@github-actionsgithub-actionsBot unlocked this conversation Mar 22, 2024
@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/8.0-staging: https://github.com/dotnet/runtime/actions/runs/8385573189

@jeffhandley

Copy link
Copy Markdown
Member

Backporting this fix to 8.0 since this was reported again in #98121.

@github-actions

Copy link
Copy Markdown
Contributor

@jeffhandley backporting to release/8.0-staging failed, the patch most likely resulted in conflicts:

$ git am --3way --ignore-whitespace --keep-non-patch changes.patch
Applying: Fix #91958: use mach_timebase_info to determine process time coefficient on macOS
Using index info to reconstruct a base tree...
M	src/libraries/Common/src/Interop/OSX/Interop.Libraries.cs
Falling back to patching base and 3-way merge...
Auto-merging src/libraries/Common/src/Interop/OSX/Interop.Libraries.cs
CONFLICT (content): Merge conflict in src/libraries/Common/src/Interop/OSX/Interop.Libraries.cs
error: Failed to merge in the changes.
hint: Use 'git am --show-current-patch=diff' to see the failed patch
Patch failed at 0001 Fix #91958: use mach_timebase_info to determine process time coefficient on macOS
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".
Error: The process '/usr/bin/git' failed with exit code 128

Please backport manually!

@github-actions

Copy link
Copy Markdown
Contributor

@jeffhandley an error occurred while backporting to release/8.0-staging, please check the run log for details!

Error: git am failed, most likely due to a merge conflict.

@github-actionsgithub-actionsBot locked as resolved and limited conversation to collaborators Mar 22, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Diagnostics.Processcommunity-contributionIndicates that the PR has been added by a community memberos-mac-os-xmacOS aka OSX

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Process::TotalProcessorTime is about 42 times lower than expected on ARM64 Mac

10 participants

@ForNeVeR@marek-safar@EgorBo@jeffhandley@tmds@am11@adamsitnik@danmoseley@ViktorHofer@AaronRobinsonMSFT
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Fix #91958: use mach_timebase_info to determine process time coefficient on macOS - #92185

Merged
adamsitnik merged 7 commits into
dotnet:mainfrom
ForNeVeR:bugfix/91958.macos-cpu-time
Oct 16, 2023
Merged

Fix #91958: use mach_timebase_info to determine process time coefficient on macOS#92185
adamsitnik merged 7 commits into
dotnet:mainfrom
ForNeVeR:bugfix/91958.macos-cpu-time

Conversation

@ForNeVeR

@ForNeVeRForNeVeR commented Sep 16, 2023

Copy link
Copy Markdown
Contributor

Closes#91958.

I have compared the results of the process timing functions to the results of ps on my M2 MacBook device, and they seem to work properly after the changes.

The new tests were properly failing before the change (since we were returning values 42 times lower than the native results), and are, of course, green after the changes.

@ghostghost added area-System.Diagnostics.Process community-contribution Indicates that the PR has been added by a community member labels Sep 16, 2023
@ghost

Copy link
Copy Markdown

Tagging subscribers to this area: @dotnet/area-system-diagnostics-process
See info in area-owners.md if you want to be subscribed.

Issue Details

null

Author:ForNeVeR
Assignees:-
Labels:

area-System.Diagnostics.Process

Milestone:-

Comment threadsrc/libraries/System.Diagnostics.Process/tests/ProcessTests.Unix.cs Outdated

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Overall it looks good, but I found few places that could be polished a bit.

Thank you for your contribution @ForNeVeR !

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@jkoritzinsky@AaronRobinsonMSFT In terms of marshaller best practices, do we need to explicitly specify sequential layout for such structs?

Suggested change
publicstruct mach_timebase_info_data_t
[StructLayout(LayoutKind.Sequential)]
publicstruct mach_timebase_info_data_t

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Technically, no. Value types in .NET default to sequential layout. However, and this is annoying, there are some Roslyn warnings that are suppressed if one does explicitly mark the type with sequential layout. The reasoning here is historical, but the gist is if Roslyn complains about unreferenced fields, which can happen for types used in interop, then placing StructLayout(LayoutKind.Sequential) on the type will automatically suppress the warning.

The interop team's general guidance here has been to accept the defaults except where there is annoying friction with C# or where the tooling requires explicit details. This falls into the C# friction bucket, but only if a warning is emitted.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@AaronRobinsonMSFT thank you for a very detailed answer!

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I can't see any related warnings in the compilation (and also we seem to have warnings as errors enabled in this part?).

Does this mean this attribute is unnecessary? I am totally okay with adding that if required. Though, yeah, we all know that sequential is the default struct layout 😅

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Does this mean this attribute is unnecessary?

Yes.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It would be better to initialize this field lazily, when we need it for the first time. Otherwise this sys-call:

  • may be called even if we don't need it (during type initializaiton)
  • in theory it may fail and be very hard to handle properly

Since we use the following logic in 4 places:

returnnewTimeSpan(Convert.ToInt64($ulong*timeBase.numer/timeBase.denom/NanosecondsTo100NanosecondsFactor));

we could introduce a helper method that could take care of everything, something like this:

Suggested change
privatestaticreadonlyInterop.libSystem.mach_timebase_info_data_ttimeBase=GetTimeBase();
privatestaticvolatileuints_timeBase_numer,s_timeBase_denom;
privatestaticTimeSpanMap(ulongsysTime)
{
uintdenom=s_timeBase_denom;
if(denom==default)
{
Interop.libSystem.mach_timebase_info_data_ttimeBase=GetTimeBase();
s_timeBase_denom=denom=timeBase.denom;
s_timeBase_numer=timeBase.numer;
}
uintnumer=s_timeBase_numer;
returnnewTimeSpan(Convert.ToInt64(sysTime*numer/denom/NanosecondsTo100NanosecondsFactor));
}

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Yeah, agree with your reasoning and applied a bit modified version of this snippet (the only change is in naming, I like MapTime a little bit better).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

thank you for finding and updating all use cases! 👍

Comment threadsrc/libraries/System.Diagnostics.Process/tests/ProcessTests.Unix.cs Outdated
@adamsitnikadamsitnik added this to the 9.0.0 milestone Sep 22, 2023
@ForNeVeR

Copy link
Copy Markdown
ContributorAuthor

Build on CI is now failing due to something being wrong with SR on Windows. Have I broken that? I need help with resources, I don't think my changes to StringResourcesPath were right.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We have two options:

  1. Include the two keys in test resources:

     <dataname="CantGetAllPids"xml:space="preserve">
    <value>Could not get all running Process IDs.</value>
    </data>
    <dataname="RUsageFailure"xml:space="preserve">
    <value>Failed to set or retrieve rusage information. See the error code for OS-specific error information.</value>
    </data>

    in:


    and delete this hard-coded line.

  2. Include test resources alongside source ones -- separated by semicolon ;:

     <StringResourcesPath>$(MSBuildProjectDirectory)\Resources\Strings.resx;$(MSBuildProjectDirectory)\..\src\Resources\Strings.resx</StringResourcesPath>

    multiple resources seem to be supported.

Option 1 is probably much cleaner that avoids mixing stuff, but I'll defer to others. cc @ViktorHofer

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Agreed. Option 1 is cleaner while it adds some duplication.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should it do the last division first, like here?

https://chromium.googlesource.com/chromium/src/+/refs/tags/58.0.3029.141/base/time/time_mac.cc#43

(I don't know what values it typically returns)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Also I suppose you can store 1000 * denom

I'm sure someone will point out that won't necessarily give the exact same result @tannergooding 🙂

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

That's a good point, but I was concerned about losing some precision due to doing division first. Though I can't wrap my head around it right now. Will try to do more thorough analysis later today.

@ForNeVeRForNeVeRSep 25, 2023

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Ok, here are my thoughts.

Typical tick values are pretty large actually. For comparison, let's consider a program that was working on a single-core CPU for a year.

> [TimeSpan]::FromDays(365).Ticks
315360000000000
> [long]::MaxValue
9223372036854775807

(here I consider long since TimeSpan takes long in its ctor, not ulong)

This means we will overflow on a numer of 29248 (or if our tick value will get significantly bigger, i.e. we take 29000 years into account, or a CPU with 29k cores).

This is very far from being realistic, but it is also much closer than I expected. So, to be on the safe side, let's do the same as Chromium does: divide by our factor first, to get a hundred times more space, by losing some precision.

We may, of course, also do value / (denom * 100) * numer which is relatively the same, yet will lose a bit more precision as well.

@danmoseleydanmoseleySep 25, 2023

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm also OK with asserting that numer is reasonably small ( say < 1000) as an alternative, since we suspect that will always be true. Or assert that the math comes out almost the same in 128 bits.

If not we should try to quantify the rounding error and how much it matters.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

My current suggestion is to leave this as sysTime / NanosecondsTo100NanosecondsFactor * numer / denom.

I am not sure how useful an assertion would be in this code. Perhaps it'd be better to add checked, since we are concerned by overflow? We do not expect this code to be too performance sensitive, so checked might be good.

What do you think?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Not my area, but I"m not sure an exception would be an improvement. I'd be interested in thoughts of a numeric expert like @tannergooding . I'll step aside for area owners to sign off overall...

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I would say that an explicit exception might be an improvement (especially since it would be thrown from a member property such as TotalProcessorTime and not on class init).

But of course, I am ready to listen to other suggestions.

@ForNeVeR
ForNeVeRforce-pushed the bugfix/91958.macos-cpu-time branch from 861ef04 to d81a801CompareSeptember 25, 2023 20:21
@ForNeVeR
ForNeVeRforce-pushed the bugfix/91958.macos-cpu-time branch 2 times, most recently from 080428d to 1a57499CompareSeptember 25, 2023 20:29
@ForNeVeR

Copy link
Copy Markdown
ContributorAuthor

I believe that all the existing feedback is addressed, so I'm waiting for further feedback. Thank you so much for your time, folks.

@marek-safar

Copy link
Copy Markdown
Contributor

@dotnet/area-system-diagnostics-process please review

@EgorBo

Copy link
Copy Markdown
Member

Ping @dotnet/area-system-diagnostics-process

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM, thank you for your fix @ForNeVeR !

And apologies for the delay (I was on a parental leave).

<data name="Argv_IncludeDoubleQuote" xml:space="preserve">
<value>The argv[0] argument cannot include a double quote.</value>
</data>
<data name="CantGetAllPids" xml:space="preserve">

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The fix I've suggested in #92185 (comment) should just work, but I can take care of that in a separate PR to get the fix merged right now.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@adamsitnik
adamsitnik merged commit fb74d89 into dotnet:mainOct 16, 2023
@ForNeVeR

Copy link
Copy Markdown
ContributorAuthor

Thank you so much for help! ❤️

@ForNeVeR
ForNeVeR deleted the bugfix/91958.macos-cpu-time branch October 16, 2023 18:34
@ghostghost locked as resolved and limited conversation to collaborators Nov 15, 2023
@jeffhandley

Copy link
Copy Markdown
Member

/backport to release/8.0-staging

@github-actionsgithub-actionsBot unlocked this conversation Mar 22, 2024
@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/8.0-staging: https://github.com/dotnet/runtime/actions/runs/8385573189

@jeffhandley

Copy link
Copy Markdown
Member

Backporting this fix to 8.0 since this was reported again in #98121.

@github-actions

Copy link
Copy Markdown
Contributor

@jeffhandley backporting to release/8.0-staging failed, the patch most likely resulted in conflicts:

$ git am --3way --ignore-whitespace --keep-non-patch changes.patch
Applying: Fix #91958: use mach_timebase_info to determine process time coefficient on macOS
Using index info to reconstruct a base tree...
M	src/libraries/Common/src/Interop/OSX/Interop.Libraries.cs
Falling back to patching base and 3-way merge...
Auto-merging src/libraries/Common/src/Interop/OSX/Interop.Libraries.cs
CONFLICT (content): Merge conflict in src/libraries/Common/src/Interop/OSX/Interop.Libraries.cs
error: Failed to merge in the changes.
hint: Use 'git am --show-current-patch=diff' to see the failed patch
Patch failed at 0001 Fix #91958: use mach_timebase_info to determine process time coefficient on macOS
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".
Error: The process '/usr/bin/git' failed with exit code 128

Please backport manually!

@github-actions

Copy link
Copy Markdown
Contributor

@jeffhandley an error occurred while backporting to release/8.0-staging, please check the run log for details!

Error: git am failed, most likely due to a merge conflict.

@github-actionsgithub-actionsBot locked as resolved and limited conversation to collaborators Mar 22, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Diagnostics.Processcommunity-contributionIndicates that the PR has been added by a community memberos-mac-os-xmacOS aka OSX

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Process::TotalProcessorTime is about 42 times lower than expected on ARM64 Mac

10 participants

@ForNeVeR@marek-safar@EgorBo@jeffhandley@tmds@am11@adamsitnik@danmoseley@ViktorHofer@AaronRobinsonMSFT