Update Environment.ProcessorCount on Windows to take into account the processor affinity mask - #45943

Merged
kouvel merged 1 commit into
dotnet:masterfrom
kouvel:TpProcessAffinity
Jan 25, 2021
Merged

Update Environment.ProcessorCount on Windows to take into account the processor affinity mask#45943
kouvel merged 1 commit into
dotnet:masterfrom
kouvel:TpProcessAffinity

Conversation

@kouvel

@kouvelkouvel commented Dec 11, 2020

Copy link
Copy Markdown
Contributor
  • Similarly to cases on Unixes where sched_getaffinity is available
  • If GCCpuGroup and Thread_UseAllCpuGroups are both enabled, I'm not sure if the CPUGroupInfo count of active processors takes affinity into account as the docs are not clear, for now I'm not modifying that path until I can verify it
  • Otherwise, a process that is started with a specific processor affinity mask still shows full CPU count and perf is much worse in CPU-affinitized cases compared to the native thread pool
  • This is one of the differences in the portable managed thread pool implementation, which relies on Environment.ProcessorCount, as opposed to the native thread pool, which uses the affinity mask
  • After this change, in affinitized cases on Windows, perf-wise where this difference matters, the behavior perf-wise is closer to that on Linux and closer to what is currently expected:
    • The portable thread pool uses the same worker thread count as the native thread pool
    • Environment.ProcessorCount returns the number of processors the process is affinitized to, which may be less than it would have returned before, similarly to Linux

Breaking change issue: #47427

… processor affinity mask
- Similarly to cases on Unixes where sched_getaffinity is available
- If `GCCpuGroup` and `Thread_UseAllCpuGroups` are both enabled, I'm not sure if the `CPUGroupInfo` count of active processors takes affinity into account as the docs are not clear, for now I'm not modifying that path until I can verify it
- Otherwise, a process that is started with a specific processor affinity mask still shows full CPU count
- This is one of the differences in the portable managed thread pool implementation, which relies on Environment.ProcessorCount, as opposed to the native thread pool, which uses the affinity mask
- After this change, in affinitized cases on Windows the behavior is consistent perf-wise with Linux in similar situations:
- The portable thread pool uses the same worker thread count as the native thread pool
- `Environment.ProcessorCount` returns the number of processors the the process is affinitized to, which may be less than it would have returned before
@kouvelkouvel added this to the 6.0.0 milestone Dec 11, 2020
@kouvel
kouvel requested a review from janvorliDecember 11, 2020 03:33
@kouvelkouvel self-assigned this Dec 11, 2020
@pgrawehr

Copy link
Copy Markdown

I don't think this is a good idea. After this change, how would one obtain the processor count, for instance to check whether an affinity mask is applied? For instance, I have a piece of code that uses this property and compares it to the affinity mask to make sure the application is allowed to run on all CPUs.

@jkotas

Copy link
Copy Markdown
Member

@pgrawehr The number of processors that the application can run on can be limited by number of mechanism. Process affinity, job control on Windows and cgroups on Linux are the most common mechanisms. We have found through trial-and-failure that returning the restricted number of processors from this property is the most appropriate behavior that makes most callers work well, and it is what we do on non-Windows systems already.

After this change, how would one obtain the processor count

You can PInvoke the appropriate OS APIs.

@kouvel I agree that this is a good change to make, but it needs to be marked as breaking change.

@pgrawehr

Copy link
Copy Markdown

You can PInvoke the appropriate OS APIs.

I think that's bad, because it's again OS dependent. The properties and methods in the Environment class are just there so the programmer doesn't need to use any low-level PInvoke calls for common system properties. Maybe adding a separate property would be nicer.

@janvorlijanvorli 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!

@danmoseley

Copy link
Copy Markdown
Contributor

@pgrawehr you could make an API proposal, with the template.

@danmoseleydanmoseley added the breaking-change Issue or PR that represents a breaking API or functional change over a previous release. label Dec 17, 2020
@ghostghost added the needs-breaking-change-doc-created Breaking changes need an issue opened with https://github.com/dotnet/docs/issues/new?template=dotnet label Dec 17, 2020
Comment threadsrc/coreclr/vm/eeconfig.cpp
@stephentoub

Copy link
Copy Markdown
Member

@kouvel, can this be merged?

@kouvel

Copy link
Copy Markdown
ContributorAuthor

I just need to file an issue and document some things for the breaking change process, will try to do that early next week.

@stephentoub

Copy link
Copy Markdown
Member

Ok, cool.

@danmoseley

Copy link
Copy Markdown
Contributor

@kouvel when you open that breaking change issue please remove the "needs breaking change doc" label

@kouvelkouvel removed the needs-breaking-change-doc-created Breaking changes need an issue opened with https://github.com/dotnet/docs/issues/new?template=dotnet label Jan 25, 2021
jkotas added a commit to jkotas/runtimelab that referenced this pull request Jan 27, 2021
jkotas added a commit to jkotas/runtimelab that referenced this pull request Jan 27, 2021
jkotas added a commit to jkotas/runtimelab that referenced this pull request Jan 27, 2021
jkotas added a commit to jkotas/runtimelab that referenced this pull request Jan 27, 2021
MichalStrehovsky pushed a commit to dotnet/runtimelab that referenced this pull request Jan 28, 2021
@ghostghost locked as resolved and limited conversation to collaborators Feb 24, 2021
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Threadingbreaking-changeIssue or PR that represents a breaking API or functional change over a previous release.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@kouvel@pgrawehr@jkotas@danmoseley@stephentoub@janvorli
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 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

