tediousjs / tedious

Node TDS module for connecting to SQL Server databases.
http://tediousjs.github.io/tedious/
MIT License
1.58k stars 439 forks source link

refactor: move message handling internals to use `async`/`await` #1656

Open arthurschreiber opened 3 months ago

arthurschreiber commented 3 months ago

This introduces some initial refactoring around MessageIO/IncomingMessageStream/OutgoingMessageStream.

Namely, the goal is to completely remove IncomingMessageStream/OutgoingMessageStream/Message and replace them with two straightforward functions instead:

Both these new methods are much simpler compared to the previous IncomingMessageStream/OutgoingMessageStream implementation, both from a logical complexity as well as an implementation complexity point.

They're also both significantly faster than the current implementations. I added benchmarks that try to compare either implementation (benchmarks run using Node.js v18.20.4):

@arthurschreiber ➜ /workspace/benchmarks (arthur/async-await) $ node message-io/incoming-message-stream.js 
message-io/incoming-message-stream.js n=100: 2,913.7299061537133 (minor: 0 - 0ms, major: 0 - 0ms, incremental: 0 - 0ms)
message-io/incoming-message-stream.js n=1000: 11,430.989311430583 (minor: 0 - 0ms, major: 0 - 0ms, incremental: 0 - 0ms)
message-io/incoming-message-stream.js n=10000: 32,195.67874171715 (minor: 0 - 0ms, major: 0 - 0ms, incremental: 0 - 0ms)
message-io/incoming-message-stream.js n=100000: 101,359.99006469377 (minor: 0 - 0ms, major: 0 - 0ms, incremental: 0 - 0ms)
@arthurschreiber ➜ /workspace/benchmarks (arthur/async-await) $ node message-io/read-message.js 
message-io/read-message.js n=100: 15,410.443287565346 (minor: 0 - 0ms, major: 0 - 0ms, incremental: 0 - 0ms)
message-io/read-message.js n=1000: 22,116.38940123348 (minor: 0 - 0ms, major: 0 - 0ms, incremental: 0 - 0ms)
message-io/read-message.js n=10000: 70,465.68105003222 (minor: 0 - 0ms, major: 0 - 0ms, incremental: 0 - 0ms)
message-io/read-message.js n=100000: 206,620.15053389582 (minor: 0 - 0ms, major: 0 - 0ms, incremental: 0 - 0ms)
@arthurschreiber ➜ /workspace/benchmarks (arthur/async-await) $ node message-io/outgoing-message-stream.js 
message-io/outgoing-message-stream.js n=100: 5,938.379808083441 (minor: 0 - 0ms, major: 0 - 0ms, incremental: 0 - 0ms)
message-io/outgoing-message-stream.js n=1000: 9,312.915449158187 (minor: 0 - 0ms, major: 0 - 0ms, incremental: 0 - 0ms)
message-io/outgoing-message-stream.js n=10000: 37,337.954398051086 (minor: 0 - 0ms, major: 0 - 0ms, incremental: 0 - 0ms)
message-io/outgoing-message-stream.js n=100000: 80,630.96081259915 (minor: 0 - 0ms, major: 0 - 0ms, incremental: 0 - 0ms)
@arthurschreiber ➜ /workspace/benchmarks (arthur/async-await) $ node message-io/write-message.js 
message-io/write-message.js n=100: 18,303.00403544633 (minor: 0 - 0ms, major: 0 - 0ms, incremental: 0 - 0ms)
message-io/write-message.js n=1000: 15,285.594130026144 (minor: 0 - 0ms, major: 0 - 0ms, incremental: 0 - 0ms)
message-io/write-message.js n=10000: 67,938.25567509481 (minor: 0 - 0ms, major: 0 - 0ms, incremental: 0 - 0ms)
message-io/write-message.js n=100000: 127,125.10735604081 (minor: 0 - 0ms, major: 0 - 0ms, incremental: 0 - 0ms)

The current implementation spends a lot of time setting up new stream objects for each incoming and outgoing message (via the Message class that inherits from PassThrough transform stream), and that causes quite a dent in performance, especially when v8 optimizations haven't kicked in yet.

codecov[bot] commented 3 months ago

Codecov Report

Attention: Patch coverage is 91.20370% with 19 lines in your changes missing coverage. Please review.

Project coverage is 79.53%. Comparing base (fc2aa28) to head (39cbe28).

Files with missing lines Patch % Lines
src/message-io.ts 90.83% 3 Missing and 9 partials :warning:
src/connection.ts 90.27% 4 Missing and 3 partials :warning:
Additional details and impacted files ```diff @@ Coverage Diff @@ ## master #1656 +/- ## ========================================== + Coverage 78.97% 79.53% +0.56% ========================================== Files 90 90 Lines 4855 5009 +154 Branches 929 947 +18 ========================================== + Hits 3834 3984 +150 + Misses 718 712 -6 - Partials 303 313 +10 ```

:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.

arthurschreiber commented 3 months ago

@MichaelSun90 @mShan0 Mind taking a look? I only moved the PRELOGIN payload and parsing to use the new methods so far. I think this is probably large enough to warrant merging this before moving more things over - I don't think this will be reviewable if we move more things over inside of this PR.