Apache SSHD LocalWindow.release() Performance Issues
- Dominant language
- Java
- Stars
- 1.1k
- Forks
- 400
- Avg merge
- 5d 1h
- Merged PRs (30d)
- 1
Description
### Version
2.15.0
### Bug description
Problem Summary
LocalWindow.release() becomes a significant performance bottleneck during SFTP uploads, being called hundreds of times per second with excessive overhead. This causes SFTP upload speeds to be significantly slower than in version 2.13.2.
### Actual behavior
1.Too aggressive window adjustment threshold
Location: Line 110
if (released > packetSize / 2 || released > maxFree / 10 || released > 16 * 1024)
Problem: The 16KB threshold is too low for modern high-throughput connections. This causes window adjust messages to be sent very frequently, adding network and processing overhead.
Impact: With 64KB packets, this sends window adjusts for every ~2-3 packets, generating excessive SSH_MSG_CHANNEL_WINDOW_ADJUST messages.
2.Complex shouldAdjust logic causes unnecessary adjustments
Location: Line 114
if (size < maxFree / 2 || maxFree - size > 3 * packetSize)
Problem: The condition maxFree - size > 3 * packetSize causes window adjustments even when the window is not actually low. This is overly aggressive and sends adjustments "just because space is available" rather than because the sender needs it.
Impact: Generates unnecessary network messages and processing overhead.
3.Redundant AtomicLong inside synchronized block
Location: Line 42, 118
private final AtomicLong adjustment = new AtomicLong();// Later in release():long adjustSize = adjustment.addAndGet(newSize - size); // Inside synchronized(lock)
Problem: Using AtomicLong operations inside a synchronized(lock) block is redundant. The lock already provides thread safety, so the atomic operations add unnecessary overhead for every window adjustment.
Impact: Every window adjust performs expensive atomic compare-and-swap operations when a simple long addition would suffice
4.No early exit optimization
Problem: The method always enters the synchronized block and performs calculations even when below the threshold and no adjustment will be sent.
Impact: Adds synchronization overhead for every small chunk release, even when no action is needed
### Expected behavior
1.Minimal per-call overhead: LocalWindow.release() should have minimal CPU overhead since it's called very frequently during data transfer (hundreds of times per second in proxy scenarios).
2.Efficient window management: Window adjust messages (SSH_MSG_CHANNEL_WINDOW_ADJUST) should only be sent when the window is actually getting low and the sender needs more space, not just because space is available.
3.Appropriate threshold for high-throughput: The threshold for triggering window adjustments should scale with packet size to avoid excessive messages in high-throughput scenarios (e.g., 128KB instead of 16KB).
4.No redundant synchronization: Should not use atomic operations inside synchronized blocks where the lock already provides thread safety.
5.Performance comparable to 2.13.2: SFTP transfer speeds should not regress significantly from previous versions. In our testing, 2.15.0 was notably slower than 2.13.2 for the same workload.
6.Efficient for proxy architectures: Should perform well when data is being forwarded between channels (proxy/gateway scenarios) where release() is called very frequently on multiple LocalWindow instances simultaneously.
### Relevant log output
```Shell
```
### Other information
_No response_
Contributor guide
No contributing guide indexed for this repository
Research direction
Start by locating LocalWindow.release() and reviewing the logic around the cited lines, then compare it with the 2.13.2 implementation and reproduce the SFTP upload performance regression. Evaluate the threshold, adjustment condition, synchronization, and AtomicLong concerns against the expected window-management behavior; done means fewer unnecessary window-adjust messages and transfer performance comparable to 2.13.2.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- networking, performance
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100