Update Environment.ProcessorCount on Windows to take into account the processor affinity mask - #45943

Merged
kouvel merged 1 commit into
dotnet:masterfrom
kouvel:TpProcessAffinity
Jan 25, 2021
Merged

Update Environment.ProcessorCount on Windows to take into account the processor affinity mask#45943
kouvel merged 1 commit into
dotnet:masterfrom
kouvel:TpProcessAffinity

Conversation

@kouvel

@kouvelkouvel commented Dec 11, 2020

Copy link
Copy Markdown
Contributor
  • Similarly to cases on Unixes where sched_getaffinity is available
  • If GCCpuGroup and Thread_UseAllCpuGroups are both enabled, I'm not sure if the CPUGroupInfo count of active processors takes affinity into account as the docs are not clear, for now I'm not modifying that path until I can verify it
  • Otherwise, a process that is started with a specific processor affinity mask still shows full CPU count and perf is much worse in CPU-affinitized cases compared to the native thread pool
  • This is one of the differences in the portable managed thread pool implementation, which relies on Environment.ProcessorCount, as opposed to the native thread pool, which uses the affinity mask
  • After this change, in affinitized cases on Windows, perf-wise where this difference matters, the behavior perf-wise is closer to that on Linux and closer to what is currently expected:
    • The portable thread pool uses the same worker thread count as the native thread pool
    • Environment.ProcessorCount returns the number of processors the process is affinitized to, which may be less than it would have returned before, similarly to Linux

Breaking change issue: #47427

… processor affinity mask
- Similarly to cases on Unixes where sched_getaffinity is available
- If `GCCpuGroup` and `Thread_UseAllCpuGroups` are both enabled, I'm not sure if the `CPUGroupInfo` count of active processors takes affinity into account as the docs are not clear, for now I'm not modifying that path until I can verify it
- Otherwise, a process that is started with a specific processor affinity mask still shows full CPU count
- This is one of the differences in the portable managed thread pool implementation, which relies on Environment.ProcessorCount, as opposed to the native thread pool, which uses the affinity mask
- After this change, in affinitized cases on Windows the behavior is consistent perf-wise with Linux in similar situations:
- The portable thread pool uses the same worker thread count as the native thread pool
- `Environment.ProcessorCount` returns the number of processors the the process is affinitized to, which may be less than it would have returned before
@kouvelkouvel added this to the 6.0.0 milestone Dec 11, 2020
@kouvel
kouvel requested a review from janvorliDecember 11, 2020 03:33
@kouvelkouvel self-assigned this Dec 11, 2020
@pgrawehr

Copy link
Copy Markdown

I don't think this is a good idea. After this change, how would one obtain the processor count, for instance to check whether an affinity mask is applied? For instance, I have a piece of code that uses this property and compares it to the affinity mask to make sure the application is allowed to run on all CPUs.

@jkotas

Copy link
Copy Markdown
Member

@pgrawehr The number of processors that the application can run on can be limited by number of mechanism. Process affinity, job control on Windows and cgroups on Linux are the most common mechanisms. We have found through trial-and-failure that returning the restricted number of processors from this property is the most appropriate behavior that makes most callers work well, and it is what we do on non-Windows systems already.

After this change, how would one obtain the processor count

You can PInvoke the appropriate OS APIs.

@kouvel I agree that this is a good change to make, but it needs to be marked as breaking change.

@pgrawehr

Copy link
Copy Markdown

You can PInvoke the appropriate OS APIs.

I think that's bad, because it's again OS dependent. The properties and methods in the Environment class are just there so the programmer doesn't need to use any low-level PInvoke calls for common system properties. Maybe adding a separate property would be nicer.

@janvorlijanvorli 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!

@danmoseley

Copy link
Copy Markdown
Contributor

@pgrawehr you could make an API proposal, with the template.

@danmoseleydanmoseley added the breaking-change Issue or PR that represents a breaking API or functional change over a previous release. label Dec 17, 2020
@ghostghost added the needs-breaking-change-doc-created Breaking changes need an issue opened with https://github.com/dotnet/docs/issues/new?template=dotnet label Dec 17, 2020
Comment threadsrc/coreclr/vm/eeconfig.cpp
@stephentoub

Copy link
Copy Markdown
Member

@kouvel, can this be merged?

@kouvel

Copy link
Copy Markdown
ContributorAuthor

I just need to file an issue and document some things for the breaking change process, will try to do that early next week.

@stephentoub

Copy link
Copy Markdown
Member

Ok, cool.

@danmoseley

Copy link
Copy Markdown
Contributor

@kouvel when you open that breaking change issue please remove the "needs breaking change doc" label

@kouvelkouvel removed the needs-breaking-change-doc-created Breaking changes need an issue opened with https://github.com/dotnet/docs/issues/new?template=dotnet label Jan 25, 2021
jkotas added a commit to jkotas/runtimelab that referenced this pull request Jan 27, 2021
jkotas added a commit to jkotas/runtimelab that referenced this pull request Jan 27, 2021
jkotas added a commit to jkotas/runtimelab that referenced this pull request Jan 27, 2021
jkotas added a commit to jkotas/runtimelab that referenced this pull request Jan 27, 2021
MichalStrehovsky pushed a commit to dotnet/runtimelab that referenced this pull request Jan 28, 2021
@ghostghost locked as resolved and limited conversation to collaborators Feb 24, 2021
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Threadingbreaking-changeIssue or PR that represents a breaking API or functional change over a previous release.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@kouvel@pgrawehr@jkotas@danmoseley@stephentoub@janvorli
, '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

