Implement basic network flow control - #2803

Merged
ReenigneArcher merged 3 commits into
LizardByte:masterfrom
ns6089:paced_send
Jul 11, 2024
Merged

Implement basic network flow control#2803
ReenigneArcher merged 3 commits into
LizardByte:masterfrom
ns6089:paced_send

Conversation

@ns6089

@ns6089ns6089 commented Jul 4, 2024

Copy link
Copy Markdown
Contributor

Description

Combat RX/TX buffer overflows and improve multi-FEC on large frames.

Adopted from #1466
Should supersede #2787

Screenshot

Issues Fixed or Closed

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Dependency update (updates to dependencies)
  • Documentation update (changes to documentation)
  • Repository update (changes to repository files, e.g. .github/...)

Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have added or updated the in code docstring/documentation-blocks for new or existing methods/components

Branch Updates

LizardByte requires that branches be up-to-date before merging. This means that after any PR is merged, this branch
must be updated before it can be merged. You must also
Allow edits from maintainers.

  • I want maintainers to keep my branch updated

@ns6089

Copy link
Copy Markdown
ContributorAuthor

Basic implementation wasn't that hard, but it uncovered a few problems.

  1. I will try to implement hybrid sleep/spin wait after all, 0.5ms timer precision should be barely enough.
  2. On large bitrates our Reed-Solomon implementation takes significant amount of time. I will try moving it to separate thread, but in the long run it won't be enough.

@cgutman Have you considered alternative RS implementations that make use of SIMD instructions?
Like this one https://github.com/catid/leopard

@cgutman

Copy link
Copy Markdown
Collaborator

On large bitrates our Reed-Solomon implementation takes significant amount of time. I will try moving it to separate thread, but in the long run it won't be enough.

I don't think this needs to block merging this PR, unless you think these changes are going to make it worse somehow.

@cgutman Have you considered alternative RS implementations that make use of SIMD instructions?

nanors has SIMD optimizations too, but we don't really get much on x86_64 because it only guarantees SSE2. Bumping it to SSSE3 would enable the hand-optimized codepaths that should be much faster. Assuming we're willing to drop support for CPUs without SSSE3, it should just be as simple as adding -mssse3 to

set_source_files_properties("${CMAKE_SOURCE_DIR}/third-party/nanors/rs.c"
DIRECTORY"${CMAKE_SOURCE_DIR}""${TEST_DIR}"
PROPERTIES COMPILE_FLAGS"-include deps/obl/autoshim.h -ftree-vectorize")

If SSSE3 resolves the performance issues you saw at the bitrates we're targeting, that's probably enough. If we want to go further, we can use GCC/Clang function multiversioning to have the compiler build AVX2, SSSE3, and SSE2 variants, but that requires more extensive modifications. We could also switch to totally new library if necessary.

@ns6089

Copy link
Copy Markdown
ContributorAuthor

Yeah, enabling SSSE3 for nanors gives RS encode around 6 times speedup, bringing it to sub millisecond range. Don't need to bother with separate thread then, one less thing to worry about. We should absolutely enabled it.

@cgutman

Copy link
Copy Markdown
Collaborator

Excellent, that's a pretty substantial win.

In terms of hardware support we're dropping with SSSE3, it looks like Intel CPUs prior to Core 2/Atom (~2006), AMD CPUs prior to Bulldozer (~2011), and VIA CPUs prior to Nano (~2008). It looks like all common x64 emulation layers like Rosetta 2 and XTA/Prism support SSSE3, so there should be no issues there either.

The only non-SSSE3 CPUs there that might otherwise be performant enough for some modern games/applications would be AMD K10-based processors (Phenom II). However, those also lack AES-NI, so they're going to get punished by encryption too with ~20x more cycles/byte vs AES-NI.

Overall, I think bumping up the CPU requirement to SSSE3 is probably reasonable. Users with very old CPUs can use an older version of Sunshine.

@ns6089

Copy link
Copy Markdown
ContributorAuthor

@cgutman This generic low latency flow control doesn't seem to be working well, at least on Windows. WSASendMsg() in particular can take more than 5ms even when using extremely low batches (4 packets each), and that's with ethernet level (IEEE 802.3x) flow control disabled at link level. With a lot of calls the combined latency grows. Maybe we can outline all possible congestion scenarios and combat them on a case by case basis? I'm interested in what the aforementioned IEEE 802.3x can't cover. The first thing that comes to mind is streaming over the internet where WAN link is slower than LAN link, but we should be able to detect such cases and maybe apply higher latency throttling with 1ms packet batches.

@ns6089

Copy link
Copy Markdown
ContributorAuthor

The first thing that comes to mind is streaming over the internet where WAN link is slower than LAN link, but we should be able to detect such cases and maybe apply higher latency throttling with 1ms packet batches.

Or try using QoS shaping https://learn.microsoft.com/en-us/windows/win32/api/qos2/ns-qos2-qos_flowrate_outgoing
In theory this exactly what we want in this scenario, if it works of course.

@ns6089

Copy link
Copy Markdown
ContributorAuthor

Oh, turns out my travel wifi router has atrocious ethernet switch and more or less requires 0.1ms batches. I guess this is the kind of devices we have problems with. Will try to optimize for it I guess, even though WSASendMsg() occasionally shoots up to 10ms even on such abysmal batches,

@ns6089

Copy link
Copy Markdown
ContributorAuthor

Oh, turns out my travel wifi router has atrocious ethernet switch and more or less requires 0.1ms batches. I guess this is the kind of devices we have problems with. Will try to optimize for it I guess

Two things were necessary when dealing with this switch

  1. Increasing udp socket send buffer size with SO_SENDBUF
  2. Calling WSASendMsg() with small batches, 10 packets worked best

No sleep or pacing was needed, socket buffer took care of the congestion.
Streams easily at constant 300+Mbps now when before it couldn't even reach 100Mbps.

I guess I can try adding some throttling logic on top of this larger buffer. In theory it should be enough to appease slow clients without resorting to costly spin waits with periodic latency spikes.

@ns6089
ns6089force-pushed the paced_send branch 3 times, most recently from 04dc814 to ea2b9a6CompareJuly 7, 2024 21:40
@ns6089
ns6089 marked this pull request as ready for review July 7, 2024 21:52
@ns6089

Copy link
Copy Markdown
ContributorAuthor

Should be ready. Works really well on Windows from my tests, haven't tested Linux or MacOS.

@cgutman Maybe we can distinguish WAN streaming from LAN streaming based on the packet size? And apply more aggressive throttling in this case, based on requested bitrate. Something like 2 or 3 times the bitrate, will give 1/2 or 1/3 frame time latency.
ea2b9a6#diff-a8b463faa2b4901d7f646c0a3a856d705fd293dc7b99cee500a375dae91ef6bfR1402-R1403

@codecov

codecovBot commented Jul 7, 2024

Copy link
Copy Markdown

Codecov Report

Attention: Patch coverage is 5.81395% with 162 lines in your changes missing coverage. Please review.

Project coverage is 8.99%. Comparing base (6607a28) to head (4fb8438).
Report is 134 commits behind head on master.

Files with missing linesPatch %Lines
src/stream.cpp0.00%77 Missing and 27 partials ⚠️
src/platform/windows/misc.cpp14.58%39 Missing and 2 partials ⚠️
src/platform/linux/misc.cpp0.00%7 Missing ⚠️
src/platform/macos/misc.mm0.00%6 Missing ⚠️
src/platform/windows/display_base.cpp0.00%4 Missing ⚠️
Additional details and impacted files
@@ Coverage Diff @@## master #2803 +/- ##
=======================================
Coverage 8.99% 8.99% =======================================
Files 95 95 Lines 17312 17412 +100 Branches 8236 8272 +36 =======================================
+ Hits 1557 1567 +10 - Misses 12890 13118 +228 + Partials 2865 2727 -138 
FlagCoverage Δ
Linux6.76% <0.00%> (-0.05%)⬇️
Windows4.20% <5.69%> (+0.04%)⬆️
macOS-1210.03% <0.92%> (-0.07%)⬇️
macOS-139.94% <0.92%> (-0.07%)⬇️
macOS-1410.24% <0.92%> (-0.07%)⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing linesCoverage Δ
src/platform/common.h36.90% <100.00%> (+1.53%)⬆️
src/platform/windows/display.h7.24% <ø> (+0.10%)⬆️
src/utility.h28.50% <100.00%> (ø)
src/platform/windows/display_base.cpp12.95% <0.00%> (+0.45%)⬆️
src/platform/macos/misc.mm6.85% <0.00%> (-0.17%)⬇️
src/platform/linux/misc.cpp9.04% <0.00%> (-0.16%)⬇️
src/platform/windows/misc.cpp2.23% <14.58%> (+0.74%)⬆️
src/stream.cpp0.96% <0.00%> (+0.05%)⬆️

... and 20 files with indirect coverage changes

@ns6089

Copy link
Copy Markdown
ContributorAuthor

Fixed the typo in linux/macos code, builds shouldn't fail now.

@ReenigneArcherReenigneArcher mentioned this pull request Jul 8, 2024
11 tasks
@ns6089

Copy link
Copy Markdown
ContributorAuthor

I also have the follow-up refactoring to periodic loggers that remove most of the syntactic bloat from them, improving the readability.
https://github.com/ns6089/Sunshine/commit/60e2c2f98e405e6912bcf009ad4e7fe3c6a2b836#diff-a8b463faa2b4901d7f646c0a3a856d705fd293dc7b99cee500a375dae91ef6bf
I can add it to this PR, if anyone prefers.

@cgutmancgutman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Pacing behavior seems great in my testing on Windows and Linux. I'm seeing the expected behavior of densely packed FEC blocks without the nasty packet loss I had in my previous attempt.

Once these last few issues are resolved, this looks good to merge.

Comment threadcmake/targets/common.cmake Outdated
Comment threadsrc/stream.cpp Outdated
Comment threadsrc/stream.cpp Outdated
@ns6089ns6089 changed the title Try to implement basic network flow controlImplement basic network flow controlJul 10, 2024
cgutmanand others added 3 commits July 10, 2024 18:12
We were too conservative in determining our max data size before needing to split, which resulted in many frames being split into multiple FEC blocks unnecessarily.
We also just used a hardcoded split into 3 blocks instead of actually calculating how many blocks are actually required.
@ReenigneArcher
ReenigneArcher enabled auto-merge (squash) July 10, 2024 23:28
@ReenigneArcher
ReenigneArcher merged commit 037c61d into LizardByte:masterJul 11, 2024
KuleRucket pushed a commit to KuleRucket/Sunshine that referenced this pull request Oct 9, 2024
Co-authored-by: Cameron Gutman <aicommander@gmail.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@ns6089@cgutman@ReenigneArcher
, '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

