pydicom / pynetdicom

A Python implementation of the DICOM networking protocol
https://pydicom.github.io/pynetdicom
MIT License
500 stars 176 forks source link

C-STORE SCP performance issues with parallel storescu #917

Closed tokeefe closed 6 months ago

tokeefe commented 6 months ago

I'm noticing a very steep drop-off in C-STORE performance when multiple storescu (from DCMTK) transfers overlap, even if they only overlap briefly.

Here's a detailed example. I have a very simple pynetdicom C-STORE SCP running

from time import time 
from pynetdicom import (
    AE, evt,
    AllStoragePresentationContexts,
)

def main():
    ae = AE()
    ae.supported_contexts = AllStoragePresentationContexts
    handlers = [
        (
            evt.EVT_C_STORE, 
            handle_store
        )
    ]
    ae.start_server(
        (
            '0.0.0.0',
            11112
        ),
        ae_title='TESTING',
        evt_handlers=handlers,
        block=True
    )

def handle_store(event):
    ds = event.dataset
    seconds = int(time())
    print(f'{seconds} {ds.SOPInstanceUID}')
    return 0x0000

Now, in a separate shell, I'm sending a fairly large series (1.5 GB, 1300 files, SOP Class Enhanced MR Image Storage) using storescu from DCMTK

storescu <hostname> 11112 *.dcm

At this point, everything is reasonably fast. I'm seeing throughput on the order of about 20-22 files per second.

However, if I transfer a very small handful of DICOM files (e.g., 4 or 5 files with SOP Class MR Image Storage) in a parallel storescu process, the transfer speed of the first storescu falls considerably to about 2-3 files per second and never recovers. Only when I stop and restart the first transfer does performance goes back to 20-22 files per second.

P.S. - I have also noticed separately that there is a fairly significant performance difference when transferring SOP Class Enhanced MR Image Storage files using DCMTK storescu (roughly 20-22 files per second) versus python -m pynetdicom storescu (roughly 1-2 files per second). Not sure if this is related at the moment.

Here are some details from my environment. I am also able to share some DICOM files with SOP Class Enhanced MR Image Storage if needed

OS: CentOS 7.8 Python: 3.10.8 pynetdicom: 2.0.2

scaramallion commented 6 months ago

This isn't unexpected, there's always a performance cost with Python threading because of the GIL, although the performance hit should be temporary. I'm not sure why it would require restarting the server.

Enhanced MR does tend to be larger, the difference may be due to the overhead from pydicom decoding/encoding or it could be the PDU size? Have you tried the various options available to speed things up? Also, you know, Python.

I generally check the performance prior to release. The performance results for v2.0.0 are here.

tokeefe commented 6 months ago

Thank you for the quick reply. I've been testing this for the last day or so on different machines and I'm far less convinced at this point that performance issues I've been experiencing have anything to do with pynetdicom. I think I'm wrestling with filesystem performance issues. I'm going to close this question. Sorry for spinning your wheels. Thank you for all the hard work you and others have put into this amazing package!

scaramallion commented 6 months ago

No problem!