-
Notifications
You must be signed in to change notification settings - Fork 182
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
[MRG] Improve DUL performance #651
Conversation
- Added `nr_ds` to make it easy to configure the number of datasets to use in the benchmark - Print the name of the DICOM file being used for the benchmark Note that `pynetdicom` performance is worse for larger DICOM files, such as `RTImageStorage.dcm`: ``` 9) C-STORE SCU/SCP transferred 100 total RTImageStorage.dcm datasets over 1 association(s) in 20.88 s 10) C-STORE DCMTK SCU/SCP transferred 100 total RTImageStorage.dcm datasets over 1 association(s) in 0.28 s ``` For `RTImageStorage.dcm`, `pynetdicom` is ~75x slower than DCMTK.
Instead of sleeping before every event, only sleep when there are no queued events to process. This ensures that queued events are processed as fast as possible. The `_run_loop_delay` setting now only affects the case where there are no queued events (i.e. the system is idle). After the performance optimization, `pynetdicom` is 23x faster than before when transferring `RTImageStorage.dcm`: New: ``` 1) C-STORE SCU transferred 100 total RTImageStorage.dcm datasets over 1 association(s) in 0.85 s 9) C-STORE SCU/SCP transferred 100 total RTImageStorage.dcm datasets over 1 association(s) in 1.43 s 10) C-STORE DCMTK SCU/SCP transferred 100 total RTImageStorage.dcm datasets over 1 association(s) in 0.29 s ``` Old: ``` 1) C-STORE SCU transferred 100 total RTImageStorage.dcm datasets over 1 association(s) in 19.69 s 9) C-STORE SCU/SCP transferred 100 total RTImageStorage.dcm datasets over 1 association(s) in 20.88 s 10) C-STORE DCMTK SCU/SCP transferred 100 total RTImageStorage.dcm datasets over 1 association(s) in 0.28 s ``` Now `pynetdicom` is only ~5x slower than DCMTK instead of ~75x.
When single-stepping the reactor, sleep between events so that test code has time to run.
- Prompt to use large or small dataset - Prompt for number of datasets to use (with default) - Run multiple benchmarks in a single run
- Display write option in output of `receive_store()` - Support running all tests, ranges of tests, or lists of tests
- Copy working `sleep()` timing pattern from `TestUPSFindServiceClass::test_scp_cancelled()` to 3 instances of `test_scp_cancelled()` in `test_service_qr.py`
Codecov Report
@@ Coverage Diff @@
## master #651 +/- ##
=========================================
Coverage 100.00% 100.00%
=========================================
Files 28 28
Lines 8609 8618 +9
=========================================
+ Hits 8609 8618 +9
|
Can you change these lines to: for elem in iter(ds):
if elem.VR == 'SQ': To fix the typing error |
You'll also need to add an explicit test for |
The failing test in |
- Add unit testing for `NotificationEvent::__str__()` - Add unit testing for `InterventionEvent::__str__()` - Remove `Event::__str__()` since it wasn't reliable/complete - Convert to f-strings in `benchmark_script.py` - Fix type error in `dsutils.py::pretty_dataset()`
I don't understand the state machine well enough to create a new unit test for |
OK, let me think about it a bit |
Test that `stop_dul()` returns `True` when in `Sta1`
I added a unit test to verify that |
@scaramallion Can you please kick off the workflow for this PR to verify that all of the checks now pass? Thanks! |
@scaramallion Just checking in on this again :-) |
Hi there, @scaramallion. Any update on this? It's been a month. Thanks. |
I'm really looking forward for this improvement, when can we expect this to be released? |
Thanks! |
Reference issue
Issue #650
What changed
Instead of sleeping before every event in
run_reactor()
, only sleep when there are no queued events to process.This ensures that queued events are processed as fast as possible. The
_run_loop_delay
setting now only affects the case where there are no queued events (i.e. the system is idle).After the performance optimization,
pynetdicom
C-STORE SCU is ~23x faster than before when transferring large DICOMs, such as the 2MBRTImageStorage.dcm
(0.87 sec vs 19.66 sec):Benchmark BEFORE:
Benchmark AFTER:
Now
pynetdicom
C-STORE SCU is only ~4x slower than DCMTK (0.87 sec vs. 0.22 sec) instead of ~100x forRTImageStorage.dcm
.The improvement is much more modest for small DICOMs, such as the 39KB
CTImageStorage.dcm
(only ~2x speedup).The ultrasound images we typically see in our use case are ~200MB and we saw a ~30x speedup on C-STORE SCU with this change.
How it was tested
All unit tests pass. Some unit tests had to be updated to avoid timing-dependent failures.
Also, one unit test fails on
master
even before the changes:pynetdicom/apps/tests/test_common.py:604: AssertionError: assert None == '' where None = getattr((300a, 00c0) Beam Number IS: None, 'BeamNumber')
Seems like there is an extra space in "Beam Number" somewhere?
I also tested the
storescu.py
app with a local instance of OsiriX Lite and it worked properly.This PR is ready to merge.