Implement basic network flow control - #2803

Merged
ReenigneArcher merged 3 commits into
LizardByte:masterfrom
ns6089:paced_send
Jul 11, 2024
Merged

Implement basic network flow control#2803
ReenigneArcher merged 3 commits into
LizardByte:masterfrom
ns6089:paced_send

Conversation

@ns6089

@ns6089ns6089 commented Jul 4, 2024

Copy link
Copy Markdown
Contributor

Description

Combat RX/TX buffer overflows and improve multi-FEC on large frames.

Adopted from #1466
Should supersede #2787

Screenshot

Issues Fixed or Closed

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Dependency update (updates to dependencies)
  • Documentation update (changes to documentation)
  • Repository update (changes to repository files, e.g. .github/...)

Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have added or updated the in code docstring/documentation-blocks for new or existing methods/components

Branch Updates

LizardByte requires that branches be up-to-date before merging. This means that after any PR is merged, this branch
must be updated before it can be merged. You must also
Allow edits from maintainers.

  • I want maintainers to keep my branch updated

@ns6089

Copy link
Copy Markdown
ContributorAuthor

Basic implementation wasn't that hard, but it uncovered a few problems.

  1. I will try to implement hybrid sleep/spin wait after all, 0.5ms timer precision should be barely enough.
  2. On large bitrates our Reed-Solomon implementation takes significant amount of time. I will try moving it to separate thread, but in the long run it won't be enough.

@cgutman Have you considered alternative RS implementations that make use of SIMD instructions?
Like this one https://github.com/catid/leopard

@cgutman

Copy link
Copy Markdown
Collaborator

On large bitrates our Reed-Solomon implementation takes significant amount of time. I will try moving it to separate thread, but in the long run it won't be enough.

I don't think this needs to block merging this PR, unless you think these changes are going to make it worse somehow.

@cgutman Have you considered alternative RS implementations that make use of SIMD instructions?

nanors has SIMD optimizations too, but we don't really get much on x86_64 because it only guarantees SSE2. Bumping it to SSSE3 would enable the hand-optimized codepaths that should be much faster. Assuming we're willing to drop support for CPUs without SSSE3, it should just be as simple as adding -mssse3 to

set_source_files_properties("${CMAKE_SOURCE_DIR}/third-party/nanors/rs.c"
DIRECTORY"${CMAKE_SOURCE_DIR}""${TEST_DIR}"
PROPERTIES COMPILE_FLAGS"-include deps/obl/autoshim.h -ftree-vectorize")

If SSSE3 resolves the performance issues you saw at the bitrates we're targeting, that's probably enough. If we want to go further, we can use GCC/Clang function multiversioning to have the compiler build AVX2, SSSE3, and SSE2 variants, but that requires more extensive modifications. We could also switch to totally new library if necessary.

@ns6089

Copy link
Copy Markdown
ContributorAuthor

Yeah, enabling SSSE3 for nanors gives RS encode around 6 times speedup, bringing it to sub millisecond range. Don't need to bother with separate thread then, one less thing to worry about. We should absolutely enabled it.

@cgutman

Copy link
Copy Markdown
Collaborator

Excellent, that's a pretty substantial win.

In terms of hardware support we're dropping with SSSE3, it looks like Intel CPUs prior to Core 2/Atom (~2006), AMD CPUs prior to Bulldozer (~2011), and VIA CPUs prior to Nano (~2008). It looks like all common x64 emulation layers like Rosetta 2 and XTA/Prism support SSSE3, so there should be no issues there either.

The only non-SSSE3 CPUs there that might otherwise be performant enough for some modern games/applications would be AMD K10-based processors (Phenom II). However, those also lack AES-NI, so they're going to get punished by encryption too with ~20x more cycles/byte vs AES-NI.

Overall, I think bumping up the CPU requirement to SSSE3 is probably reasonable. Users with very old CPUs can use an older version of Sunshine.

@ns6089

Copy link
Copy Markdown
ContributorAuthor

@cgutman This generic low latency flow control doesn't seem to be working well, at least on Windows. WSASendMsg() in particular can take more than 5ms even when using extremely low batches (4 packets each), and that's with ethernet level (IEEE 802.3x) flow control disabled at link level. With a lot of calls the combined latency grows. Maybe we can outline all possible congestion scenarios and combat them on a case by case basis? I'm interested in what the aforementioned IEEE 802.3x can't cover. The first thing that comes to mind is streaming over the internet where WAN link is slower than LAN link, but we should be able to detect such cases and maybe apply higher latency throttling with 1ms packet batches.

@ns6089

Copy link
Copy Markdown
ContributorAuthor

The first thing that comes to mind is streaming over the internet where WAN link is slower than LAN link, but we should be able to detect such cases and maybe apply higher latency throttling with 1ms packet batches.

Or try using QoS shaping https://learn.microsoft.com/en-us/windows/win32/api/qos2/ns-qos2-qos_flowrate_outgoing
In theory this exactly what we want in this scenario, if it works of course.

@ns6089

Copy link
Copy Markdown
ContributorAuthor

Oh, turns out my travel wifi router has atrocious ethernet switch and more or less requires 0.1ms batches. I guess this is the kind of devices we have problems with. Will try to optimize for it I guess, even though WSASendMsg() occasionally shoots up to 10ms even on such abysmal batches,

@ns6089

Copy link
Copy Markdown
ContributorAuthor

Oh, turns out my travel wifi router has atrocious ethernet switch and more or less requires 0.1ms batches. I guess this is the kind of devices we have problems with. Will try to optimize for it I guess

Two things were necessary when dealing with this switch

  1. Increasing udp socket send buffer size with SO_SENDBUF
  2. Calling WSASendMsg() with small batches, 10 packets worked best

No sleep or pacing was needed, socket buffer took care of the congestion.
Streams easily at constant 300+Mbps now when before it couldn't even reach 100Mbps.

I guess I can try adding some throttling logic on top of this larger buffer. In theory it should be enough to appease slow clients without resorting to costly spin waits with periodic latency spikes.

@ns6089
ns6089force-pushed the paced_send branch 3 times, most recently from 04dc814 to ea2b9a6CompareJuly 7, 2024 21:40
@ns6089
ns6089 marked this pull request as ready for review July 7, 2024 21:52
@ns6089

Copy link
Copy Markdown
ContributorAuthor

Should be ready. Works really well on Windows from my tests, haven't tested Linux or MacOS.

@cgutman Maybe we can distinguish WAN streaming from LAN streaming based on the packet size? And apply more aggressive throttling in this case, based on requested bitrate. Something like 2 or 3 times the bitrate, will give 1/2 or 1/3 frame time latency.
ea2b9a6#diff-a8b463faa2b4901d7f646c0a3a856d705fd293dc7b99cee500a375dae91ef6bfR1402-R1403

@codecov

codecovBot commented Jul 7, 2024

Copy link
Copy Markdown

Codecov Report

Attention: Patch coverage is 5.81395% with 162 lines in your changes missing coverage. Please review.

Project coverage is 8.99%. Comparing base (6607a28) to head (4fb8438).
Report is 134 commits behind head on master.

Files with missing linesPatch %Lines
src/stream.cpp0.00%77 Missing and 27 partials ⚠️
src/platform/windows/misc.cpp14.58%39 Missing and 2 partials ⚠️
src/platform/linux/misc.cpp0.00%7 Missing ⚠️
src/platform/macos/misc.mm0.00%6 Missing ⚠️
src/platform/windows/display_base.cpp0.00%4 Missing ⚠️
Additional details and impacted files
@@ Coverage Diff @@## master #2803 +/- ##
=======================================
Coverage 8.99% 8.99% =======================================
Files 95 95 Lines 17312 17412 +100 Branches 8236 8272 +36 =======================================
+ Hits 1557 1567 +10 - Misses 12890 13118 +228 + Partials 2865 2727 -138 
FlagCoverage Δ
Linux6.76% <0.00%> (-0.05%)⬇️
Windows4.20% <5.69%> (+0.04%)⬆️
macOS-1210.03% <0.92%> (-0.07%)⬇️
macOS-139.94% <0.92%> (-0.07%)⬇️
macOS-1410.24% <0.92%> (-0.07%)⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing linesCoverage Δ
src/platform/common.h36.90% <100.00%> (+1.53%)⬆️
src/platform/windows/display.h7.24% <ø> (+0.10%)⬆️
src/utility.h28.50% <100.00%> (ø)
src/platform/windows/display_base.cpp12.95% <0.00%> (+0.45%)⬆️
src/platform/macos/misc.mm6.85% <0.00%> (-0.17%)⬇️
src/platform/linux/misc.cpp9.04% <0.00%> (-0.16%)⬇️
src/platform/windows/misc.cpp2.23% <14.58%> (+0.74%)⬆️
src/stream.cpp0.96% <0.00%> (+0.05%)⬆️

... and 20 files with indirect coverage changes

@ns6089

Copy link
Copy Markdown
ContributorAuthor

Fixed the typo in linux/macos code, builds shouldn't fail now.

@ReenigneArcherReenigneArcher mentioned this pull request Jul 8, 2024
11 tasks
@ns6089

Copy link
Copy Markdown
ContributorAuthor

I also have the follow-up refactoring to periodic loggers that remove most of the syntactic bloat from them, improving the readability.
https://github.com/ns6089/Sunshine/commit/60e2c2f98e405e6912bcf009ad4e7fe3c6a2b836#diff-a8b463faa2b4901d7f646c0a3a856d705fd293dc7b99cee500a375dae91ef6bf
I can add it to this PR, if anyone prefers.

@cgutmancgutman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Pacing behavior seems great in my testing on Windows and Linux. I'm seeing the expected behavior of densely packed FEC blocks without the nasty packet loss I had in my previous attempt.

Once these last few issues are resolved, this looks good to merge.

Comment threadcmake/targets/common.cmake Outdated
Comment threadsrc/stream.cpp Outdated
Comment threadsrc/stream.cpp Outdated
@ns6089ns6089 changed the title Try to implement basic network flow controlImplement basic network flow controlJul 10, 2024
cgutmanand others added 3 commits July 10, 2024 18:12
We were too conservative in determining our max data size before needing to split, which resulted in many frames being split into multiple FEC blocks unnecessarily.
We also just used a hardcoded split into 3 blocks instead of actually calculating how many blocks are actually required.
@ReenigneArcher
ReenigneArcher enabled auto-merge (squash) July 10, 2024 23:28
@ReenigneArcher
ReenigneArcher merged commit 037c61d into LizardByte:masterJul 11, 2024
KuleRucket pushed a commit to KuleRucket/Sunshine that referenced this pull request Oct 9, 2024
Co-authored-by: Cameron Gutman <aicommander@gmail.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@ns6089@cgutman@ReenigneArcher
, '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