Update Environment.ProcessorCount on Windows to take into account the processor affinity mask - #45943

Merged
kouvel merged 1 commit into
dotnet:masterfrom
kouvel:TpProcessAffinity
Jan 25, 2021
Merged

Update Environment.ProcessorCount on Windows to take into account the processor affinity mask#45943
kouvel merged 1 commit into
dotnet:masterfrom
kouvel:TpProcessAffinity

Conversation

@kouvel

@kouvelkouvel commented Dec 11, 2020

Copy link
Copy Markdown
Contributor
  • Similarly to cases on Unixes where sched_getaffinity is available
  • If GCCpuGroup and Thread_UseAllCpuGroups are both enabled, I'm not sure if the CPUGroupInfo count of active processors takes affinity into account as the docs are not clear, for now I'm not modifying that path until I can verify it
  • Otherwise, a process that is started with a specific processor affinity mask still shows full CPU count and perf is much worse in CPU-affinitized cases compared to the native thread pool
  • This is one of the differences in the portable managed thread pool implementation, which relies on Environment.ProcessorCount, as opposed to the native thread pool, which uses the affinity mask
  • After this change, in affinitized cases on Windows, perf-wise where this difference matters, the behavior perf-wise is closer to that on Linux and closer to what is currently expected:
    • The portable thread pool uses the same worker thread count as the native thread pool
    • Environment.ProcessorCount returns the number of processors the process is affinitized to, which may be less than it would have returned before, similarly to Linux

Breaking change issue: #47427

… processor affinity mask
- Similarly to cases on Unixes where sched_getaffinity is available
- If `GCCpuGroup` and `Thread_UseAllCpuGroups` are both enabled, I'm not sure if the `CPUGroupInfo` count of active processors takes affinity into account as the docs are not clear, for now I'm not modifying that path until I can verify it
- Otherwise, a process that is started with a specific processor affinity mask still shows full CPU count
- This is one of the differences in the portable managed thread pool implementation, which relies on Environment.ProcessorCount, as opposed to the native thread pool, which uses the affinity mask
- After this change, in affinitized cases on Windows the behavior is consistent perf-wise with Linux in similar situations:
- The portable thread pool uses the same worker thread count as the native thread pool
- `Environment.ProcessorCount` returns the number of processors the the process is affinitized to, which may be less than it would have returned before
@kouvelkouvel added this to the 6.0.0 milestone Dec 11, 2020
@kouvel
kouvel requested a review from janvorliDecember 11, 2020 03:33
@kouvelkouvel self-assigned this Dec 11, 2020
@pgrawehr

Copy link
Copy Markdown

I don't think this is a good idea. After this change, how would one obtain the processor count, for instance to check whether an affinity mask is applied? For instance, I have a piece of code that uses this property and compares it to the affinity mask to make sure the application is allowed to run on all CPUs.

@jkotas

Copy link
Copy Markdown
Member

@pgrawehr The number of processors that the application can run on can be limited by number of mechanism. Process affinity, job control on Windows and cgroups on Linux are the most common mechanisms. We have found through trial-and-failure that returning the restricted number of processors from this property is the most appropriate behavior that makes most callers work well, and it is what we do on non-Windows systems already.

After this change, how would one obtain the processor count

You can PInvoke the appropriate OS APIs.

@kouvel I agree that this is a good change to make, but it needs to be marked as breaking change.

@pgrawehr

Copy link
Copy Markdown

You can PInvoke the appropriate OS APIs.

I think that's bad, because it's again OS dependent. The properties and methods in the Environment class are just there so the programmer doesn't need to use any low-level PInvoke calls for common system properties. Maybe adding a separate property would be nicer.

@janvorlijanvorli 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!

@danmoseley

Copy link
Copy Markdown
Contributor

@pgrawehr you could make an API proposal, with the template.

@danmoseleydanmoseley added the breaking-change Issue or PR that represents a breaking API or functional change over a previous release. label Dec 17, 2020
@ghostghost added the needs-breaking-change-doc-created Breaking changes need an issue opened with https://github.com/dotnet/docs/issues/new?template=dotnet label Dec 17, 2020
Comment threadsrc/coreclr/vm/eeconfig.cpp
@stephentoub

Copy link
Copy Markdown
Member

@kouvel, can this be merged?

@kouvel

Copy link
Copy Markdown
ContributorAuthor

I just need to file an issue and document some things for the breaking change process, will try to do that early next week.

@stephentoub

Copy link
Copy Markdown
Member

Ok, cool.

@danmoseley

Copy link
Copy Markdown
Contributor

@kouvel when you open that breaking change issue please remove the "needs breaking change doc" label

@kouvelkouvel removed the needs-breaking-change-doc-created Breaking changes need an issue opened with https://github.com/dotnet/docs/issues/new?template=dotnet label Jan 25, 2021
jkotas added a commit to jkotas/runtimelab that referenced this pull request Jan 27, 2021
jkotas added a commit to jkotas/runtimelab that referenced this pull request Jan 27, 2021
jkotas added a commit to jkotas/runtimelab that referenced this pull request Jan 27, 2021
jkotas added a commit to jkotas/runtimelab that referenced this pull request Jan 27, 2021
MichalStrehovsky pushed a commit to dotnet/runtimelab that referenced this pull request Jan 28, 2021
@ghostghost locked as resolved and limited conversation to collaborators Feb 24, 2021
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Threadingbreaking-changeIssue or PR that represents a breaking API or functional change over a previous release.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@kouvel@pgrawehr@jkotas@danmoseley@stephentoub@janvorli
, '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 > 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

