Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use faster timers #1908

Merged
merged 16 commits into from Feb 5, 2023
Merged

use faster timers #1908

merged 16 commits into from Feb 5, 2023

Conversation

ronag
Copy link
Member

@ronag ronag commented Feb 4, 2023

Another major bottleneck I found is the constant refreshing of timers, in particular the body timeout timer which is refresh every time we get a packet.

Our current use of timers is that we have a very few timers which we update frequently where high accuracy is not required. This PR tries to implement that.

@ronag
Copy link
Member Author

ronag commented Feb 4, 2023

@mcollina This breaks all the tests using fake timers... thoughts on what to do about that?

@ronag ronag force-pushed the timeout123 branch 2 times, most recently from e0ffe52 to f406dc6 Compare February 4, 2023 11:06
@mcollina
Copy link
Member

mcollina commented Feb 4, 2023

What benefits is this giving us?

I would prefer this timer to be attached to the agent, so we can actually stop them. If this is significantly faster, why aren't we briging that optimization to Node.js itself?

@ronag
Copy link
Member Author

ronag commented Feb 4, 2023

What benefits is this giving us?

In high throughput scenarios with lots of small packets we are constantly calling refresh on node timers which is much more expensive than what this PR does.

I would prefer this timer to be attached to the agent, so we can actually stop them. If this is significantly faster, why aren't we briging that optimization to Node.js itself?

I don't follow... Node has a more generic timer implementation which works for other less nisch use cases.

@ronag
Copy link
Member Author

ronag commented Feb 4, 2023

@mcollina PTAL

@ronag ronag force-pushed the timeout123 branch 8 times, most recently from a1574b0 to b1bd910 Compare February 4, 2023 12:24
@ronag
Copy link
Member Author

ronag commented Feb 4, 2023

Note that the timers in this PR are much less accurate than Node core timers, which I believe is fine for our use case.

@mcollina
Copy link
Member

mcollina commented Feb 4, 2023

Have you got a benchmark before/after?

@ronag
Copy link
Member Author

ronag commented Feb 4, 2023

Before:

[bench:run] │ undici - stream │ 1 │ 7383.29 req/sec │ ± 0.00 % │ + 395.85 % │

After:

[bench:run] │ undici - stream │ 1 │ 7683.40 req/sec │ ± 0.00 % │ + 358.60 % │

I'm a little sceptical about our benchmark accuracy...

@ronag ronag force-pushed the timeout123 branch 3 times, most recently from 8fafaa1 to 7b93202 Compare February 4, 2023 12:50
@ronag
Copy link
Member Author

ronag commented Feb 5, 2023

I haven't looked into connectionsCheckingInterval so much. But would an alternative be the other way around? Go from a c++ version to an inaccurate but fast js version?

@ShogunPanda
Copy link
Contributor

Well, I guess you could try and measure the impact.

For you to consider: connectionsCheckingInterval is a mechanism that every x seconds check the entire pool of opened inbound connections comparing (in the same "inaccurate" way you did here) if the timeout as gone off.
He's written in C++ (leveraging C sorted sets and thus able to easily bail out early in the loop) but I think it can be easily adapted in JS.

The only pain is to maintain the list of opened/active connections (especially when we think about KeepAlive)

@ronag
Copy link
Member Author

ronag commented Feb 5, 2023

I see. I wouldn't mind using that per se. I don't know how that would practically work in undici which is developed outside of core.

@ronag ronag force-pushed the timeout123 branch 3 times, most recently from 9111ed7 to 2750939 Compare February 5, 2023 12:53
@ronag
Copy link
Member Author

ronag commented Feb 5, 2023

CI looks ok 👍

lib/timers.js Show resolved Hide resolved
lib/timers.js Outdated Show resolved Hide resolved
lib/timers.js Show resolved Hide resolved
Copy link
Member

@mcollina mcollina left a comment

Choose a reason for hiding this comment

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

lgtm

@mcollina
Copy link
Member

mcollina commented Feb 5, 2023