Implement basic network flow control - #2803

Merged
ReenigneArcher merged 3 commits into
LizardByte:masterfrom
ns6089:paced_send
Jul 11, 2024
Merged

Implement basic network flow control#2803
ReenigneArcher merged 3 commits into
LizardByte:masterfrom
ns6089:paced_send

Conversation

@ns6089

@ns6089ns6089 commented Jul 4, 2024

Copy link
Copy Markdown
Contributor

Description

Combat RX/TX buffer overflows and improve multi-FEC on large frames.

Adopted from #1466
Should supersede #2787

Screenshot

Issues Fixed or Closed

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Dependency update (updates to dependencies)
  • Documentation update (changes to documentation)
  • Repository update (changes to repository files, e.g. .github/...)

Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have added or updated the in code docstring/documentation-blocks for new or existing methods/components

Branch Updates

LizardByte requires that branches be up-to-date before merging. This means that after any PR is merged, this branch
must be updated before it can be merged. You must also
Allow edits from maintainers.

  • I want maintainers to keep my branch updated

@ns6089

Copy link
Copy Markdown
ContributorAuthor

Basic implementation wasn't that hard, but it uncovered a few problems.

  1. I will try to implement hybrid sleep/spin wait after all, 0.5ms timer precision should be barely enough.
  2. On large bitrates our Reed-Solomon implementation takes significant amount of time. I will try moving it to separate thread, but in the long run it won't be enough.

@cgutman Have you considered alternative RS implementations that make use of SIMD instructions?
Like this one https://github.com/catid/leopard

@cgutman

Copy link
Copy Markdown
Collaborator

On large bitrates our Reed-Solomon implementation takes significant amount of time. I will try moving it to separate thread, but in the long run it won't be enough.

I don't think this needs to block merging this PR, unless you think these changes are going to make it worse somehow.

@cgutman Have you considered alternative RS implementations that make use of SIMD instructions?

nanors has SIMD optimizations too, but we don't really get much on x86_64 because it only guarantees SSE2. Bumping it to SSSE3 would enable the hand-optimized codepaths that should be much faster. Assuming we're willing to drop support for CPUs without SSSE3, it should just be as simple as adding -mssse3 to

set_source_files_properties("${CMAKE_SOURCE_DIR}/third-party/nanors/rs.c"
DIRECTORY"${CMAKE_SOURCE_DIR}""${TEST_DIR}"
PROPERTIES COMPILE_FLAGS"-include deps/obl/autoshim.h -ftree-vectorize")

If SSSE3 resolves the performance issues you saw at the bitrates we're targeting, that's probably enough. If we want to go further, we can use GCC/Clang function multiversioning to have the compiler build AVX2, SSSE3, and SSE2 variants, but that requires more extensive modifications. We could also switch to totally new library if necessary.

@ns6089

Copy link
Copy Markdown
ContributorAuthor

Yeah, enabling SSSE3 for nanors gives RS encode around 6 times speedup, bringing it to sub millisecond range. Don't need to bother with separate thread then, one less thing to worry about. We should absolutely enabled it.

@cgutman

Copy link
Copy Markdown
Collaborator

Excellent, that's a pretty substantial win.

In terms of hardware support we're dropping with SSSE3, it looks like Intel CPUs prior to Core 2/Atom (~2006), AMD CPUs prior to Bulldozer (~2011), and VIA CPUs prior to Nano (~2008). It looks like all common x64 emulation layers like Rosetta 2 and XTA/Prism support SSSE3, so there should be no issues there either.

The only non-SSSE3 CPUs there that might otherwise be performant enough for some modern games/applications would be AMD K10-based processors (Phenom II). However, those also lack AES-NI, so they're going to get punished by encryption too with ~20x more cycles/byte vs AES-NI.

Overall, I think bumping up the CPU requirement to SSSE3 is probably reasonable. Users with very old CPUs can use an older version of Sunshine.

@ns6089

Copy link
Copy Markdown
ContributorAuthor

@cgutman This generic low latency flow control doesn't seem to be working well, at least on Windows. WSASendMsg() in particular can take more than 5ms even when using extremely low batches (4 packets each), and that's with ethernet level (IEEE 802.3x) flow control disabled at link level. With a lot of calls the combined latency grows. Maybe we can outline all possible congestion scenarios and combat them on a case by case basis? I'm interested in what the aforementioned IEEE 802.3x can't cover. The first thing that comes to mind is streaming over the internet where WAN link is slower than LAN link, but we should be able to detect such cases and maybe apply higher latency throttling with 1ms packet batches.

@ns6089

Copy link
Copy Markdown
ContributorAuthor

The first thing that comes to mind is streaming over the internet where WAN link is slower than LAN link, but we should be able to detect such cases and maybe apply higher latency throttling with 1ms packet batches.

Or try using QoS shaping https://learn.microsoft.com/en-us/windows/win32/api/qos2/ns-qos2-qos_flowrate_outgoing
In theory this exactly what we want in this scenario, if it works of course.

@ns6089

Copy link
Copy Markdown
ContributorAuthor

Oh, turns out my travel wifi router has atrocious ethernet switch and more or less requires 0.1ms batches. I guess this is the kind of devices we have problems with. Will try to optimize for it I guess, even though WSASendMsg() occasionally shoots up to 10ms even on such abysmal batches,

@ns6089

Copy link
Copy Markdown
ContributorAuthor

Oh, turns out my travel wifi router has atrocious ethernet switch and more or less requires 0.1ms batches. I guess this is the kind of devices we have problems with. Will try to optimize for it I guess

Two things were necessary when dealing with this switch

  1. Increasing udp socket send buffer size with SO_SENDBUF
  2. Calling WSASendMsg() with small batches, 10 packets worked best

No sleep or pacing was needed, socket buffer took care of the congestion.
Streams easily at constant 300+Mbps now when before it couldn't even reach 100Mbps.

I guess I can try adding some throttling logic on top of this larger buffer. In theory it should be enough to appease slow clients without resorting to costly spin waits with periodic latency spikes.

@ns6089
ns6089force-pushed the paced_send branch 3 times, most recently from 04dc814 to ea2b9a6CompareJuly 7, 2024 21:40
@ns6089
ns6089 marked this pull request as ready for review July 7, 2024 21:52
@ns6089

Copy link
Copy Markdown
ContributorAuthor

Should be ready. Works really well on Windows from my tests, haven't tested Linux or MacOS.

@cgutman Maybe we can distinguish WAN streaming from LAN streaming based on the packet size? And apply more aggressive throttling in this case, based on requested bitrate. Something like 2 or 3 times the bitrate, will give 1/2 or 1/3 frame time latency.
ea2b9a6#diff-a8b463faa2b4901d7f646c0a3a856d705fd293dc7b99cee500a375dae91ef6bfR1402-R1403

@codecov

codecovBot commented Jul 7, 2024

Copy link
Copy Markdown

Codecov Report

Attention: Patch coverage is 5.81395% with 162 lines in your changes missing coverage. Please review.

Project coverage is 8.99%. Comparing base (6607a28) to head (4fb8438).
Report is 134 commits behind head on master.

Files with missing linesPatch %Lines
src/stream.cpp0.00%77 Missing and 27 partials ⚠️
src/platform/windows/misc.cpp14.58%39 Missing and 2 partials ⚠️
src/platform/linux/misc.cpp0.00%7 Missing ⚠️
src/platform/macos/misc.mm0.00%6 Missing ⚠️
src/platform/windows/display_base.cpp0.00%4 Missing ⚠️
Additional details and impacted files
@@ Coverage Diff @@## master #2803 +/- ##
=======================================
Coverage 8.99% 8.99% =======================================
Files 95 95 Lines 17312 17412 +100 Branches 8236 8272 +36 =======================================
+ Hits 1557 1567 +10 - Misses 12890 13118 +228 + Partials 2865 2727 -138 
FlagCoverage Δ
Linux6.76% <0.00%> (-0.05%)⬇️
Windows4.20% <5.69%> (+0.04%)⬆️
macOS-1210.03% <0.92%> (-0.07%)⬇️
macOS-139.94% <0.92%> (-0.07%)⬇️
macOS-1410.24% <0.92%> (-0.07%)⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing linesCoverage Δ
src/platform/common.h36.90% <100.00%> (+1.53%)⬆️
src/platform/windows/display.h7.24% <ø> (+0.10%)⬆️
src/utility.h28.50% <100.00%> (ø)
src/platform/windows/display_base.cpp12.95% <0.00%> (+0.45%)⬆️
src/platform/macos/misc.mm6.85% <0.00%> (-0.17%)⬇️
src/platform/linux/misc.cpp9.04% <0.00%> (-0.16%)⬇️
src/platform/windows/misc.cpp2.23% <14.58%> (+0.74%)⬆️
src/stream.cpp0.96% <0.00%> (+0.05%)⬆️

... and 20 files with indirect coverage changes

@ns6089

Copy link
Copy Markdown
ContributorAuthor

Fixed the typo in linux/macos code, builds shouldn't fail now.

@ReenigneArcherReenigneArcher mentioned this pull request Jul 8, 2024
11 tasks
@ns6089

Copy link
Copy Markdown
ContributorAuthor

I also have the follow-up refactoring to periodic loggers that remove most of the syntactic bloat from them, improving the readability.
https://github.com/ns6089/Sunshine/commit/60e2c2f98e405e6912bcf009ad4e7fe3c6a2b836#diff-a8b463faa2b4901d7f646c0a3a856d705fd293dc7b99cee500a375dae91ef6bf
I can add it to this PR, if anyone prefers.

@cgutmancgutman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Pacing behavior seems great in my testing on Windows and Linux. I'm seeing the expected behavior of densely packed FEC blocks without the nasty packet loss I had in my previous attempt.

Once these last few issues are resolved, this looks good to merge.

Comment threadcmake/targets/common.cmake Outdated
Comment threadsrc/stream.cpp Outdated
Comment threadsrc/stream.cpp Outdated
@ns6089ns6089 changed the title Try to implement basic network flow controlImplement basic network flow controlJul 10, 2024
cgutmanand others added 3 commits July 10, 2024 18:12
We were too conservative in determining our max data size before needing to split, which resulted in many frames being split into multiple FEC blocks unnecessarily.
We also just used a hardcoded split into 3 blocks instead of actually calculating how many blocks are actually required.
@ReenigneArcher
ReenigneArcher enabled auto-merge (squash) July 10, 2024 23:28
@ReenigneArcher
ReenigneArcher merged commit 037c61d into LizardByte:masterJul 11, 2024
KuleRucket pushed a commit to KuleRucket/Sunshine that referenced this pull request Oct 9, 2024
Co-authored-by: Cameron Gutman <aicommander@gmail.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@ns6089@cgutman@ReenigneArcher
, '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