Update Environment.ProcessorCount on Windows to take into account the processor affinity mask - #45943

Merged
kouvel merged 1 commit into
dotnet:masterfrom
kouvel:TpProcessAffinity
Jan 25, 2021
Merged

Update Environment.ProcessorCount on Windows to take into account the processor affinity mask#45943
kouvel merged 1 commit into
dotnet:masterfrom
kouvel:TpProcessAffinity

Conversation

@kouvel

@kouvelkouvel commented Dec 11, 2020

Copy link
Copy Markdown
Contributor
  • Similarly to cases on Unixes where sched_getaffinity is available
  • If GCCpuGroup and Thread_UseAllCpuGroups are both enabled, I'm not sure if the CPUGroupInfo count of active processors takes affinity into account as the docs are not clear, for now I'm not modifying that path until I can verify it
  • Otherwise, a process that is started with a specific processor affinity mask still shows full CPU count and perf is much worse in CPU-affinitized cases compared to the native thread pool
  • This is one of the differences in the portable managed thread pool implementation, which relies on Environment.ProcessorCount, as opposed to the native thread pool, which uses the affinity mask
  • After this change, in affinitized cases on Windows, perf-wise where this difference matters, the behavior perf-wise is closer to that on Linux and closer to what is currently expected:
    • The portable thread pool uses the same worker thread count as the native thread pool
    • Environment.ProcessorCount returns the number of processors the process is affinitized to, which may be less than it would have returned before, similarly to Linux

Breaking change issue: #47427

… processor affinity mask
- Similarly to cases on Unixes where sched_getaffinity is available
- If `GCCpuGroup` and `Thread_UseAllCpuGroups` are both enabled, I'm not sure if the `CPUGroupInfo` count of active processors takes affinity into account as the docs are not clear, for now I'm not modifying that path until I can verify it
- Otherwise, a process that is started with a specific processor affinity mask still shows full CPU count
- This is one of the differences in the portable managed thread pool implementation, which relies on Environment.ProcessorCount, as opposed to the native thread pool, which uses the affinity mask
- After this change, in affinitized cases on Windows the behavior is consistent perf-wise with Linux in similar situations:
- The portable thread pool uses the same worker thread count as the native thread pool
- `Environment.ProcessorCount` returns the number of processors the the process is affinitized to, which may be less than it would have returned before
@kouvelkouvel added this to the 6.0.0 milestone Dec 11, 2020
@kouvel
kouvel requested a review from janvorliDecember 11, 2020 03:33
@kouvelkouvel self-assigned this Dec 11, 2020
@pgrawehr

Copy link
Copy Markdown

I don't think this is a good idea. After this change, how would one obtain the processor count, for instance to check whether an affinity mask is applied? For instance, I have a piece of code that uses this property and compares it to the affinity mask to make sure the application is allowed to run on all CPUs.

@jkotas

Copy link
Copy Markdown
Member

@pgrawehr The number of processors that the application can run on can be limited by number of mechanism. Process affinity, job control on Windows and cgroups on Linux are the most common mechanisms. We have found through trial-and-failure that returning the restricted number of processors from this property is the most appropriate behavior that makes most callers work well, and it is what we do on non-Windows systems already.

After this change, how would one obtain the processor count

You can PInvoke the appropriate OS APIs.

@kouvel I agree that this is a good change to make, but it needs to be marked as breaking change.

@pgrawehr

Copy link
Copy Markdown

You can PInvoke the appropriate OS APIs.

I think that's bad, because it's again OS dependent. The properties and methods in the Environment class are just there so the programmer doesn't need to use any low-level PInvoke calls for common system properties. Maybe adding a separate property would be nicer.

@janvorlijanvorli 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!

@danmoseley

Copy link
Copy Markdown
Contributor

@pgrawehr you could make an API proposal, with the template.

@danmoseleydanmoseley added the breaking-change Issue or PR that represents a breaking API or functional change over a previous release. label Dec 17, 2020
@ghostghost added the needs-breaking-change-doc-created Breaking changes need an issue opened with https://github.com/dotnet/docs/issues/new?template=dotnet label Dec 17, 2020
Comment threadsrc/coreclr/vm/eeconfig.cpp
@stephentoub

Copy link
Copy Markdown
Member

@kouvel, can this be merged?

@kouvel

Copy link
Copy Markdown
ContributorAuthor

I just need to file an issue and document some things for the breaking change process, will try to do that early next week.

@stephentoub

Copy link
Copy Markdown
Member

Ok, cool.

@danmoseley

Copy link
Copy Markdown
Contributor

@kouvel when you open that breaking change issue please remove the "needs breaking change doc" label

@kouvelkouvel removed the needs-breaking-change-doc-created Breaking changes need an issue opened with https://github.com/dotnet/docs/issues/new?template=dotnet label Jan 25, 2021
jkotas added a commit to jkotas/runtimelab that referenced this pull request Jan 27, 2021
jkotas added a commit to jkotas/runtimelab that referenced this pull request Jan 27, 2021
jkotas added a commit to jkotas/runtimelab that referenced this pull request Jan 27, 2021
jkotas added a commit to jkotas/runtimelab that referenced this pull request Jan 27, 2021
MichalStrehovsky pushed a commit to dotnet/runtimelab that referenced this pull request Jan 28, 2021
@ghostghost locked as resolved and limited conversation to collaborators Feb 24, 2021
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Threadingbreaking-changeIssue or PR that represents a breaking API or functional change over a previous release.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@kouvel@pgrawehr@jkotas@danmoseley@stephentoub@janvorli
, '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

