Describe the bug
Hi, I recently migrated my application OyasumiVR from bluest to btleplug. Since then, I've had reports of memory usage climbing over time on Windows, which I've also reproduced myself with btleplug 0.13.1.
I want to be upfront that this isn't my area of expertise, so I threw Astra at the problem. It came up with a possible cause and patch. I can personally only speak for the before and after results, not the findings or solution, but I figured I'd report it anyway.
Expected behavior
btleplug should release resources when they're no longer needed, without memory accumulating over repeated use.
Actual behavior
I ran the unpatched 0.13.1 build for about eight hours, then the patched build for two hours, with the same five Bluetooth LE devices connected.
|
Unpatched 0.13.1 |
With the proposed patch |
| Duration |
About 8 hours |
2 hours |
| Private memory at start |
53 MiB |
53 MiB |
| Private memory at end |
1,477 MiB |
56 MiB |
| Memory growth over matching periods |
About 182 MiB/hour |
About 0.37 MiB/hour |
Astra calculated the growth rates from the matching first two hours, excluding the first ten minutes. Memory kept growing throughout the unpatched run. With the patch, it stayed below 57 MiB.
All five devices connected in both runs. Neither run logged connection failures during measurement. I haven't tested the patched build for the full eight hours.
Additional context
Setup
- Windows
- Intel Wireless Bluetooth, driver 24.30.1.1
- btleplug 0.13.1
- Five Bluetooth LE devices
Dump analysis
Astra analyzed memory dumps from both runs using their matching executables and PDBs. It identified the following radio callbacks:
|
Near the start |
At the end |
| Unpatched |
18 |
3,198 |
| Patched |
1 |
1 |
In the unpatched final dump, it traced those callbacks to 3,198 adapter managers and about 73,000 retained device objects. Those are accumulated objects from repeated discovery, not separate physical devices. Their map storage alone accounted for about 1.17 GiB.
According to its analysis, 3,197 of those managers had only one remaining strong reference, held by a radio callback. It also checked a sample of the callback and manager allocations against Windows heap records.
Suspected cause
Astra's explanation is that the Windows Radio::StateChanged handler remains registered after its adapter is dropped. The callback holds references to the radio and device manager, keeping the manager's device data alive.
The dump findings appear to support that explanation, but I haven't independently verified Astra's interpretation.
Proposed patch
This PR contains the patch Astra implemented for 0.13.1. It removes the radio handler when the last adapter clone is dropped and changes the callback to hold a weak reference to the manager.
The scan-handler cleanup already present in 0.13.1 is unchanged.
I can't vouch for the implementation or whether this is the correct fix. I can only confirm that memory consumption was much lower in my test with it applied. I'd appreciate someone familiar with the Windows implementation taking a look.
Describe the bug
Hi, I recently migrated my application OyasumiVR from bluest to btleplug. Since then, I've had reports of memory usage climbing over time on Windows, which I've also reproduced myself with btleplug 0.13.1.
I want to be upfront that this isn't my area of expertise, so I threw Astra at the problem. It came up with a possible cause and patch. I can personally only speak for the before and after results, not the findings or solution, but I figured I'd report it anyway.
Expected behavior
btleplug should release resources when they're no longer needed, without memory accumulating over repeated use.
Actual behavior
I ran the unpatched 0.13.1 build for about eight hours, then the patched build for two hours, with the same five Bluetooth LE devices connected.
Astra calculated the growth rates from the matching first two hours, excluding the first ten minutes. Memory kept growing throughout the unpatched run. With the patch, it stayed below 57 MiB.
All five devices connected in both runs. Neither run logged connection failures during measurement. I haven't tested the patched build for the full eight hours.
Additional context
Setup
Dump analysis
Astra analyzed memory dumps from both runs using their matching executables and PDBs. It identified the following radio callbacks:
In the unpatched final dump, it traced those callbacks to 3,198 adapter managers and about 73,000 retained device objects. Those are accumulated objects from repeated discovery, not separate physical devices. Their map storage alone accounted for about 1.17 GiB.
According to its analysis, 3,197 of those managers had only one remaining strong reference, held by a radio callback. It also checked a sample of the callback and manager allocations against Windows heap records.
Suspected cause
Astra's explanation is that the Windows
Radio::StateChangedhandler remains registered after its adapter is dropped. The callback holds references to the radio and device manager, keeping the manager's device data alive.The dump findings appear to support that explanation, but I haven't independently verified Astra's interpretation.
Proposed patch
This PR contains the patch Astra implemented for 0.13.1. It removes the radio handler when the last adapter clone is dropped and changes the callback to hold a weak reference to the manager.
The scan-handler cleanup already present in 0.13.1 is unchanged.
I can't vouch for the implementation or whether this is the correct fix. I can only confirm that memory consumption was much lower in my test with it applied. I'd appreciate someone familiar with the Windows implementation taking a look.