Implement basic network flow control - #2803

Merged
ReenigneArcher merged 3 commits into
LizardByte:masterfrom
ns6089:paced_send
Jul 11, 2024
Merged

Implement basic network flow control#2803
ReenigneArcher merged 3 commits into
LizardByte:masterfrom
ns6089:paced_send

Conversation

@ns6089

@ns6089ns6089 commented Jul 4, 2024

Copy link
Copy Markdown
Contributor

Description

Combat RX/TX buffer overflows and improve multi-FEC on large frames.

Adopted from #1466
Should supersede #2787

Screenshot

Issues Fixed or Closed

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Dependency update (updates to dependencies)
  • Documentation update (changes to documentation)
  • Repository update (changes to repository files, e.g. .github/...)

Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have added or updated the in code docstring/documentation-blocks for new or existing methods/components

Branch Updates

LizardByte requires that branches be up-to-date before merging. This means that after any PR is merged, this branch
must be updated before it can be merged. You must also
Allow edits from maintainers.

  • I want maintainers to keep my branch updated

@ns6089

Copy link
Copy Markdown
ContributorAuthor

Basic implementation wasn't that hard, but it uncovered a few problems.

  1. I will try to implement hybrid sleep/spin wait after all, 0.5ms timer precision should be barely enough.
  2. On large bitrates our Reed-Solomon implementation takes significant amount of time. I will try moving it to separate thread, but in the long run it won't be enough.

@cgutman Have you considered alternative RS implementations that make use of SIMD instructions?
Like this one https://github.com/catid/leopard

@cgutman

Copy link
Copy Markdown
Collaborator

On large bitrates our Reed-Solomon implementation takes significant amount of time. I will try moving it to separate thread, but in the long run it won't be enough.

I don't think this needs to block merging this PR, unless you think these changes are going to make it worse somehow.

@cgutman Have you considered alternative RS implementations that make use of SIMD instructions?

nanors has SIMD optimizations too, but we don't really get much on x86_64 because it only guarantees SSE2. Bumping it to SSSE3 would enable the hand-optimized codepaths that should be much faster. Assuming we're willing to drop support for CPUs without SSSE3, it should just be as simple as adding -mssse3 to

set_source_files_properties("${CMAKE_SOURCE_DIR}/third-party/nanors/rs.c"
DIRECTORY"${CMAKE_SOURCE_DIR}""${TEST_DIR}"
PROPERTIES COMPILE_FLAGS"-include deps/obl/autoshim.h -ftree-vectorize")

If SSSE3 resolves the performance issues you saw at the bitrates we're targeting, that's probably enough. If we want to go further, we can use GCC/Clang function multiversioning to have the compiler build AVX2, SSSE3, and SSE2 variants, but that requires more extensive modifications. We could also switch to totally new library if necessary.

@ns6089

Copy link
Copy Markdown
ContributorAuthor

Yeah, enabling SSSE3 for nanors gives RS encode around 6 times speedup, bringing it to sub millisecond range. Don't need to bother with separate thread then, one less thing to worry about. We should absolutely enabled it.

@cgutman

Copy link
Copy Markdown
Collaborator

Excellent, that's a pretty substantial win.

In terms of hardware support we're dropping with SSSE3, it looks like Intel CPUs prior to Core 2/Atom (~2006), AMD CPUs prior to Bulldozer (~2011), and VIA CPUs prior to Nano (~2008). It looks like all common x64 emulation layers like Rosetta 2 and XTA/Prism support SSSE3, so there should be no issues there either.

The only non-SSSE3 CPUs there that might otherwise be performant enough for some modern games/applications would be AMD K10-based processors (Phenom II). However, those also lack AES-NI, so they're going to get punished by encryption too with ~20x more cycles/byte vs AES-NI.

Overall, I think bumping up the CPU requirement to SSSE3 is probably reasonable. Users with very old CPUs can use an older version of Sunshine.

@ns6089

Copy link
Copy Markdown
ContributorAuthor

@cgutman This generic low latency flow control doesn't seem to be working well, at least on Windows. WSASendMsg() in particular can take more than 5ms even when using extremely low batches (4 packets each), and that's with ethernet level (IEEE 802.3x) flow control disabled at link level. With a lot of calls the combined latency grows. Maybe we can outline all possible congestion scenarios and combat them on a case by case basis? I'm interested in what the aforementioned IEEE 802.3x can't cover. The first thing that comes to mind is streaming over the internet where WAN link is slower than LAN link, but we should be able to detect such cases and maybe apply higher latency throttling with 1ms packet batches.

@ns6089

Copy link
Copy Markdown
ContributorAuthor

The first thing that comes to mind is streaming over the internet where WAN link is slower than LAN link, but we should be able to detect such cases and maybe apply higher latency throttling with 1ms packet batches.

Or try using QoS shaping https://learn.microsoft.com/en-us/windows/win32/api/qos2/ns-qos2-qos_flowrate_outgoing
In theory this exactly what we want in this scenario, if it works of course.

@ns6089

Copy link
Copy Markdown
ContributorAuthor

Oh, turns out my travel wifi router has atrocious ethernet switch and more or less requires 0.1ms batches. I guess this is the kind of devices we have problems with. Will try to optimize for it I guess, even though WSASendMsg() occasionally shoots up to 10ms even on such abysmal batches,

@ns6089

Copy link
Copy Markdown
ContributorAuthor

Oh, turns out my travel wifi router has atrocious ethernet switch and more or less requires 0.1ms batches. I guess this is the kind of devices we have problems with. Will try to optimize for it I guess

Two things were necessary when dealing with this switch

  1. Increasing udp socket send buffer size with SO_SENDBUF
  2. Calling WSASendMsg() with small batches, 10 packets worked best

No sleep or pacing was needed, socket buffer took care of the congestion.
Streams easily at constant 300+Mbps now when before it couldn't even reach 100Mbps.

I guess I can try adding some throttling logic on top of this larger buffer. In theory it should be enough to appease slow clients without resorting to costly spin waits with periodic latency spikes.

@ns6089
ns6089force-pushed the paced_send branch 3 times, most recently from 04dc814 to ea2b9a6CompareJuly 7, 2024 21:40
@ns6089
ns6089 marked this pull request as ready for review July 7, 2024 21:52
@ns6089

Copy link
Copy Markdown
ContributorAuthor

Should be ready. Works really well on Windows from my tests, haven't tested Linux or MacOS.

@cgutman Maybe we can distinguish WAN streaming from LAN streaming based on the packet size? And apply more aggressive throttling in this case, based on requested bitrate. Something like 2 or 3 times the bitrate, will give 1/2 or 1/3 frame time latency.
ea2b9a6#diff-a8b463faa2b4901d7f646c0a3a856d705fd293dc7b99cee500a375dae91ef6bfR1402-R1403

@codecov

codecovBot commented Jul 7, 2024

Copy link
Copy Markdown

Codecov Report

Attention: Patch coverage is 5.81395% with 162 lines in your changes missing coverage. Please review.

Project coverage is 8.99%. Comparing base (6607a28) to head (4fb8438).
Report is 134 commits behind head on master.

Files with missing linesPatch %Lines
src/stream.cpp0.00%77 Missing and 27 partials ⚠️
src/platform/windows/misc.cpp14.58%39 Missing and 2 partials ⚠️
src/platform/linux/misc.cpp0.00%7 Missing ⚠️
src/platform/macos/misc.mm0.00%6 Missing ⚠️
src/platform/windows/display_base.cpp0.00%4 Missing ⚠️
Additional details and impacted files
@@ Coverage Diff @@## master #2803 +/- ##
=======================================
Coverage 8.99% 8.99% =======================================
Files 95 95 Lines 17312 17412 +100 Branches 8236 8272 +36 =======================================
+ Hits 1557 1567 +10 - Misses 12890 13118 +228 + Partials 2865 2727 -138 
FlagCoverage Δ
Linux6.76% <0.00%> (-0.05%)⬇️
Windows4.20% <5.69%> (+0.04%)⬆️
macOS-1210.03% <0.92%> (-0.07%)⬇️
macOS-139.94% <0.92%> (-0.07%)⬇️
macOS-1410.24% <0.92%> (-0.07%)⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing linesCoverage Δ
src/platform/common.h36.90% <100.00%> (+1.53%)⬆️
src/platform/windows/display.h7.24% <ø> (+0.10%)⬆️
src/utility.h28.50% <100.00%> (ø)
src/platform/windows/display_base.cpp12.95% <0.00%> (+0.45%)⬆️
src/platform/macos/misc.mm6.85% <0.00%> (-0.17%)⬇️
src/platform/linux/misc.cpp9.04% <0.00%> (-0.16%)⬇️
src/platform/windows/misc.cpp2.23% <14.58%> (+0.74%)⬆️
src/stream.cpp0.96% <0.00%> (+0.05%)⬆️

... and 20 files with indirect coverage changes

@ns6089

Copy link
Copy Markdown
ContributorAuthor

Fixed the typo in linux/macos code, builds shouldn't fail now.

@ReenigneArcherReenigneArcher mentioned this pull request Jul 8, 2024
11 tasks
@ns6089

Copy link
Copy Markdown
ContributorAuthor

I also have the follow-up refactoring to periodic loggers that remove most of the syntactic bloat from them, improving the readability.
https://github.com/ns6089/Sunshine/commit/60e2c2f98e405e6912bcf009ad4e7fe3c6a2b836#diff-a8b463faa2b4901d7f646c0a3a856d705fd293dc7b99cee500a375dae91ef6bf
I can add it to this PR, if anyone prefers.

@cgutmancgutman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Pacing behavior seems great in my testing on Windows and Linux. I'm seeing the expected behavior of densely packed FEC blocks without the nasty packet loss I had in my previous attempt.

Once these last few issues are resolved, this looks good to merge.

Comment threadcmake/targets/common.cmake Outdated
Comment threadsrc/stream.cpp Outdated
Comment threadsrc/stream.cpp Outdated
@ns6089ns6089 changed the title Try to implement basic network flow controlImplement basic network flow controlJul 10, 2024
cgutmanand others added 3 commits July 10, 2024 18:12
We were too conservative in determining our max data size before needing to split, which resulted in many frames being split into multiple FEC blocks unnecessarily.
We also just used a hardcoded split into 3 blocks instead of actually calculating how many blocks are actually required.
@ReenigneArcher
ReenigneArcher enabled auto-merge (squash) July 10, 2024 23:28
@ReenigneArcher
ReenigneArcher merged commit 037c61d into LizardByte:masterJul 11, 2024
KuleRucket pushed a commit to KuleRucket/Sunshine that referenced this pull request Oct 9, 2024
Co-authored-by: Cameron Gutman <aicommander@gmail.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@ns6089@cgutman@ReenigneArcher
, '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