Update Environment.ProcessorCount on Windows to take into account the processor affinity mask - #45943

Merged
kouvel merged 1 commit into
dotnet:masterfrom
kouvel:TpProcessAffinity
Jan 25, 2021
Merged

Update Environment.ProcessorCount on Windows to take into account the processor affinity mask#45943
kouvel merged 1 commit into
dotnet:masterfrom
kouvel:TpProcessAffinity

Conversation

@kouvel

@kouvelkouvel commented Dec 11, 2020

Copy link
Copy Markdown
Contributor
  • Similarly to cases on Unixes where sched_getaffinity is available
  • If GCCpuGroup and Thread_UseAllCpuGroups are both enabled, I'm not sure if the CPUGroupInfo count of active processors takes affinity into account as the docs are not clear, for now I'm not modifying that path until I can verify it
  • Otherwise, a process that is started with a specific processor affinity mask still shows full CPU count and perf is much worse in CPU-affinitized cases compared to the native thread pool
  • This is one of the differences in the portable managed thread pool implementation, which relies on Environment.ProcessorCount, as opposed to the native thread pool, which uses the affinity mask
  • After this change, in affinitized cases on Windows, perf-wise where this difference matters, the behavior perf-wise is closer to that on Linux and closer to what is currently expected:
    • The portable thread pool uses the same worker thread count as the native thread pool
    • Environment.ProcessorCount returns the number of processors the process is affinitized to, which may be less than it would have returned before, similarly to Linux

Breaking change issue: #47427

… processor affinity mask
- Similarly to cases on Unixes where sched_getaffinity is available
- If `GCCpuGroup` and `Thread_UseAllCpuGroups` are both enabled, I'm not sure if the `CPUGroupInfo` count of active processors takes affinity into account as the docs are not clear, for now I'm not modifying that path until I can verify it
- Otherwise, a process that is started with a specific processor affinity mask still shows full CPU count
- This is one of the differences in the portable managed thread pool implementation, which relies on Environment.ProcessorCount, as opposed to the native thread pool, which uses the affinity mask
- After this change, in affinitized cases on Windows the behavior is consistent perf-wise with Linux in similar situations:
- The portable thread pool uses the same worker thread count as the native thread pool
- `Environment.ProcessorCount` returns the number of processors the the process is affinitized to, which may be less than it would have returned before
@kouvelkouvel added this to the 6.0.0 milestone Dec 11, 2020
@kouvel
kouvel requested a review from janvorliDecember 11, 2020 03:33
@kouvelkouvel self-assigned this Dec 11, 2020
@pgrawehr

Copy link
Copy Markdown

I don't think this is a good idea. After this change, how would one obtain the processor count, for instance to check whether an affinity mask is applied? For instance, I have a piece of code that uses this property and compares it to the affinity mask to make sure the application is allowed to run on all CPUs.

@jkotas

Copy link
Copy Markdown
Member

@pgrawehr The number of processors that the application can run on can be limited by number of mechanism. Process affinity, job control on Windows and cgroups on Linux are the most common mechanisms. We have found through trial-and-failure that returning the restricted number of processors from this property is the most appropriate behavior that makes most callers work well, and it is what we do on non-Windows systems already.

After this change, how would one obtain the processor count

You can PInvoke the appropriate OS APIs.

@kouvel I agree that this is a good change to make, but it needs to be marked as breaking change.

@pgrawehr

Copy link
Copy Markdown

You can PInvoke the appropriate OS APIs.

I think that's bad, because it's again OS dependent. The properties and methods in the Environment class are just there so the programmer doesn't need to use any low-level PInvoke calls for common system properties. Maybe adding a separate property would be nicer.

@janvorlijanvorli 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!

@danmoseley

Copy link
Copy Markdown
Contributor

@pgrawehr you could make an API proposal, with the template.

@danmoseleydanmoseley added the breaking-change Issue or PR that represents a breaking API or functional change over a previous release. label Dec 17, 2020
@ghostghost added the needs-breaking-change-doc-created Breaking changes need an issue opened with https://github.com/dotnet/docs/issues/new?template=dotnet label Dec 17, 2020
Comment threadsrc/coreclr/vm/eeconfig.cpp
@stephentoub

Copy link
Copy Markdown
Member

@kouvel, can this be merged?

@kouvel

Copy link
Copy Markdown
ContributorAuthor

I just need to file an issue and document some things for the breaking change process, will try to do that early next week.

@stephentoub

Copy link
Copy Markdown
Member

Ok, cool.

@danmoseley

Copy link
Copy Markdown
Contributor

@kouvel when you open that breaking change issue please remove the "needs breaking change doc" label

@kouvelkouvel removed the needs-breaking-change-doc-created Breaking changes need an issue opened with https://github.com/dotnet/docs/issues/new?template=dotnet label Jan 25, 2021
jkotas added a commit to jkotas/runtimelab that referenced this pull request Jan 27, 2021
jkotas added a commit to jkotas/runtimelab that referenced this pull request Jan 27, 2021
jkotas added a commit to jkotas/runtimelab that referenced this pull request Jan 27, 2021
jkotas added a commit to jkotas/runtimelab that referenced this pull request Jan 27, 2021
MichalStrehovsky pushed a commit to dotnet/runtimelab that referenced this pull request Jan 28, 2021
@ghostghost locked as resolved and limited conversation to collaborators Feb 24, 2021
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Threadingbreaking-changeIssue or PR that represents a breaking API or functional change over a previous release.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@kouvel@pgrawehr@jkotas@danmoseley@stephentoub@janvorli
, '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