CI is still very red :(

@ronag
Copy link
Member Author

ronag commented Feb 5, 2023

I will fix that

@ronag
Copy link
Member Author

ronag commented Feb 5, 2023

Seems ok now. Same as usual with windows on node 19.

@ronag ronag merged commit b06f19f into main Feb 5, 2023
@anonrig anonrig deleted the timeout123 branch February 5, 2023 19:57
@KhafraDev
Copy link
Member

v12 CI failed on this test

     # Subtest: keep-alive threshold
        1..2
        ok 1 - should not error
        not ok 2 - (unnamed test)
          ---
          at:
            line: 217
            column: 13
            file: test/client-keep-alive.js
            type: Timeout
            method: _onTimeout
          stack: |
            Timeout._onTimeout (test/client-keep-alive.js:217:13)
          source: |2
                    const timeout = setTimeout(() => {
                      t.fail()
            ------------^
                    }, 2e3)
                    client.on('disconnect', () => {
          ...
        
        # failed 1 of 2 tests
    not ok 6 - keep-alive threshold # time=2017.2ms

anonrig pushed a commit to anonrig/undici that referenced this pull request Apr 4, 2023
* refactor: refreshTimeout

* perf: fast timers

* fixup

* Revert "fixup"

This reverts commit 2fc8eaa7195c931481d902a3f2583f38317td0be8.

* fixup

* fixup

* fixup

* fixup

* fixup

* fixup

* fixup

* fixup

* fixup

* Update lib/timers.js

* Update lib/timers.js

* Update lib/timers.js
metcoder95 pushed a commit to metcoder95/undici that referenced this pull request Jul 21, 2023
* refactor: refreshTimeout

* perf: fast timers

* fixup

* Revert "fixup"

This reverts commit 2fc8eaa7195c931481d902a3f2583f38317td0be8.

* fixup

* fixup

* fixup

* fixup

* fixup

* fixup

* fixup

* fixup

* fixup

* Update lib/timers.js

* Update lib/timers.js

* Update lib/timers.js
kodiakhq bot pushed a commit to X-oss-byte/Canary-nextjs that referenced this pull request Sep 18, 2023
[![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [undici](https://undici.nodejs.org) ([source](https://togithub.com/nodejs/undici)) | [`5.14.0` -> `5.19.1`](https://renovatebot.com/diffs/npm/undici/5.14.0/5.19.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/undici/5.19.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/undici/5.19.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/undici/5.14.0/5.19.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/undici/5.14.0/5.19.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

### GitHub Vulnerability Alerts

#### [CVE-2023-23936](https://togithub.com/nodejs/undici/security/advisories/GHSA-5r9g-qh6m-jxff)

### Impact

undici library does not protect `host` HTTP header from CRLF injection vulnerabilities.

### Patches

This issue was patched in Undici v5.19.1.

### Workarounds

Sanitize the `headers.host` string before passing to undici.

### References

Reported at https://hackerone.com/reports/1820955.

### Credits

Thank you to Zhipeng Zhang ([@​timon8](https://hackerone.com/timon8)) for reporting this vulnerability.

---

### Release Notes

<details>
<summary>nodejs/undici (undici)</summary>

### [`v5.19.1`](https://togithub.com/nodejs/undici/releases/tag/v5.19.1)

[Compare Source](https://togithub.com/nodejs/undici/compare/v5.19.0...v5.19.1)

#### ⚠️ Security Release ⚠️

-   [Regular Expression Denial of Service in Headers](https://togithub.com/nodejs/undici/security/advisories/GHSA-r6ch-mqf9-qc9w) with CVE-2023-24807
-   [CRLF Injection in Nodejs ‘undici’ via host](https://togithub.com/nodejs/undici/security/advisories/GHSA-5r9g-qh6m-jxff) with CVE-2023-23936

This release is part of the Node.js security release train: https://nodejs.org/en/blog/vulnerability/february-2023-security-releases/

### [`v5.19.0`](https://togithub.com/nodejs/undici/releases/tag/v5.19.0)

[Compare Source](https://togithub.com/nodejs/undici/compare/v5.18.0...v5.19.0)

#### What's Changed

-   fix(fetch): raise AbortSignal max event listeners by [@&#8203;KhafraDev](https://togithub.com/KhafraDev) in [nodejs/undici#1910
-   fix: content-disposition header parsing by [@&#8203;climba03003](https://togithub.com/climba03003) in [nodejs/undici#1911
-   fix: remove test by [@&#8203;KhafraDev](https://togithub.com/KhafraDev) in [nodejs/undici#1916
-   feat: add Headers.prototype.getSetCookie by [@&#8203;KhafraDev](https://togithub.com/KhafraDev) in [nodejs/undici#1915
-   fix(headers): clone getSetCookie list & add getSetCookie type by [@&#8203;KhafraDev](https://togithub.com/KhafraDev) in [nodejs/undici#1917
-   doc(mock): update out-of-date reply documentation by [@&#8203;p9f](https://togithub.com/p9f) in [nodejs/undici#1913
-   fix(types): add missing keepAlive params by [@&#8203;SkeLLLa](https://togithub.com/SkeLLLa) in [nodejs/undici#1918
-   Make the fetch() abort test pass locally, on Linux and Mac, Node 18/19. by [@&#8203;mcollina](https://togithub.com/mcollina) in [nodejs/undici#1927

#### New Contributors

-   [@&#8203;climba03003](https://togithub.com/climba03003) made their first contribution in [nodejs/undici#1911
-   [@&#8203;p9f](https://togithub.com/p9f) made their first contribution in [nodejs/undici#1913

**Full Changelog**: nodejs/undici@v5.18.0...v5.19.0

### [`v5.18.0`](https://togithub.com/nodejs/undici/releases/tag/v5.18.0)

[Compare Source](https://togithub.com/nodejs/undici/compare/v5.17.1...v5.18.0)

##### What's Changed

-   Add ability to set TCP keepalive by [@&#8203;xconverge](https://togithub.com/xconverge) in [nodejs/undici#1904
-   use faster timers by [@&#8203;ronag](https://togithub.com/ronag) in [nodejs/undici#1908
-   fix: ensure header value is a string by [@&#8203;ronag](https://togithub.com/ronag) in [nodejs/undici#1899

**Full Changelog**: nodejs/undici@v5.17.1...v5.18.0

### [`v5.17.1`](https://togithub.com/nodejs/undici/releases/tag/v5.17.1)

[Compare Source](https://togithub.com/nodejs/undici/compare/v5.17.0...v5.17.1)

#### What's Changed

-   fix: bad buffer slice (nodejs/undici@d2be675)

**Full Changelog**: nodejs/undici@v5.17.0...v5.17.1

### [`v5.17.0`](https://togithub.com/nodejs/undici/releases/tag/v5.17.0)

[Compare Source](https://togithub.com/nodejs/undici/compare/v5.16.0...v5.17.0)

#### What's Changed

-   fix(wpts): Blob is a global getter in >=v19.x.x by [@&#8203;KhafraDev](https://togithub.com/KhafraDev) in [nodejs/undici#1880
-   doc: fix anchor links dispatcher.stream by [@&#8203;RafaelGSS](https://togithub.com/RafaelGSS) in [nodejs/undici#1881
-   wpt: make runner more resilient by [@&#8203;KhafraDev](https://togithub.com/KhafraDev) in [nodejs/undici#1884
-   Make test pass in v19.x by [@&#8203;mcollina](https://togithub.com/mcollina) in [nodejs/undici#1879
-   Correct the type of DispatchOptions\["headers"] by [@&#8203;pan93412](https://togithub.com/pan93412) in [nodejs/undici#1896
-   perf(content-type parser): faster string collector by [@&#8203;KhafraDev](https://togithub.com/KhafraDev) in [nodejs/undici#1894
-   feat: expose content-type parser by [@&#8203;KhafraDev](https://togithub.com/KhafraDev) in [nodejs/undici#1895
-   fix(types): Update DispatchOptions type for missing "blocking" by [@&#8203;xconverge](https://togithub.com/xconverge) in [nodejs/undici#1889
-   fix(types): update error type definitions by [@&#8203;rafaelcr](https://togithub.com/rafaelcr) in [nodejs/undici#1888
-   fix: ensure connection header is a string by [@&#8203;ronag](https://togithub.com/ronag) in [nodejs/undici#1900
-   fix: throw if invalid content-type header by [@&#8203;ronag](https://togithub.com/ronag) in [nodejs/undici#1901
-   fix(fetch): use semicolon for Cookie header delimiter by [@&#8203;KhafraDev](https://togithub.com/KhafraDev) in [nodejs/undici#1906
-   Use FastBuffer by [@&#8203;ronag](https://togithub.com/ronag) in [nodejs/undici#1907

#### New Contributors

-   [@&#8203;pan93412](https://togithub.com/pan93412) made their first contribution in [nodejs/undici#1896
-   [@&#8203;rafaelcr](https://togithub.com/rafaelcr) made their first contribution in [nodejs/undici#1888

**Full Changelog**: nodejs/undici@v5.16.0...v5.17.0

### [`v5.16.0`](https://togithub.com/nodejs/undici/releases/tag/v5.16.0)

[Compare Source](https://togithub.com/nodejs/undici/compare/v5.15.2...v5.16.0)

#### What's Changed

-   Add feature to specify custom headers for proxies by [@&#8203;Sebmaster](https://togithub.com/Sebmaster) in [nodejs/undici#1877

#### New Contributors

-   [@&#8203;Sebmaster](https://togithub.com/Sebmaster) made their first contribution in [nodejs/undici#1877

**Full Changelog**: nodejs/undici@v5.15.2...v5.16.0

### [`v5.15.2`](https://togithub.com/nodejs/undici/compare/9d5f23177408dc16d3d4cbb8cebf463081c54e16...9457c9719029945ef9ff36b71d58557443730942)

[Compare Source](https://togithub.com/nodejs/undici/compare/v5.15.1...v5.15.2)

### [`v5.15.1`](https://togithub.com/nodejs/undici/releases/tag/v5.15.1)

[Compare Source](https://togithub.com/nodejs/undici/compare/v5.15.0...v5.15.1)

#### What's Changed

-   fix(websocket): simplify typedarray copying by [@&#8203;KhafraDev](https://togithub.com/KhafraDev) in [nodejs/undici#1854
-   fix: wpts on node v18.13.0+ by [@&#8203;KhafraDev](https://togithub.com/KhafraDev) in [nodejs/undici#1859
-   perf: allow keep alive for HEAD requests by [@&#8203;ronag](https://togithub.com/ronag) in [nodejs/undici#1858
-   fix: flaky abort test by [@&#8203;KhafraDev](https://togithub.com/KhafraDev) in [nodejs/undici#1863

**Full Changelog**: nodejs/undici@v5.15.0...v5.15.1

### [`v5.15.0`](https://togithub.com/nodejs/undici/releases/tag/v5.15.0)

[Compare Source](https://togithub.com/nodejs/undici/compare/v5.14.0...v5.15.0)

#### What's Changed

-   \[types] update ProxyAgent Options (timeout) by [@&#8203;sosoba](https://togithub.com/sosoba) in [nodejs/undici#1801
-   feat: implement websockets by [@&#8203;KhafraDev](https://togithub.com/KhafraDev) in [nodejs/undici#1795
-   feat(websocket): handle ping/pong frames & fix fragmented frames by [@&#8203;KhafraDev](https://togithub.com/KhafraDev) in [nodejs/undici#1809
-   docs: add basic fetch & company docs by [@&#8203;KhafraDev](https://togithub.com/KhafraDev) in [nodejs/undici#1810
-   make formdata body immutable and encode it only once by [@&#8203;jimmywarting](https://togithub.com/jimmywarting) in [nodejs/undici#1814
-   test: add regression test for [#&#8203;1814](https://togithub.com/nodejs/undici/issues/1814) by [@&#8203;KhafraDev](https://togithub.com/KhafraDev) in [nodejs/undici#1815
-   feat(websocket): only consume necessary bytes by [@&#8203;KhafraDev](https://togithub.com/KhafraDev) in [nodejs/undici#1812
-   websocket: use Buffer.allocUnsafe by [@&#8203;KhafraDev](https://togithub.com/KhafraDev) in [nodejs/undici#1817
-   build(deps-dev): bump [@&#8203;sinonjs/fake-timers](https://togithub.com/sinonjs/fake-timers) from 9.1.2 to 10.0.2 by [@&#8203;dependabot](https://togithub.com/dependabot) in [nodejs/undici#1819
-   fix(websocket): deprecation warning & 64-bit unsigned int body length by [@&#8203;KhafraDev](https://togithub.com/KhafraDev) in [nodejs/undici#1818
-   Use nodejs.stream.destroyed symbol by [@&#8203;ronag](https://togithub.com/ronag) in [nodejs/undici#1816
-   fetch: removal of redundant condition by [@&#8203;debadree25](https://togithub.com/debadree25) in [nodejs/undici#1821
-   fix(request): request headers array by [@&#8203;jd-carroll](https://togithub.com/jd-carroll) in [nodejs/undici#1807
-   fix(websocket): validate payload length received by [@&#8203;KhafraDev](https://togithub.com/KhafraDev) in [nodejs/undici#1822
-   fix(websocket): run parser in loop, instead of recursively by [@&#8203;KhafraDev](https://togithub.com/KhafraDev) in [nodejs/undici#1828
-   fix(fetch): weaker refs by [@&#8203;ronag](https://togithub.com/ronag) in [nodejs/undici#1824
-   websocket: add tests for opening handshake by [@&#8203;KhafraDev](https://togithub.com/KhafraDev) in [nodejs/undici#1831
-   websocket: add tests for constructor, close, and send by [@&#8203;KhafraDev](https://togithub.com/KhafraDev) in [nodejs/undici#1832
-   websocket: more test coverage by [@&#8203;KhafraDev](https://togithub.com/KhafraDev) in [nodejs/undici#1833
-   fix(WPTs): flaky abort test by [@&#8203;KhafraDev](https://togithub.com/KhafraDev) in [nodejs/undici#1835
-   wpt: add test by [@&#8203;KhafraDev](https://togithub.com/KhafraDev) in [nodejs/undici#1836
-   fix: don't send keep-alive if we want reset by [@&#8203;ronag](https://togithub.com/ronag) in [nodejs/undici#1846
-   fetch: update body consume to match spec by [@&#8203;KhafraDev](https://togithub.com/KhafraDev) in [nodejs/undici#1847
-   feat: allow connection header in request by [@&#8203;metcoder95](https://togithub.com/metcoder95) in [nodejs/undici#1829
-   feat: add cookie parsing ability by [@&#8203;KhafraDev](https://togithub.com/KhafraDev) in [nodejs/undici#1848
-   fix(cookie): add docs & expose in node v16 by [@&#8203;KhafraDev](https://togithub.com/KhafraDev) in [nodejs/undici#1849
-   fix(cookies): work with global Headers by [@&#8203;KhafraDev](https://togithub.com/KhafraDev) in [nodejs/undici#1850
-   docs(Dispatcher): adjust documentation for reset flag by [@&#8203;metcoder95](https://togithub.com/metcoder95) in [nodejs/undici#1852
-   Fix broken interceptor test by [@&#8203;mcollina](https://togithub.com/mcollina) in [nodejs/undici#1853

#### New Contributors

-   [@&#8203;sosoba](https://togithub.com/sosoba) made their first contribution in [nodejs/undici#1801
-   [@&#8203;debadree25](https://togithub.com/debadree25) made their first contribution in [nodejs/undici#1821
-   [@&#8203;jd-carroll](https://togithub.com/jd-carroll) made their first contribution in [nodejs/undici#1807

**Full Changelog**: nodejs/undici@v5.14.0...v5.15.0

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "" (UTC), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/sammyfilly/Canary-nextjs).
crysmags pushed a commit to crysmags/undici that referenced this pull request Feb 27, 2024
* refactor: refreshTimeout

* perf: fast timers

* fixup

* Revert "fixup"

This reverts commit 2fc8eaa7195c931481d902a3f2583f38317td0be8.

* fixup

* fixup

* fixup

* fixup

* fixup

* fixup

* fixup

* fixup

* fixup

* Update lib/timers.js

* Update lib/timers.js

* Update lib/timers.js
Sign up for free to 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.

None yet

6 participants