Implement basic network flow control - #2803

Merged
ReenigneArcher merged 3 commits into
LizardByte:masterfrom
ns6089:paced_send
Jul 11, 2024
Merged

Implement basic network flow control#2803
ReenigneArcher merged 3 commits into
LizardByte:masterfrom
ns6089:paced_send

Conversation

@ns6089

@ns6089ns6089 commented Jul 4, 2024

Copy link
Copy Markdown
Contributor

Description

Combat RX/TX buffer overflows and improve multi-FEC on large frames.

Adopted from #1466
Should supersede #2787

Screenshot

Issues Fixed or Closed

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Dependency update (updates to dependencies)
  • Documentation update (changes to documentation)
  • Repository update (changes to repository files, e.g. .github/...)

Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have added or updated the in code docstring/documentation-blocks for new or existing methods/components

Branch Updates

LizardByte requires that branches be up-to-date before merging. This means that after any PR is merged, this branch
must be updated before it can be merged. You must also
Allow edits from maintainers.

  • I want maintainers to keep my branch updated

@ns6089

Copy link
Copy Markdown
ContributorAuthor

Basic implementation wasn't that hard, but it uncovered a few problems.

  1. I will try to implement hybrid sleep/spin wait after all, 0.5ms timer precision should be barely enough.
  2. On large bitrates our Reed-Solomon implementation takes significant amount of time. I will try moving it to separate thread, but in the long run it won't be enough.

@cgutman Have you considered alternative RS implementations that make use of SIMD instructions?
Like this one https://github.com/catid/leopard

@cgutman

Copy link
Copy Markdown
Collaborator

On large bitrates our Reed-Solomon implementation takes significant amount of time. I will try moving it to separate thread, but in the long run it won't be enough.

I don't think this needs to block merging this PR, unless you think these changes are going to make it worse somehow.

@cgutman Have you considered alternative RS implementations that make use of SIMD instructions?

nanors has SIMD optimizations too, but we don't really get much on x86_64 because it only guarantees SSE2. Bumping it to SSSE3 would enable the hand-optimized codepaths that should be much faster. Assuming we're willing to drop support for CPUs without SSSE3, it should just be as simple as adding -mssse3 to

set_source_files_properties("${CMAKE_SOURCE_DIR}/third-party/nanors/rs.c"
DIRECTORY"${CMAKE_SOURCE_DIR}""${TEST_DIR}"
PROPERTIES COMPILE_FLAGS"-include deps/obl/autoshim.h -ftree-vectorize")

If SSSE3 resolves the performance issues you saw at the bitrates we're targeting, that's probably enough. If we want to go further, we can use GCC/Clang function multiversioning to have the compiler build AVX2, SSSE3, and SSE2 variants, but that requires more extensive modifications. We could also switch to totally new library if necessary.

@ns6089

Copy link
Copy Markdown
ContributorAuthor

Yeah, enabling SSSE3 for nanors gives RS encode around 6 times speedup, bringing it to sub millisecond range. Don't need to bother with separate thread then, one less thing to worry about. We should absolutely enabled it.

@cgutman

Copy link
Copy Markdown
Collaborator

Excellent, that's a pretty substantial win.

In terms of hardware support we're dropping with SSSE3, it looks like Intel CPUs prior to Core 2/Atom (~2006), AMD CPUs prior to Bulldozer (~2011), and VIA CPUs prior to Nano (~2008). It looks like all common x64 emulation layers like Rosetta 2 and XTA/Prism support SSSE3, so there should be no issues there either.

The only non-SSSE3 CPUs there that might otherwise be performant enough for some modern games/applications would be AMD K10-based processors (Phenom II). However, those also lack AES-NI, so they're going to get punished by encryption too with ~20x more cycles/byte vs AES-NI.

Overall, I think bumping up the CPU requirement to SSSE3 is probably reasonable. Users with very old CPUs can use an older version of Sunshine.

@ns6089

Copy link
Copy Markdown
ContributorAuthor

@cgutman This generic low latency flow control doesn't seem to be working well, at least on Windows. WSASendMsg() in particular can take more than 5ms even when using extremely low batches (4 packets each), and that's with ethernet level (IEEE 802.3x) flow control disabled at link level. With a lot of calls the combined latency grows. Maybe we can outline all possible congestion scenarios and combat them on a case by case basis? I'm interested in what the aforementioned IEEE 802.3x can't cover. The first thing that comes to mind is streaming over the internet where WAN link is slower than LAN link, but we should be able to detect such cases and maybe apply higher latency throttling with 1ms packet batches.

@ns6089

Copy link
Copy Markdown
ContributorAuthor

The first thing that comes to mind is streaming over the internet where WAN link is slower than LAN link, but we should be able to detect such cases and maybe apply higher latency throttling with 1ms packet batches.

Or try using QoS shaping https://learn.microsoft.com/en-us/windows/win32/api/qos2/ns-qos2-qos_flowrate_outgoing
In theory this exactly what we want in this scenario, if it works of course.

@ns6089

Copy link
Copy Markdown
ContributorAuthor

Oh, turns out my travel wifi router has atrocious ethernet switch and more or less requires 0.1ms batches. I guess this is the kind of devices we have problems with. Will try to optimize for it I guess, even though WSASendMsg() occasionally shoots up to 10ms even on such abysmal batches,

@ns6089

Copy link
Copy Markdown
ContributorAuthor

Oh, turns out my travel wifi router has atrocious ethernet switch and more or less requires 0.1ms batches. I guess this is the kind of devices we have problems with. Will try to optimize for it I guess

Two things were necessary when dealing with this switch

  1. Increasing udp socket send buffer size with SO_SENDBUF
  2. Calling WSASendMsg() with small batches, 10 packets worked best

No sleep or pacing was needed, socket buffer took care of the congestion.
Streams easily at constant 300+Mbps now when before it couldn't even reach 100Mbps.

I guess I can try adding some throttling logic on top of this larger buffer. In theory it should be enough to appease slow clients without resorting to costly spin waits with periodic latency spikes.

@ns6089
ns6089force-pushed the paced_send branch 3 times, most recently from 04dc814 to ea2b9a6CompareJuly 7, 2024 21:40
@ns6089
ns6089 marked this pull request as ready for review July 7, 2024 21:52
@ns6089

Copy link
Copy Markdown
ContributorAuthor

Should be ready. Works really well on Windows from my tests, haven't tested Linux or MacOS.

@cgutman Maybe we can distinguish WAN streaming from LAN streaming based on the packet size? And apply more aggressive throttling in this case, based on requested bitrate. Something like 2 or 3 times the bitrate, will give 1/2 or 1/3 frame time latency.
ea2b9a6#diff-a8b463faa2b4901d7f646c0a3a856d705fd293dc7b99cee500a375dae91ef6bfR1402-R1403

@codecov

codecovBot commented Jul 7, 2024

Copy link
Copy Markdown

Codecov Report

Attention: Patch coverage is 5.81395% with 162 lines in your changes missing coverage. Please review.

Project coverage is 8.99%. Comparing base (6607a28) to head (4fb8438).
Report is 134 commits behind head on master.

Files with missing linesPatch %Lines
src/stream.cpp0.00%77 Missing and 27 partials ⚠️
src/platform/windows/misc.cpp14.58%39 Missing and 2 partials ⚠️
src/platform/linux/misc.cpp0.00%7 Missing ⚠️
src/platform/macos/misc.mm0.00%6 Missing ⚠️
src/platform/windows/display_base.cpp0.00%4 Missing ⚠️
Additional details and impacted files
@@ Coverage Diff @@## master #2803 +/- ##
=======================================
Coverage 8.99% 8.99% =======================================
Files 95 95 Lines 17312 17412 +100 Branches 8236 8272 +36 =======================================
+ Hits 1557 1567 +10 - Misses 12890 13118 +228 + Partials 2865 2727 -138 
FlagCoverage Δ
Linux6.76% <0.00%> (-0.05%)⬇️
Windows4.20% <5.69%> (+0.04%)⬆️
macOS-1210.03% <0.92%> (-0.07%)⬇️
macOS-139.94% <0.92%> (-0.07%)⬇️
macOS-1410.24% <0.92%> (-0.07%)⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing linesCoverage Δ
src/platform/common.h36.90% <100.00%> (+1.53%)⬆️
src/platform/windows/display.h7.24% <ø> (+0.10%)⬆️
src/utility.h28.50% <100.00%> (ø)
src/platform/windows/display_base.cpp12.95% <0.00%> (+0.45%)⬆️
src/platform/macos/misc.mm6.85% <0.00%> (-0.17%)⬇️
src/platform/linux/misc.cpp9.04% <0.00%> (-0.16%)⬇️
src/platform/windows/misc.cpp2.23% <14.58%> (+0.74%)⬆️
src/stream.cpp0.96% <0.00%> (+0.05%)⬆️

... and 20 files with indirect coverage changes

@ns6089

Copy link
Copy Markdown
ContributorAuthor

Fixed the typo in linux/macos code, builds shouldn't fail now.

@ReenigneArcherReenigneArcher mentioned this pull request Jul 8, 2024
11 tasks
@ns6089

Copy link
Copy Markdown
ContributorAuthor

I also have the follow-up refactoring to periodic loggers that remove most of the syntactic bloat from them, improving the readability.
https://github.com/ns6089/Sunshine/commit/60e2c2f98e405e6912bcf009ad4e7fe3c6a2b836#diff-a8b463faa2b4901d7f646c0a3a856d705fd293dc7b99cee500a375dae91ef6bf
I can add it to this PR, if anyone prefers.

@cgutmancgutman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Pacing behavior seems great in my testing on Windows and Linux. I'm seeing the expected behavior of densely packed FEC blocks without the nasty packet loss I had in my previous attempt.

Once these last few issues are resolved, this looks good to merge.

Comment threadcmake/targets/common.cmake Outdated
Comment threadsrc/stream.cpp Outdated
Comment threadsrc/stream.cpp Outdated
@ns6089ns6089 changed the title Try to implement basic network flow controlImplement basic network flow controlJul 10, 2024
cgutmanand others added 3 commits July 10, 2024 18:12
We were too conservative in determining our max data size before needing to split, which resulted in many frames being split into multiple FEC blocks unnecessarily.
We also just used a hardcoded split into 3 blocks instead of actually calculating how many blocks are actually required.
@ReenigneArcher
ReenigneArcher enabled auto-merge (squash) July 10, 2024 23:28
@ReenigneArcher
ReenigneArcher merged commit 037c61d into LizardByte:masterJul 11, 2024
KuleRucket pushed a commit to KuleRucket/Sunshine that referenced this pull request Oct 9, 2024
Co-authored-by: Cameron Gutman <aicommander@gmail.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@ns6089@cgutman@ReenigneArcher
, '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