Update Environment.ProcessorCount on Windows to take into account the processor affinity mask - #45943

Merged
kouvel merged 1 commit into
dotnet:masterfrom
kouvel:TpProcessAffinity
Jan 25, 2021
Merged

Update Environment.ProcessorCount on Windows to take into account the processor affinity mask#45943
kouvel merged 1 commit into
dotnet:masterfrom
kouvel:TpProcessAffinity

Conversation

@kouvel

@kouvelkouvel commented Dec 11, 2020

Copy link
Copy Markdown
Contributor
  • Similarly to cases on Unixes where sched_getaffinity is available
  • If GCCpuGroup and Thread_UseAllCpuGroups are both enabled, I'm not sure if the CPUGroupInfo count of active processors takes affinity into account as the docs are not clear, for now I'm not modifying that path until I can verify it
  • Otherwise, a process that is started with a specific processor affinity mask still shows full CPU count and perf is much worse in CPU-affinitized cases compared to the native thread pool
  • This is one of the differences in the portable managed thread pool implementation, which relies on Environment.ProcessorCount, as opposed to the native thread pool, which uses the affinity mask
  • After this change, in affinitized cases on Windows, perf-wise where this difference matters, the behavior perf-wise is closer to that on Linux and closer to what is currently expected:
    • The portable thread pool uses the same worker thread count as the native thread pool
    • Environment.ProcessorCount returns the number of processors the process is affinitized to, which may be less than it would have returned before, similarly to Linux

Breaking change issue: #47427

… processor affinity mask
- Similarly to cases on Unixes where sched_getaffinity is available
- If `GCCpuGroup` and `Thread_UseAllCpuGroups` are both enabled, I'm not sure if the `CPUGroupInfo` count of active processors takes affinity into account as the docs are not clear, for now I'm not modifying that path until I can verify it
- Otherwise, a process that is started with a specific processor affinity mask still shows full CPU count
- This is one of the differences in the portable managed thread pool implementation, which relies on Environment.ProcessorCount, as opposed to the native thread pool, which uses the affinity mask
- After this change, in affinitized cases on Windows the behavior is consistent perf-wise with Linux in similar situations:
- The portable thread pool uses the same worker thread count as the native thread pool
- `Environment.ProcessorCount` returns the number of processors the the process is affinitized to, which may be less than it would have returned before
@kouvelkouvel added this to the 6.0.0 milestone Dec 11, 2020
@kouvel
kouvel requested a review from janvorliDecember 11, 2020 03:33
@kouvelkouvel self-assigned this Dec 11, 2020
@pgrawehr

Copy link
Copy Markdown

I don't think this is a good idea. After this change, how would one obtain the processor count, for instance to check whether an affinity mask is applied? For instance, I have a piece of code that uses this property and compares it to the affinity mask to make sure the application is allowed to run on all CPUs.

@jkotas

Copy link
Copy Markdown
Member

@pgrawehr The number of processors that the application can run on can be limited by number of mechanism. Process affinity, job control on Windows and cgroups on Linux are the most common mechanisms. We have found through trial-and-failure that returning the restricted number of processors from this property is the most appropriate behavior that makes most callers work well, and it is what we do on non-Windows systems already.

After this change, how would one obtain the processor count

You can PInvoke the appropriate OS APIs.

@kouvel I agree that this is a good change to make, but it needs to be marked as breaking change.

@pgrawehr

Copy link
Copy Markdown

You can PInvoke the appropriate OS APIs.

I think that's bad, because it's again OS dependent. The properties and methods in the Environment class are just there so the programmer doesn't need to use any low-level PInvoke calls for common system properties. Maybe adding a separate property would be nicer.

@janvorlijanvorli 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!

@danmoseley

Copy link
Copy Markdown
Contributor

@pgrawehr you could make an API proposal, with the template.

@danmoseleydanmoseley added the breaking-change Issue or PR that represents a breaking API or functional change over a previous release. label Dec 17, 2020
@ghostghost added the needs-breaking-change-doc-created Breaking changes need an issue opened with https://github.com/dotnet/docs/issues/new?template=dotnet label Dec 17, 2020
Comment threadsrc/coreclr/vm/eeconfig.cpp
@stephentoub

Copy link
Copy Markdown
Member

@kouvel, can this be merged?

@kouvel

Copy link
Copy Markdown
ContributorAuthor

I just need to file an issue and document some things for the breaking change process, will try to do that early next week.

@stephentoub

Copy link
Copy Markdown
Member

Ok, cool.

@danmoseley

Copy link
Copy Markdown
Contributor

@kouvel when you open that breaking change issue please remove the "needs breaking change doc" label

@kouvelkouvel removed the needs-breaking-change-doc-created Breaking changes need an issue opened with https://github.com/dotnet/docs/issues/new?template=dotnet label Jan 25, 2021
jkotas added a commit to jkotas/runtimelab that referenced this pull request Jan 27, 2021
jkotas added a commit to jkotas/runtimelab that referenced this pull request Jan 27, 2021
jkotas added a commit to jkotas/runtimelab that referenced this pull request Jan 27, 2021
jkotas added a commit to jkotas/runtimelab that referenced this pull request Jan 27, 2021
MichalStrehovsky pushed a commit to dotnet/runtimelab that referenced this pull request Jan 28, 2021
@ghostghost locked as resolved and limited conversation to collaborators Feb 24, 2021
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Threadingbreaking-changeIssue or PR that represents a breaking API or functional change over a previous release.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@kouvel@pgrawehr@jkotas@danmoseley@stephentoub@janvorli
, '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