Implement basic network flow control - #2803

Merged
ReenigneArcher merged 3 commits into
LizardByte:masterfrom
ns6089:paced_send
Jul 11, 2024
Merged

Implement basic network flow control#2803
ReenigneArcher merged 3 commits into
LizardByte:masterfrom
ns6089:paced_send

Conversation

@ns6089

@ns6089ns6089 commented Jul 4, 2024

Copy link
Copy Markdown
Contributor

Description

Combat RX/TX buffer overflows and improve multi-FEC on large frames.

Adopted from #1466
Should supersede #2787

Screenshot

Issues Fixed or Closed

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Dependency update (updates to dependencies)
  • Documentation update (changes to documentation)
  • Repository update (changes to repository files, e.g. .github/...)

Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have added or updated the in code docstring/documentation-blocks for new or existing methods/components

Branch Updates

LizardByte requires that branches be up-to-date before merging. This means that after any PR is merged, this branch
must be updated before it can be merged. You must also
Allow edits from maintainers.

  • I want maintainers to keep my branch updated

@ns6089

Copy link
Copy Markdown
ContributorAuthor

Basic implementation wasn't that hard, but it uncovered a few problems.

  1. I will try to implement hybrid sleep/spin wait after all, 0.5ms timer precision should be barely enough.
  2. On large bitrates our Reed-Solomon implementation takes significant amount of time. I will try moving it to separate thread, but in the long run it won't be enough.

@cgutman Have you considered alternative RS implementations that make use of SIMD instructions?
Like this one https://github.com/catid/leopard

@cgutman

Copy link
Copy Markdown
Collaborator

On large bitrates our Reed-Solomon implementation takes significant amount of time. I will try moving it to separate thread, but in the long run it won't be enough.

I don't think this needs to block merging this PR, unless you think these changes are going to make it worse somehow.

@cgutman Have you considered alternative RS implementations that make use of SIMD instructions?

nanors has SIMD optimizations too, but we don't really get much on x86_64 because it only guarantees SSE2. Bumping it to SSSE3 would enable the hand-optimized codepaths that should be much faster. Assuming we're willing to drop support for CPUs without SSSE3, it should just be as simple as adding -mssse3 to

set_source_files_properties("${CMAKE_SOURCE_DIR}/third-party/nanors/rs.c"
DIRECTORY"${CMAKE_SOURCE_DIR}""${TEST_DIR}"
PROPERTIES COMPILE_FLAGS"-include deps/obl/autoshim.h -ftree-vectorize")

If SSSE3 resolves the performance issues you saw at the bitrates we're targeting, that's probably enough. If we want to go further, we can use GCC/Clang function multiversioning to have the compiler build AVX2, SSSE3, and SSE2 variants, but that requires more extensive modifications. We could also switch to totally new library if necessary.

@ns6089

Copy link
Copy Markdown
ContributorAuthor

Yeah, enabling SSSE3 for nanors gives RS encode around 6 times speedup, bringing it to sub millisecond range. Don't need to bother with separate thread then, one less thing to worry about. We should absolutely enabled it.

@cgutman

Copy link
Copy Markdown
Collaborator

Excellent, that's a pretty substantial win.

In terms of hardware support we're dropping with SSSE3, it looks like Intel CPUs prior to Core 2/Atom (~2006), AMD CPUs prior to Bulldozer (~2011), and VIA CPUs prior to Nano (~2008). It looks like all common x64 emulation layers like Rosetta 2 and XTA/Prism support SSSE3, so there should be no issues there either.

The only non-SSSE3 CPUs there that might otherwise be performant enough for some modern games/applications would be AMD K10-based processors (Phenom II). However, those also lack AES-NI, so they're going to get punished by encryption too with ~20x more cycles/byte vs AES-NI.

Overall, I think bumping up the CPU requirement to SSSE3 is probably reasonable. Users with very old CPUs can use an older version of Sunshine.

@ns6089

Copy link
Copy Markdown
ContributorAuthor

@cgutman This generic low latency flow control doesn't seem to be working well, at least on Windows. WSASendMsg() in particular can take more than 5ms even when using extremely low batches (4 packets each), and that's with ethernet level (IEEE 802.3x) flow control disabled at link level. With a lot of calls the combined latency grows. Maybe we can outline all possible congestion scenarios and combat them on a case by case basis? I'm interested in what the aforementioned IEEE 802.3x can't cover. The first thing that comes to mind is streaming over the internet where WAN link is slower than LAN link, but we should be able to detect such cases and maybe apply higher latency throttling with 1ms packet batches.

@ns6089

Copy link
Copy Markdown
ContributorAuthor

The first thing that comes to mind is streaming over the internet where WAN link is slower than LAN link, but we should be able to detect such cases and maybe apply higher latency throttling with 1ms packet batches.

Or try using QoS shaping https://learn.microsoft.com/en-us/windows/win32/api/qos2/ns-qos2-qos_flowrate_outgoing
In theory this exactly what we want in this scenario, if it works of course.

@ns6089

Copy link
Copy Markdown
ContributorAuthor

Oh, turns out my travel wifi router has atrocious ethernet switch and more or less requires 0.1ms batches. I guess this is the kind of devices we have problems with. Will try to optimize for it I guess, even though WSASendMsg() occasionally shoots up to 10ms even on such abysmal batches,

@ns6089

Copy link
Copy Markdown
ContributorAuthor

Oh, turns out my travel wifi router has atrocious ethernet switch and more or less requires 0.1ms batches. I guess this is the kind of devices we have problems with. Will try to optimize for it I guess

Two things were necessary when dealing with this switch

  1. Increasing udp socket send buffer size with SO_SENDBUF
  2. Calling WSASendMsg() with small batches, 10 packets worked best

No sleep or pacing was needed, socket buffer took care of the congestion.
Streams easily at constant 300+Mbps now when before it couldn't even reach 100Mbps.

I guess I can try adding some throttling logic on top of this larger buffer. In theory it should be enough to appease slow clients without resorting to costly spin waits with periodic latency spikes.

@ns6089
ns6089force-pushed the paced_send branch 3 times, most recently from 04dc814 to ea2b9a6CompareJuly 7, 2024 21:40
@ns6089
ns6089 marked this pull request as ready for review July 7, 2024 21:52
@ns6089

Copy link
Copy Markdown
ContributorAuthor

Should be ready. Works really well on Windows from my tests, haven't tested Linux or MacOS.

@cgutman Maybe we can distinguish WAN streaming from LAN streaming based on the packet size? And apply more aggressive throttling in this case, based on requested bitrate. Something like 2 or 3 times the bitrate, will give 1/2 or 1/3 frame time latency.
ea2b9a6#diff-a8b463faa2b4901d7f646c0a3a856d705fd293dc7b99cee500a375dae91ef6bfR1402-R1403

@codecov

codecovBot commented Jul 7, 2024

Copy link
Copy Markdown

Codecov Report

Attention: Patch coverage is 5.81395% with 162 lines in your changes missing coverage. Please review.

Project coverage is 8.99%. Comparing base (6607a28) to head (4fb8438).
Report is 134 commits behind head on master.

Files with missing linesPatch %Lines
src/stream.cpp0.00%77 Missing and 27 partials ⚠️
src/platform/windows/misc.cpp14.58%39 Missing and 2 partials ⚠️
src/platform/linux/misc.cpp0.00%7 Missing ⚠️
src/platform/macos/misc.mm0.00%6 Missing ⚠️
src/platform/windows/display_base.cpp0.00%4 Missing ⚠️
Additional details and impacted files
@@ Coverage Diff @@## master #2803 +/- ##
=======================================
Coverage 8.99% 8.99% =======================================
Files 95 95 Lines 17312 17412 +100 Branches 8236 8272 +36 =======================================
+ Hits 1557 1567 +10 - Misses 12890 13118 +228 + Partials 2865 2727 -138 
FlagCoverage Δ
Linux6.76% <0.00%> (-0.05%)⬇️
Windows4.20% <5.69%> (+0.04%)⬆️
macOS-1210.03% <0.92%> (-0.07%)⬇️
macOS-139.94% <0.92%> (-0.07%)⬇️
macOS-1410.24% <0.92%> (-0.07%)⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing linesCoverage Δ
src/platform/common.h36.90% <100.00%> (+1.53%)⬆️
src/platform/windows/display.h7.24% <ø> (+0.10%)⬆️
src/utility.h28.50% <100.00%> (ø)
src/platform/windows/display_base.cpp12.95% <0.00%> (+0.45%)⬆️
src/platform/macos/misc.mm6.85% <0.00%> (-0.17%)⬇️
src/platform/linux/misc.cpp9.04% <0.00%> (-0.16%)⬇️
src/platform/windows/misc.cpp2.23% <14.58%> (+0.74%)⬆️
src/stream.cpp0.96% <0.00%> (+0.05%)⬆️

... and 20 files with indirect coverage changes

@ns6089

Copy link
Copy Markdown
ContributorAuthor

Fixed the typo in linux/macos code, builds shouldn't fail now.

@ReenigneArcherReenigneArcher mentioned this pull request Jul 8, 2024
11 tasks
@ns6089

Copy link
Copy Markdown
ContributorAuthor

I also have the follow-up refactoring to periodic loggers that remove most of the syntactic bloat from them, improving the readability.
https://github.com/ns6089/Sunshine/commit/60e2c2f98e405e6912bcf009ad4e7fe3c6a2b836#diff-a8b463faa2b4901d7f646c0a3a856d705fd293dc7b99cee500a375dae91ef6bf
I can add it to this PR, if anyone prefers.

@cgutmancgutman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Pacing behavior seems great in my testing on Windows and Linux. I'm seeing the expected behavior of densely packed FEC blocks without the nasty packet loss I had in my previous attempt.

Once these last few issues are resolved, this looks good to merge.

Comment threadcmake/targets/common.cmake Outdated
Comment threadsrc/stream.cpp Outdated
Comment threadsrc/stream.cpp Outdated
@ns6089ns6089 changed the title Try to implement basic network flow controlImplement basic network flow controlJul 10, 2024
cgutmanand others added 3 commits July 10, 2024 18:12
We were too conservative in determining our max data size before needing to split, which resulted in many frames being split into multiple FEC blocks unnecessarily.
We also just used a hardcoded split into 3 blocks instead of actually calculating how many blocks are actually required.
@ReenigneArcher
ReenigneArcher enabled auto-merge (squash) July 10, 2024 23:28
@ReenigneArcher
ReenigneArcher merged commit 037c61d into LizardByte:masterJul 11, 2024
KuleRucket pushed a commit to KuleRucket/Sunshine that referenced this pull request Oct 9, 2024
Co-authored-by: Cameron Gutman <aicommander@gmail.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@ns6089@cgutman@ReenigneArcher
, '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

Implement basic network flow control - #2803

Merged
ReenigneArcher merged 3 commits into
LizardByte:masterfrom
ns6089:paced_send
Jul 11, 2024
Merged

Implement basic network flow control#2803
ReenigneArcher merged 3 commits into
LizardByte:masterfrom
ns6089:paced_send

Conversation

@ns6089

@ns6089ns6089 commented Jul 4, 2024

Copy link
Copy Markdown
Contributor

Description

Combat RX/TX buffer overflows and improve multi-FEC on large frames.

Adopted from #1466
Should supersede #2787

Screenshot

Issues Fixed or Closed

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Dependency update (updates to dependencies)
  • Documentation update (changes to documentation)
  • Repository update (changes to repository files, e.g. .github/...)

Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have added or updated the in code docstring/documentation-blocks for new or existing methods/components

Branch Updates

LizardByte requires that branches be up-to-date before merging. This means that after any PR is merged, this branch
must be updated before it can be merged. You must also
Allow edits from maintainers.

  • I want maintainers to keep my branch updated

@ns6089

Copy link
Copy Markdown
ContributorAuthor

Basic implementation wasn't that hard, but it uncovered a few problems.

  1. I will try to implement hybrid sleep/spin wait after all, 0.5ms timer precision should be barely enough.
  2. On large bitrates our Reed-Solomon implementation takes significant amount of time. I will try moving it to separate thread, but in the long run it won't be enough.

@cgutman Have you considered alternative RS implementations that make use of SIMD instructions?
Like this one https://github.com/catid/leopard

@cgutman

Copy link
Copy Markdown
Collaborator

On large bitrates our Reed-Solomon implementation takes significant amount of time. I will try moving it to separate thread, but in the long run it won't be enough.

I don't think this needs to block merging this PR, unless you think these changes are going to make it worse somehow.

@cgutman Have you considered alternative RS implementations that make use of SIMD instructions?

nanors has SIMD optimizations too, but we don't really get much on x86_64 because it only guarantees SSE2. Bumping it to SSSE3 would enable the hand-optimized codepaths that should be much faster. Assuming we're willing to drop support for CPUs without SSSE3, it should just be as simple as adding -mssse3 to

set_source_files_properties("${CMAKE_SOURCE_DIR}/third-party/nanors/rs.c"
DIRECTORY"${CMAKE_SOURCE_DIR}""${TEST_DIR}"
PROPERTIES COMPILE_FLAGS"-include deps/obl/autoshim.h -ftree-vectorize")

If SSSE3 resolves the performance issues you saw at the bitrates we're targeting, that's probably enough. If we want to go further, we can use GCC/Clang function multiversioning to have the compiler build AVX2, SSSE3, and SSE2 variants, but that requires more extensive modifications. We could also switch to totally new library if necessary.

@ns6089

Copy link
Copy Markdown
ContributorAuthor

Yeah, enabling SSSE3 for nanors gives RS encode around 6 times speedup, bringing it to sub millisecond range. Don't need to bother with separate thread then, one less thing to worry about. We should absolutely enabled it.

@cgutman

Copy link
Copy Markdown
Collaborator

Excellent, that's a pretty substantial win.

In terms of hardware support we're dropping with SSSE3, it looks like Intel CPUs prior to Core 2/Atom (~2006), AMD CPUs prior to Bulldozer (~2011), and VIA CPUs prior to Nano (~2008). It looks like all common x64 emulation layers like Rosetta 2 and XTA/Prism support SSSE3, so there should be no issues there either.

The only non-SSSE3 CPUs there that might otherwise be performant enough for some modern games/applications would be AMD K10-based processors (Phenom II). However, those also lack AES-NI, so they're going to get punished by encryption too with ~20x more cycles/byte vs AES-NI.

Overall, I think bumping up the CPU requirement to SSSE3 is probably reasonable. Users with very old CPUs can use an older version of Sunshine.

@ns6089

Copy link
Copy Markdown
ContributorAuthor

@cgutman This generic low latency flow control doesn't seem to be working well, at least on Windows. WSASendMsg() in particular can take more than 5ms even when using extremely low batches (4 packets each), and that's with ethernet level (IEEE 802.3x) flow control disabled at link level. With a lot of calls the combined latency grows. Maybe we can outline all possible congestion scenarios and combat them on a case by case basis? I'm interested in what the aforementioned IEEE 802.3x can't cover. The first thing that comes to mind is streaming over the internet where WAN link is slower than LAN link, but we should be able to detect such cases and maybe apply higher latency throttling with 1ms packet batches.

@ns6089

Copy link
Copy Markdown
ContributorAuthor

The first thing that comes to mind is streaming over the internet where WAN link is slower than LAN link, but we should be able to detect such cases and maybe apply higher latency throttling with 1ms packet batches.

Or try using QoS shaping https://learn.microsoft.com/en-us/windows/win32/api/qos2/ns-qos2-qos_flowrate_outgoing
In theory this exactly what we want in this scenario, if it works of course.

@ns6089

Copy link
Copy Markdown
ContributorAuthor

Oh, turns out my travel wifi router has atrocious ethernet switch and more or less requires 0.1ms batches. I guess this is the kind of devices we have problems with. Will try to optimize for it I guess, even though WSASendMsg() occasionally shoots up to 10ms even on such abysmal batches,

@ns6089

Copy link
Copy Markdown
ContributorAuthor

Oh, turns out my travel wifi router has atrocious ethernet switch and more or less requires 0.1ms batches. I guess this is the kind of devices we have problems with. Will try to optimize for it I guess

Two things were necessary when dealing with this switch

  1. Increasing udp socket send buffer size with SO_SENDBUF
  2. Calling WSASendMsg() with small batches, 10 packets worked best

No sleep or pacing was needed, socket buffer took care of the congestion.
Streams easily at constant 300+Mbps now when before it couldn't even reach 100Mbps.

I guess I can try adding some throttling logic on top of this larger buffer. In theory it should be enough to appease slow clients without resorting to costly spin waits with periodic latency spikes.

@ns6089
ns6089force-pushed the paced_send branch 3 times, most recently from 04dc814 to ea2b9a6CompareJuly 7, 2024 21:40
@ns6089
ns6089 marked this pull request as ready for review July 7, 2024 21:52
@ns6089

Copy link
Copy Markdown
ContributorAuthor

Should be ready. Works really well on Windows from my tests, haven't tested Linux or MacOS.

@cgutman Maybe we can distinguish WAN streaming from LAN streaming based on the packet size? And apply more aggressive throttling in this case, based on requested bitrate. Something like 2 or 3 times the bitrate, will give 1/2 or 1/3 frame time latency.
ea2b9a6#diff-a8b463faa2b4901d7f646c0a3a856d705fd293dc7b99cee500a375dae91ef6bfR1402-R1403

@codecov

codecovBot commented Jul 7, 2024

Copy link
Copy Markdown

Codecov Report

Attention: Patch coverage is 5.81395% with 162 lines in your changes missing coverage. Please review.

Project coverage is 8.99%. Comparing base (6607a28) to head (4fb8438).
Report is 134 commits behind head on master.

Files with missing linesPatch %Lines
src/stream.cpp0.00%77 Missing and 27 partials ⚠️
src/platform/windows/misc.cpp14.58%39 Missing and 2 partials ⚠️
src/platform/linux/misc.cpp0.00%7 Missing ⚠️
src/platform/macos/misc.mm0.00%6 Missing ⚠️
src/platform/windows/display_base.cpp0.00%4 Missing ⚠️
Additional details and impacted files
@@ Coverage Diff @@## master #2803 +/- ##
=======================================
Coverage 8.99% 8.99% =======================================
Files 95 95 Lines 17312 17412 +100 Branches 8236 8272 +36 =======================================
+ Hits 1557 1567 +10 - Misses 12890 13118 +228 + Partials 2865 2727 -138 
FlagCoverage Δ
Linux6.76% <0.00%> (-0.05%)⬇️
Windows4.20% <5.69%> (+0.04%)⬆️
macOS-1210.03% <0.92%> (-0.07%)⬇️
macOS-139.94% <0.92%> (-0.07%)⬇️
macOS-1410.24% <0.92%> (-0.07%)⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing linesCoverage Δ
src/platform/common.h36.90% <100.00%> (+1.53%)⬆️
src/platform/windows/display.h7.24% <ø> (+0.10%)⬆️
src/utility.h28.50% <100.00%> (ø)
src/platform/windows/display_base.cpp12.95% <0.00%> (+0.45%)⬆️
src/platform/macos/misc.mm6.85% <0.00%> (-0.17%)⬇️
src/platform/linux/misc.cpp9.04% <0.00%> (-0.16%)⬇️
src/platform/windows/misc.cpp2.23% <14.58%> (+0.74%)⬆️
src/stream.cpp0.96% <0.00%> (+0.05%)⬆️

... and 20 files with indirect coverage changes

@ns6089

Copy link
Copy Markdown
ContributorAuthor

Fixed the typo in linux/macos code, builds shouldn't fail now.

@ReenigneArcherReenigneArcher mentioned this pull request Jul 8, 2024
11 tasks
@ns6089

Copy link
Copy Markdown
ContributorAuthor

I also have the follow-up refactoring to periodic loggers that remove most of the syntactic bloat from them, improving the readability.
https://github.com/ns6089/Sunshine/commit/60e2c2f98e405e6912bcf009ad4e7fe3c6a2b836#diff-a8b463faa2b4901d7f646c0a3a856d705fd293dc7b99cee500a375dae91ef6bf
I can add it to this PR, if anyone prefers.

@cgutmancgutman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Pacing behavior seems great in my testing on Windows and Linux. I'm seeing the expected behavior of densely packed FEC blocks without the nasty packet loss I had in my previous attempt.

Once these last few issues are resolved, this looks good to merge.

Comment threadcmake/targets/common.cmake Outdated
Comment threadsrc/stream.cpp Outdated
Comment threadsrc/stream.cpp Outdated
@ns6089ns6089 changed the title Try to implement basic network flow controlImplement basic network flow controlJul 10, 2024
cgutmanand others added 3 commits July 10, 2024 18:12
We were too conservative in determining our max data size before needing to split, which resulted in many frames being split into multiple FEC blocks unnecessarily.
We also just used a hardcoded split into 3 blocks instead of actually calculating how many blocks are actually required.
@ReenigneArcher
ReenigneArcher enabled auto-merge (squash) July 10, 2024 23:28
@ReenigneArcher
ReenigneArcher merged commit 037c61d into LizardByte:masterJul 11, 2024
KuleRucket pushed a commit to KuleRucket/Sunshine that referenced this pull request Oct 9, 2024
Co-authored-by: Cameron Gutman <aicommander@gmail.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@ns6089@cgutman@ReenigneArcher
, '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