Update Environment.ProcessorCount on Windows to take into account the processor affinity mask - #45943

Merged
kouvel merged 1 commit into
dotnet:masterfrom
kouvel:TpProcessAffinity
Jan 25, 2021
Merged

Update Environment.ProcessorCount on Windows to take into account the processor affinity mask#45943
kouvel merged 1 commit into
dotnet:masterfrom
kouvel:TpProcessAffinity

Conversation

@kouvel

@kouvelkouvel commented Dec 11, 2020

Copy link
Copy Markdown
Contributor
  • Similarly to cases on Unixes where sched_getaffinity is available
  • If GCCpuGroup and Thread_UseAllCpuGroups are both enabled, I'm not sure if the CPUGroupInfo count of active processors takes affinity into account as the docs are not clear, for now I'm not modifying that path until I can verify it
  • Otherwise, a process that is started with a specific processor affinity mask still shows full CPU count and perf is much worse in CPU-affinitized cases compared to the native thread pool
  • This is one of the differences in the portable managed thread pool implementation, which relies on Environment.ProcessorCount, as opposed to the native thread pool, which uses the affinity mask
  • After this change, in affinitized cases on Windows, perf-wise where this difference matters, the behavior perf-wise is closer to that on Linux and closer to what is currently expected:
    • The portable thread pool uses the same worker thread count as the native thread pool
    • Environment.ProcessorCount returns the number of processors the process is affinitized to, which may be less than it would have returned before, similarly to Linux

Breaking change issue: #47427

… processor affinity mask
- Similarly to cases on Unixes where sched_getaffinity is available
- If `GCCpuGroup` and `Thread_UseAllCpuGroups` are both enabled, I'm not sure if the `CPUGroupInfo` count of active processors takes affinity into account as the docs are not clear, for now I'm not modifying that path until I can verify it
- Otherwise, a process that is started with a specific processor affinity mask still shows full CPU count
- This is one of the differences in the portable managed thread pool implementation, which relies on Environment.ProcessorCount, as opposed to the native thread pool, which uses the affinity mask
- After this change, in affinitized cases on Windows the behavior is consistent perf-wise with Linux in similar situations:
- The portable thread pool uses the same worker thread count as the native thread pool
- `Environment.ProcessorCount` returns the number of processors the the process is affinitized to, which may be less than it would have returned before
@kouvelkouvel added this to the 6.0.0 milestone Dec 11, 2020
@kouvel
kouvel requested a review from janvorliDecember 11, 2020 03:33
@kouvelkouvel self-assigned this Dec 11, 2020
@pgrawehr

Copy link
Copy Markdown

I don't think this is a good idea. After this change, how would one obtain the processor count, for instance to check whether an affinity mask is applied? For instance, I have a piece of code that uses this property and compares it to the affinity mask to make sure the application is allowed to run on all CPUs.

@jkotas

Copy link
Copy Markdown
Member

@pgrawehr The number of processors that the application can run on can be limited by number of mechanism. Process affinity, job control on Windows and cgroups on Linux are the most common mechanisms. We have found through trial-and-failure that returning the restricted number of processors from this property is the most appropriate behavior that makes most callers work well, and it is what we do on non-Windows systems already.

After this change, how would one obtain the processor count

You can PInvoke the appropriate OS APIs.

@kouvel I agree that this is a good change to make, but it needs to be marked as breaking change.

@pgrawehr

Copy link
Copy Markdown

You can PInvoke the appropriate OS APIs.

I think that's bad, because it's again OS dependent. The properties and methods in the Environment class are just there so the programmer doesn't need to use any low-level PInvoke calls for common system properties. Maybe adding a separate property would be nicer.

@janvorlijanvorli 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!

@danmoseley

Copy link
Copy Markdown
Contributor

@pgrawehr you could make an API proposal, with the template.

@danmoseleydanmoseley added the breaking-change Issue or PR that represents a breaking API or functional change over a previous release. label Dec 17, 2020
@ghostghost added the needs-breaking-change-doc-created Breaking changes need an issue opened with https://github.com/dotnet/docs/issues/new?template=dotnet label Dec 17, 2020
Comment threadsrc/coreclr/vm/eeconfig.cpp
@stephentoub

Copy link
Copy Markdown
Member

@kouvel, can this be merged?

@kouvel

Copy link
Copy Markdown
ContributorAuthor

I just need to file an issue and document some things for the breaking change process, will try to do that early next week.

@stephentoub

Copy link
Copy Markdown
Member

Ok, cool.

@danmoseley

Copy link
Copy Markdown
Contributor

@kouvel when you open that breaking change issue please remove the "needs breaking change doc" label

@kouvelkouvel removed the needs-breaking-change-doc-created Breaking changes need an issue opened with https://github.com/dotnet/docs/issues/new?template=dotnet label Jan 25, 2021
jkotas added a commit to jkotas/runtimelab that referenced this pull request Jan 27, 2021
jkotas added a commit to jkotas/runtimelab that referenced this pull request Jan 27, 2021
jkotas added a commit to jkotas/runtimelab that referenced this pull request Jan 27, 2021
jkotas added a commit to jkotas/runtimelab that referenced this pull request Jan 27, 2021
MichalStrehovsky pushed a commit to dotnet/runtimelab that referenced this pull request Jan 28, 2021
@ghostghost locked as resolved and limited conversation to collaborators Feb 24, 2021
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Threadingbreaking-changeIssue or PR that represents a breaking API or functional change over a previous release.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@kouvel@pgrawehr@jkotas@danmoseley@stephentoub@janvorli
, '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