Implement basic network flow control - #2803

Merged
ReenigneArcher merged 3 commits into
LizardByte:masterfrom
ns6089:paced_send
Jul 11, 2024
Merged

Implement basic network flow control#2803
ReenigneArcher merged 3 commits into
LizardByte:masterfrom
ns6089:paced_send

Conversation

@ns6089

@ns6089ns6089 commented Jul 4, 2024

Copy link
Copy Markdown
Contributor

Description

Combat RX/TX buffer overflows and improve multi-FEC on large frames.

Adopted from #1466
Should supersede #2787

Screenshot

Issues Fixed or Closed

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Dependency update (updates to dependencies)
  • Documentation update (changes to documentation)
  • Repository update (changes to repository files, e.g. .github/...)

Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have added or updated the in code docstring/documentation-blocks for new or existing methods/components

Branch Updates

LizardByte requires that branches be up-to-date before merging. This means that after any PR is merged, this branch
must be updated before it can be merged. You must also
Allow edits from maintainers.

  • I want maintainers to keep my branch updated

@ns6089

Copy link
Copy Markdown
ContributorAuthor

Basic implementation wasn't that hard, but it uncovered a few problems.

  1. I will try to implement hybrid sleep/spin wait after all, 0.5ms timer precision should be barely enough.
  2. On large bitrates our Reed-Solomon implementation takes significant amount of time. I will try moving it to separate thread, but in the long run it won't be enough.

@cgutman Have you considered alternative RS implementations that make use of SIMD instructions?
Like this one https://github.com/catid/leopard

@cgutman

Copy link
Copy Markdown
Collaborator

On large bitrates our Reed-Solomon implementation takes significant amount of time. I will try moving it to separate thread, but in the long run it won't be enough.

I don't think this needs to block merging this PR, unless you think these changes are going to make it worse somehow.

@cgutman Have you considered alternative RS implementations that make use of SIMD instructions?

nanors has SIMD optimizations too, but we don't really get much on x86_64 because it only guarantees SSE2. Bumping it to SSSE3 would enable the hand-optimized codepaths that should be much faster. Assuming we're willing to drop support for CPUs without SSSE3, it should just be as simple as adding -mssse3 to

set_source_files_properties("${CMAKE_SOURCE_DIR}/third-party/nanors/rs.c"
DIRECTORY"${CMAKE_SOURCE_DIR}""${TEST_DIR}"
PROPERTIES COMPILE_FLAGS"-include deps/obl/autoshim.h -ftree-vectorize")

If SSSE3 resolves the performance issues you saw at the bitrates we're targeting, that's probably enough. If we want to go further, we can use GCC/Clang function multiversioning to have the compiler build AVX2, SSSE3, and SSE2 variants, but that requires more extensive modifications. We could also switch to totally new library if necessary.

@ns6089

Copy link
Copy Markdown
ContributorAuthor

Yeah, enabling SSSE3 for nanors gives RS encode around 6 times speedup, bringing it to sub millisecond range. Don't need to bother with separate thread then, one less thing to worry about. We should absolutely enabled it.

@cgutman

Copy link
Copy Markdown
Collaborator

Excellent, that's a pretty substantial win.

In terms of hardware support we're dropping with SSSE3, it looks like Intel CPUs prior to Core 2/Atom (~2006), AMD CPUs prior to Bulldozer (~2011), and VIA CPUs prior to Nano (~2008). It looks like all common x64 emulation layers like Rosetta 2 and XTA/Prism support SSSE3, so there should be no issues there either.

The only non-SSSE3 CPUs there that might otherwise be performant enough for some modern games/applications would be AMD K10-based processors (Phenom II). However, those also lack AES-NI, so they're going to get punished by encryption too with ~20x more cycles/byte vs AES-NI.

Overall, I think bumping up the CPU requirement to SSSE3 is probably reasonable. Users with very old CPUs can use an older version of Sunshine.

@ns6089

Copy link
Copy Markdown
ContributorAuthor

@cgutman This generic low latency flow control doesn't seem to be working well, at least on Windows. WSASendMsg() in particular can take more than 5ms even when using extremely low batches (4 packets each), and that's with ethernet level (IEEE 802.3x) flow control disabled at link level. With a lot of calls the combined latency grows. Maybe we can outline all possible congestion scenarios and combat them on a case by case basis? I'm interested in what the aforementioned IEEE 802.3x can't cover. The first thing that comes to mind is streaming over the internet where WAN link is slower than LAN link, but we should be able to detect such cases and maybe apply higher latency throttling with 1ms packet batches.

@ns6089

Copy link
Copy Markdown
ContributorAuthor

The first thing that comes to mind is streaming over the internet where WAN link is slower than LAN link, but we should be able to detect such cases and maybe apply higher latency throttling with 1ms packet batches.

Or try using QoS shaping https://learn.microsoft.com/en-us/windows/win32/api/qos2/ns-qos2-qos_flowrate_outgoing
In theory this exactly what we want in this scenario, if it works of course.

@ns6089

Copy link
Copy Markdown
ContributorAuthor

Oh, turns out my travel wifi router has atrocious ethernet switch and more or less requires 0.1ms batches. I guess this is the kind of devices we have problems with. Will try to optimize for it I guess, even though WSASendMsg() occasionally shoots up to 10ms even on such abysmal batches,

@ns6089

Copy link
Copy Markdown
ContributorAuthor

Oh, turns out my travel wifi router has atrocious ethernet switch and more or less requires 0.1ms batches. I guess this is the kind of devices we have problems with. Will try to optimize for it I guess

Two things were necessary when dealing with this switch

  1. Increasing udp socket send buffer size with SO_SENDBUF
  2. Calling WSASendMsg() with small batches, 10 packets worked best

No sleep or pacing was needed, socket buffer took care of the congestion.
Streams easily at constant 300+Mbps now when before it couldn't even reach 100Mbps.

I guess I can try adding some throttling logic on top of this larger buffer. In theory it should be enough to appease slow clients without resorting to costly spin waits with periodic latency spikes.

@ns6089
ns6089force-pushed the paced_send branch 3 times, most recently from 04dc814 to ea2b9a6CompareJuly 7, 2024 21:40
@ns6089
ns6089 marked this pull request as ready for review July 7, 2024 21:52
@ns6089

Copy link
Copy Markdown
ContributorAuthor

Should be ready. Works really well on Windows from my tests, haven't tested Linux or MacOS.

@cgutman Maybe we can distinguish WAN streaming from LAN streaming based on the packet size? And apply more aggressive throttling in this case, based on requested bitrate. Something like 2 or 3 times the bitrate, will give 1/2 or 1/3 frame time latency.
ea2b9a6#diff-a8b463faa2b4901d7f646c0a3a856d705fd293dc7b99cee500a375dae91ef6bfR1402-R1403

@codecov

codecovBot commented Jul 7, 2024

Copy link
Copy Markdown

Codecov Report

Attention: Patch coverage is 5.81395% with 162 lines in your changes missing coverage. Please review.

Project coverage is 8.99%. Comparing base (6607a28) to head (4fb8438).
Report is 134 commits behind head on master.

Files with missing linesPatch %Lines
src/stream.cpp0.00%77 Missing and 27 partials ⚠️
src/platform/windows/misc.cpp14.58%39 Missing and 2 partials ⚠️
src/platform/linux/misc.cpp0.00%7 Missing ⚠️
src/platform/macos/misc.mm0.00%6 Missing ⚠️
src/platform/windows/display_base.cpp0.00%4 Missing ⚠️
Additional details and impacted files
@@ Coverage Diff @@## master #2803 +/- ##
=======================================
Coverage 8.99% 8.99% =======================================
Files 95 95 Lines 17312 17412 +100 Branches 8236 8272 +36 =======================================
+ Hits 1557 1567 +10 - Misses 12890 13118 +228 + Partials 2865 2727 -138 
FlagCoverage Δ
Linux6.76% <0.00%> (-0.05%)⬇️
Windows4.20% <5.69%> (+0.04%)⬆️
macOS-1210.03% <0.92%> (-0.07%)⬇️
macOS-139.94% <0.92%> (-0.07%)⬇️
macOS-1410.24% <0.92%> (-0.07%)⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing linesCoverage Δ
src/platform/common.h36.90% <100.00%> (+1.53%)⬆️
src/platform/windows/display.h7.24% <ø> (+0.10%)⬆️
src/utility.h28.50% <100.00%> (ø)
src/platform/windows/display_base.cpp12.95% <0.00%> (+0.45%)⬆️
src/platform/macos/misc.mm6.85% <0.00%> (-0.17%)⬇️
src/platform/linux/misc.cpp9.04% <0.00%> (-0.16%)⬇️
src/platform/windows/misc.cpp2.23% <14.58%> (+0.74%)⬆️
src/stream.cpp0.96% <0.00%> (+0.05%)⬆️

... and 20 files with indirect coverage changes

@ns6089

Copy link
Copy Markdown
ContributorAuthor

Fixed the typo in linux/macos code, builds shouldn't fail now.

@ReenigneArcherReenigneArcher mentioned this pull request Jul 8, 2024
11 tasks
@ns6089

Copy link
Copy Markdown
ContributorAuthor

I also have the follow-up refactoring to periodic loggers that remove most of the syntactic bloat from them, improving the readability.
https://github.com/ns6089/Sunshine/commit/60e2c2f98e405e6912bcf009ad4e7fe3c6a2b836#diff-a8b463faa2b4901d7f646c0a3a856d705fd293dc7b99cee500a375dae91ef6bf
I can add it to this PR, if anyone prefers.

@cgutmancgutman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Pacing behavior seems great in my testing on Windows and Linux. I'm seeing the expected behavior of densely packed FEC blocks without the nasty packet loss I had in my previous attempt.

Once these last few issues are resolved, this looks good to merge.

Comment threadcmake/targets/common.cmake Outdated
Comment threadsrc/stream.cpp Outdated
Comment threadsrc/stream.cpp Outdated
@ns6089ns6089 changed the title Try to implement basic network flow controlImplement basic network flow controlJul 10, 2024
cgutmanand others added 3 commits July 10, 2024 18:12
We were too conservative in determining our max data size before needing to split, which resulted in many frames being split into multiple FEC blocks unnecessarily.
We also just used a hardcoded split into 3 blocks instead of actually calculating how many blocks are actually required.
@ReenigneArcher
ReenigneArcher enabled auto-merge (squash) July 10, 2024 23:28
@ReenigneArcher
ReenigneArcher merged commit 037c61d into LizardByte:masterJul 11, 2024
KuleRucket pushed a commit to KuleRucket/Sunshine that referenced this pull request Oct 9, 2024
Co-authored-by: Cameron Gutman <aicommander@gmail.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@ns6089@cgutman@ReenigneArcher