Update Environment.ProcessorCount on Windows to take into account the processor affinity mask - #45943

Merged
kouvel merged 1 commit into
dotnet:masterfrom
kouvel:TpProcessAffinity
Jan 25, 2021
Merged

Update Environment.ProcessorCount on Windows to take into account the processor affinity mask#45943
kouvel merged 1 commit into
dotnet:masterfrom
kouvel:TpProcessAffinity

Conversation

@kouvel

@kouvelkouvel commented Dec 11, 2020

Copy link
Copy Markdown
Contributor
  • Similarly to cases on Unixes where sched_getaffinity is available
  • If GCCpuGroup and Thread_UseAllCpuGroups are both enabled, I'm not sure if the CPUGroupInfo count of active processors takes affinity into account as the docs are not clear, for now I'm not modifying that path until I can verify it
  • Otherwise, a process that is started with a specific processor affinity mask still shows full CPU count and perf is much worse in CPU-affinitized cases compared to the native thread pool
  • This is one of the differences in the portable managed thread pool implementation, which relies on Environment.ProcessorCount, as opposed to the native thread pool, which uses the affinity mask
  • After this change, in affinitized cases on Windows, perf-wise where this difference matters, the behavior perf-wise is closer to that on Linux and closer to what is currently expected:
    • The portable thread pool uses the same worker thread count as the native thread pool
    • Environment.ProcessorCount returns the number of processors the process is affinitized to, which may be less than it would have returned before, similarly to Linux

Breaking change issue: #47427

… processor affinity mask
- Similarly to cases on Unixes where sched_getaffinity is available
- If `GCCpuGroup` and `Thread_UseAllCpuGroups` are both enabled, I'm not sure if the `CPUGroupInfo` count of active processors takes affinity into account as the docs are not clear, for now I'm not modifying that path until I can verify it
- Otherwise, a process that is started with a specific processor affinity mask still shows full CPU count
- This is one of the differences in the portable managed thread pool implementation, which relies on Environment.ProcessorCount, as opposed to the native thread pool, which uses the affinity mask
- After this change, in affinitized cases on Windows the behavior is consistent perf-wise with Linux in similar situations:
- The portable thread pool uses the same worker thread count as the native thread pool
- `Environment.ProcessorCount` returns the number of processors the the process is affinitized to, which may be less than it would have returned before
@kouvelkouvel added this to the 6.0.0 milestone Dec 11, 2020
@kouvel
kouvel requested a review from janvorliDecember 11, 2020 03:33
@kouvelkouvel self-assigned this Dec 11, 2020
@pgrawehr

Copy link
Copy Markdown

I don't think this is a good idea. After this change, how would one obtain the processor count, for instance to check whether an affinity mask is applied? For instance, I have a piece of code that uses this property and compares it to the affinity mask to make sure the application is allowed to run on all CPUs.

@jkotas

Copy link
Copy Markdown
Member

@pgrawehr The number of processors that the application can run on can be limited by number of mechanism. Process affinity, job control on Windows and cgroups on Linux are the most common mechanisms. We have found through trial-and-failure that returning the restricted number of processors from this property is the most appropriate behavior that makes most callers work well, and it is what we do on non-Windows systems already.

After this change, how would one obtain the processor count

You can PInvoke the appropriate OS APIs.

@kouvel I agree that this is a good change to make, but it needs to be marked as breaking change.

@pgrawehr

Copy link
Copy Markdown

You can PInvoke the appropriate OS APIs.

I think that's bad, because it's again OS dependent. The properties and methods in the Environment class are just there so the programmer doesn't need to use any low-level PInvoke calls for common system properties. Maybe adding a separate property would be nicer.

@janvorlijanvorli 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!

@danmoseley

Copy link
Copy Markdown
Contributor

@pgrawehr you could make an API proposal, with the template.

@danmoseleydanmoseley added the breaking-change Issue or PR that represents a breaking API or functional change over a previous release. label Dec 17, 2020
@ghostghost added the needs-breaking-change-doc-created Breaking changes need an issue opened with https://github.com/dotnet/docs/issues/new?template=dotnet label Dec 17, 2020
Comment threadsrc/coreclr/vm/eeconfig.cpp
@stephentoub

Copy link
Copy Markdown
Member

@kouvel, can this be merged?

@kouvel

Copy link
Copy Markdown
ContributorAuthor

I just need to file an issue and document some things for the breaking change process, will try to do that early next week.

@stephentoub

Copy link
Copy Markdown
Member

Ok, cool.

@danmoseley

Copy link
Copy Markdown
Contributor

@kouvel when you open that breaking change issue please remove the "needs breaking change doc" label

@kouvelkouvel removed the needs-breaking-change-doc-created Breaking changes need an issue opened with https://github.com/dotnet/docs/issues/new?template=dotnet label Jan 25, 2021
jkotas added a commit to jkotas/runtimelab that referenced this pull request Jan 27, 2021
jkotas added a commit to jkotas/runtimelab that referenced this pull request Jan 27, 2021
jkotas added a commit to jkotas/runtimelab that referenced this pull request Jan 27, 2021
jkotas added a commit to jkotas/runtimelab that referenced this pull request Jan 27, 2021
MichalStrehovsky pushed a commit to dotnet/runtimelab that referenced this pull request Jan 28, 2021
@ghostghost locked as resolved and limited conversation to collaborators Feb 24, 2021
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Threadingbreaking-changeIssue or PR that represents a breaking API or functional change over a previous release.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@kouvel@pgrawehr@jkotas@danmoseley@stephentoub@janvorli