Skip to content

Instantly share code, notes, and snippets.

@amegianeg
Last active July 24, 2020 15:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save amegianeg/f471a74c307c650547de8b5917202c62 to your computer and use it in GitHub Desktop.
Save amegianeg/f471a74c307c650547de8b5917202c62 to your computer and use it in GitHub Desktop.
import io
import shutil
import timeit
import os
import uuid
from functools import partial
BYTES_PER_MB = 1048576
NUM_ROUNDS = 5
NUM_EXECUTIONS = 100
CHUNK_SIZE = (64 * 2 ** 10) * 2 # 64kb * 2
NUMPY_ENABLED = False
def write_dicom_instance(instance_path, dicom_data_bytes):
dicom_data_bytes.seek(0)
os.makedirs(os.path.dirname(instance_path), exist_ok=True)
with open(instance_path, "wb") as outf:
outf.write(dicom_data_bytes.getbuffer())
# TODO chunks not working with BytesIO
#def write_dicom_file_chunks(instance_path, dicom_data_bytes):
# os.makedirs(os.path.dirname(instance_path), exist_ok=True)
# with open(instance_path, "wb") as outf:
# for chunk in dicom_data_bytes.chunks():
# outf.write(chunk)
def write_dicom_instance_buffer(instance_path, dicom_data_bytes):
dicom_data_bytes.seek(0)
os.makedirs(os.path.dirname(instance_path), exist_ok=True)
with open(instance_path, "wb", buffering=CHUNK_SIZE) as outf:
outf.write(dicom_data_bytes.getbuffer())
def write_dicom_instance_buffer_4096(instance_path, dicom_data_bytes):
dicom_data_bytes.seek(0)
os.makedirs(os.path.dirname(instance_path), exist_ok=True)
with open(instance_path, "wb", buffering=4096) as outf:
outf.write(dicom_data_bytes.getbuffer())
# TODO chunks not working with BytesIO
#def write_dicom_instance_buffer_rw(instance_path, dicom_data_bytes):
# os.makedirs(os.path.dirname(instance_path), exist_ok=True)
# with open(instance_path, "wb", buffering=CHUNK_SIZE) as outf:
# for chunk in dicom_data_bytes.chunks(chunk_size=CHUNK_SIZE):
# outf.write(chunk.getbuffer())
def write_dicom_instance_numpy(instance_path, dicom_data_bytes):
dicom_data_bytes.seek(0)
os.makedirs(os.path.dirname(instance_path), exist_ok=True)
array = np.array(dicom_data_bytes.getbuffer())
with open('binary.file', 'wb') as f:
array.tofile(instance_path)
def write_file_fast_copy(instance_path, dicom_data_bytes):
dicom_data_bytes.seek(0)
os.makedirs(os.path.dirname(instance_path), exist_ok=True)
with open(instance_path, "wb") as outf:
shutil.copyfileobj(dicom_data_bytes, outf)
def write_file_fast_copy_change_chunk_128(instance_path, dicom_data_bytes):
dicom_data_bytes.seek(0)
os.makedirs(os.path.dirname(instance_path), exist_ok=True)
with open(instance_path, "wb") as outf:
shutil.copyfileobj(dicom_data_bytes, outf, length=128 * 1024)
def write_file_fast_copy_change_chunk_256(instance_path, dicom_data_bytes):
dicom_data_bytes.seek(0)
os.makedirs(os.path.dirname(instance_path), exist_ok=True)
with open(instance_path, "wb") as outf:
shutil.copyfileobj(dicom_data_bytes, outf, length=256 * 1024)
def write_file_fast_copy_change_chunk_512(instance_path, dicom_data_bytes):
dicom_data_bytes.seek(0)
os.makedirs(os.path.dirname(instance_path), exist_ok=True)
with open(instance_path, "wb") as outf:
shutil.copyfileobj(dicom_data_bytes, outf, length=512 * 1024)
if __name__ == '__main__':
file_plain_films = io.BytesIO(os.urandom(BYTES_PER_MB * 15)) # Plain films 10-20Mb per dicom
file_ct = io.BytesIO(os.urandom(int(BYTES_PER_MB * 0.5))) # CT 520kb per dicom
file_mamo = io.BytesIO(os.urandom(int(BYTES_PER_MB * 30))) # Mamo 30MB per dicom
file_mr = io.BytesIO(os.urandom(int(BYTES_PER_MB * 0.25))) # MR 250kb per dicom
files = {
"PLAIN FILMS": file_plain_films,
"CT": file_ct,
"MAMO": file_mamo,
"MR": file_mr
}
for test, file in files.items():
print(f"Testing {test}")
output_path = f"./outputs/{uuid.uuid4()}/{test}"
print("Test 'write_file_fast_copy' started...")
result = timeit.repeat(
partial(write_file_fast_copy, output_path, file), repeat=NUM_ROUNDS, number=NUM_EXECUTIONS)
print(min(result))
print("Test 'write_file_fast_copy' finished.")
print("Test 'write_file_fast_copy_change_chunk_128' started...")
result = timeit.repeat(
partial(write_file_fast_copy_change_chunk_128, output_path, file), repeat=NUM_ROUNDS, number=NUM_EXECUTIONS)
print(min(result))
print("Test 'write_file_fast_copy_change_chunk_128' finished.")
print("Test 'write_file_fast_copy_change_chunk_256' started...")
result = timeit.repeat(
partial(write_file_fast_copy_change_chunk_256, output_path, file), repeat=NUM_ROUNDS, number=NUM_EXECUTIONS)
print(min(result))
print("Test 'write_file_fast_copy_change_chunk_256' finished.")
print("Test 'write_file_fast_copy_change_chunk_512' started...")
result = timeit.repeat(
partial(write_file_fast_copy_change_chunk_512, output_path, file), repeat=NUM_ROUNDS, number=NUM_EXECUTIONS)
print(min(result))
print("Test 'write_file_fast_copy_change_chunk_512' finished.")
print("Test 'write_dicom_instance_buffer' started...")
result = timeit.repeat(
partial(write_dicom_instance_buffer, output_path, file), repeat=NUM_ROUNDS, number=NUM_EXECUTIONS)
print(min(result))
print("Test 'write_dicom_instance_buffer' finished.")
print("Test 'write_dicom_instance_buffer_4096' started...")
result = timeit.repeat(
partial(write_dicom_instance_buffer_4096, output_path, file), repeat=NUM_ROUNDS, number=NUM_EXECUTIONS)
print(min(result))
print("Test 'write_dicom_instance_buffer_4096' finished.")
print("Test 'write_dicom_instance' started...")
result = timeit.repeat(
partial(write_dicom_instance, output_path, file), repeat=NUM_ROUNDS, number=NUM_EXECUTIONS)
print(min(result))
print("Test 'write_dicom_instance' finished.")
#import numpy as np
#print("Test 'write_dicom_instance_numpy' started...")
#result = timeit.repeat(
# partial(write_dicom_instance_numpy, output_path, file), repeat=NUM_ROUNDS, number=NUM_EXECUTIONS)
#print(min(result))
#print("Test 'write_dicom_instance_numpy' finished.")
print(f"Tests {test} finished!")
print("::::::::::::::::::::::::::::::::::::::::::::")
@amegianeg
Copy link
Author

amegianeg commented Jul 24, 2020

write_dicom_instance: base implementation

Testing PLAIN FILMS
Test 'write_dicom_instance' started...
2.3236861930000003
Test 'write_dicom_instance' finished.
Tests PLAIN FILMS finished!
::::::::::::::::::::::::::::::::::::::::::::
Testing CT
Test 'write_dicom_instance' started...
0.10834836899999978
Test 'write_dicom_instance' finished.
Tests CT finished!
::::::::::::::::::::::::::::::::::::::::::::
Testing MAMO
Test 'write_dicom_instance' started...
4.422732101999998
Test 'write_dicom_instance' finished.
Tests MAMO finished!
::::::::::::::::::::::::::::::::::::::::::::
Testing MR
Test 'write_dicom_instance' started...
0.07136972800000052
Test 'write_dicom_instance' finished.
Tests MR finished!

@amegianeg
Copy link
Author

amegianeg commented Jul 24, 2020

write_dicom_instance_buffer_rw: no improvement with the previous implementation

Testing PLAIN FILMS
Test 'write_dicom_instance_buffer_rw' started...
2.345521752
Test 'write_dicom_instance_buffer_rw' finished.
Tests PLAIN FILMS finished!
::::::::::::::::::::::::::::::::::::::::::::
Testing CT
Test 'write_dicom_instance_buffer_rw' started...
0.11416392900000005
Test 'write_dicom_instance_buffer_rw' finished.
Tests CT finished!
::::::::::::::::::::::::::::::::::::::::::::
Testing MAMO
Test 'write_dicom_instance_buffer_rw' started...
4.490772623000002
Test 'write_dicom_instance_buffer_rw' finished.
Tests MAMO finished!
::::::::::::::::::::::::::::::::::::::::::::
Testing MR
Test 'write_dicom_instance_buffer_rw' started...
0.07157750399999685
Test 'write_dicom_instance_buffer_rw' finished.
Tests MR finished!
::::::::::::::::::::::::::::::::::::::::::::

@amegianeg
Copy link
Author

write_dicom_instance_numpy: worse than the previous versions

Testing PLAIN FILMS
Test 'write_dicom_instance_numpy' started...
3.3246694480000016
Test 'write_dicom_instance_numpy' finished.
Tests PLAIN FILMS finished!
::::::::::::::::::::::::::::::::::::::::::::
Testing CT
Test 'write_dicom_instance_numpy' started...
0.2788707770000016
Test 'write_dicom_instance_numpy' finished.
Tests CT finished!
::::::::::::::::::::::::::::::::::::::::::::
Testing MAMO
Test 'write_dicom_instance_numpy' started...
7.217684729000002
Test 'write_dicom_instance_numpy' finished.
Tests MAMO finished!
::::::::::::::::::::::::::::::::::::::::::::
Testing MR
Test 'write_dicom_instance_numpy' started...
0.11927498899999023
Test 'write_dicom_instance_numpy' finished.
Tests MR finished!
::::::::::::::::::::::::::::::::::::::::::::

@amegianeg
Copy link
Author

write_dicom_instance_buffer_4096: no improvement from base implementation

Testing PLAIN FILMS
Test 'write_dicom_instance_buffer_4096' started...
2.412398447
Test 'write_dicom_instance_buffer_4096' finished.
Tests PLAIN FILMS finished!
::::::::::::::::::::::::::::::::::::::::::::
Testing CT
Test 'write_dicom_instance_buffer_4096' started...
0.11473188399999934
Test 'write_dicom_instance_buffer_4096' finished.
Tests CT finished!
::::::::::::::::::::::::::::::::::::::::::::
Testing MAMO
Test 'write_dicom_instance_buffer_4096' started...
4.457865293999998
Test 'write_dicom_instance_buffer_4096' finished.
Tests MAMO finished!
::::::::::::::::::::::::::::::::::::::::::::
Testing MR
Test 'write_dicom_instance_buffer_4096' started...
0.07531849600000129
Test 'write_dicom_instance_buffer_4096' finished.
Tests MR finished!
::::::::::::::::::::::::::::::::::::::::::::

@amegianeg
Copy link
Author

write_dicom_instance_buffer: same

Testing PLAIN FILMS
Test 'write_dicom_instance_buffer' started...
2.4109502640000002
Test 'write_dicom_instance_buffer' finished.
Tests PLAIN FILMS finished!
::::::::::::::::::::::::::::::::::::::::::::
Testing CT
Test 'write_dicom_instance_buffer' started...
0.11323438199999991
Test 'write_dicom_instance_buffer' finished.
Tests CT finished!
::::::::::::::::::::::::::::::::::::::::::::
Testing MAMO
Test 'write_dicom_instance_buffer' started...
4.434075345
Test 'write_dicom_instance_buffer' finished.
Tests MAMO finished!
::::::::::::::::::::::::::::::::::::::::::::
Testing MR
Test 'write_dicom_instance_buffer' started...
0.06980183400000328
Test 'write_dicom_instance_buffer' finished.
Tests MR finished!

@amegianeg
Copy link
Author

write_file_fast_copy: slightly worse

Testing PLAIN FILMS
Test 'write_file_fast_copy' started...
2.61764579
Test 'write_file_fast_copy' finished.
Tests PLAIN FILMS finished!
::::::::::::::::::::::::::::::::::::::::::::
Testing CT
Test 'write_file_fast_copy' started...
0.12783440299999782
Test 'write_file_fast_copy' finished.
Tests CT finished!
::::::::::::::::::::::::::::::::::::::::::::
Testing MAMO
Test 'write_file_fast_copy' started...
4.867965638000001
Test 'write_file_fast_copy' finished.
Tests MAMO finished!
::::::::::::::::::::::::::::::::::::::::::::
Testing MR
Test 'write_file_fast_copy' started...
0.08191233099999806
Test 'write_file_fast_copy' finished.
Tests MR finished!

@amegianeg
Copy link
Author

write_file_fast_copy_change_chunk_128: no improvement

Testing PLAIN FILMS
Test 'write_file_fast_copy_change_chunk_128' started...
2.584029662999999
Test 'write_file_fast_copy_change_chunk_128' finished.
Tests PLAIN FILMS finished!
::::::::::::::::::::::::::::::::::::::::::::
Testing CT
Test 'write_file_fast_copy_change_chunk_128' started...
0.1249897269999991
Test 'write_file_fast_copy_change_chunk_128' finished.
Tests CT finished!
::::::::::::::::::::::::::::::::::::::::::::
Testing MAMO
Test 'write_file_fast_copy_change_chunk_128' started...
4.526621552000002
Test 'write_file_fast_copy_change_chunk_128' finished.
Tests MAMO finished!
::::::::::::::::::::::::::::::::::::::::::::
Testing MR
Test 'write_file_fast_copy_change_chunk_128' started...
0.07811508099999998
Test 'write_file_fast_copy_change_chunk_128' finished.
Tests MR finished!
::::::::::::::::::::::::::::::::::::::::::::

@amegianeg
Copy link
Author

write_file_fast_copy_change_chunk_256: no improvements

Testing PLAIN FILMS
Test 'write_file_fast_copy_change_chunk_256' started...
2.416214388
Test 'write_file_fast_copy_change_chunk_256' finished.
Tests PLAIN FILMS finished!
::::::::::::::::::::::::::::::::::::::::::::
Testing CT
Test 'write_file_fast_copy_change_chunk_256' started...
0.11935645099999981
Test 'write_file_fast_copy_change_chunk_256' finished.
Tests CT finished!
::::::::::::::::::::::::::::::::::::::::::::
Testing MAMO
Test 'write_file_fast_copy_change_chunk_256' started...
4.569652141000001
Test 'write_file_fast_copy_change_chunk_256' finished.
Tests MAMO finished!
::::::::::::::::::::::::::::::::::::::::::::
Testing MR
Test 'write_file_fast_copy_change_chunk_256' started...
0.07252838499999825
Test 'write_file_fast_copy_change_chunk_256' finished.
Tests MR finished!
::::::::::::::::::::::::::::::::::::::::::::

@amegianeg
Copy link
Author

write_file_fast_copy_change_chunk_512: no improvements

Testing PLAIN FILMS
Test 'write_file_fast_copy_change_chunk_512' started...
2.458809799999999
Test 'write_file_fast_copy_change_chunk_512' finished.
Tests PLAIN FILMS finished!
::::::::::::::::::::::::::::::::::::::::::::
Testing CT
Test 'write_file_fast_copy_change_chunk_512' started...
0.11533704300000025
Test 'write_file_fast_copy_change_chunk_512' finished.
Tests CT finished!
::::::::::::::::::::::::::::::::::::::::::::
Testing MAMO
Test 'write_file_fast_copy_change_chunk_512' started...
4.5445658510000015
Test 'write_file_fast_copy_change_chunk_512' finished.
Tests MAMO finished!
::::::::::::::::::::::::::::::::::::::::::::
Testing MR
Test 'write_file_fast_copy_change_chunk_512' started...
0.0664006160000028
Test 'write_file_fast_copy_change_chunk_512' finished.
Tests MR finished!
::::::::::::::::::::::::::::::::::::::::::::

@amegianeg
Copy link
Author

amegianeg commented Jul 24, 2020

All at the same time, easier to compare the values:

$ python3 write_to_file_performance_test.py
Testing PLAIN FILMS
Test 'write_file_fast_copy' started...
2.961749990999998
Test 'write_file_fast_copy' finished.
Test 'write_file_fast_copy_change_chunk_128' started...
2.9871696420000013
Test 'write_file_fast_copy_change_chunk_128' finished.
Test 'write_file_fast_copy_change_chunk_256' started...
2.411549119
Test 'write_file_fast_copy_change_chunk_256' finished.
Test 'write_file_fast_copy_change_chunk_512' started...
2.413421995
Test 'write_file_fast_copy_change_chunk_512' finished.
Test 'write_dicom_instance_buffer' started...
2.3236169019999977
Test 'write_dicom_instance_buffer' finished.
Test 'write_dicom_instance_buffer_4096' started...
2.3362732370000003
Test 'write_dicom_instance_buffer_4096' finished.
Test 'write_dicom_instance' started...
2.372609123999993
Test 'write_dicom_instance' finished.
Tests PLAIN FILMS finished!
::::::::::::::::::::::::::::::::::::::::::::
Testing CT
Test 'write_file_fast_copy' started...
0.12380990999999142
Test 'write_file_fast_copy' finished.
Test 'write_file_fast_copy_change_chunk_128' started...
0.12076031800000919
Test 'write_file_fast_copy_change_chunk_128' finished.
Test 'write_file_fast_copy_change_chunk_256' started...
0.11965514799999255
Test 'write_file_fast_copy_change_chunk_256' finished.
Test 'write_file_fast_copy_change_chunk_512' started...
0.10971228200000382
Test 'write_file_fast_copy_change_chunk_512' finished.
Test 'write_dicom_instance_buffer' started...
0.11221432800000741
Test 'write_dicom_instance_buffer' finished.
Test 'write_dicom_instance_buffer_4096' started...
0.10755577999999844
Test 'write_dicom_instance_buffer_4096' finished.
Test 'write_dicom_instance' started...
0.11277851100000191
Test 'write_dicom_instance' finished.
Tests CT finished!
::::::::::::::::::::::::::::::::::::::::::::
Testing MAMO
Test 'write_file_fast_copy' started...
4.917326614999993
Test 'write_file_fast_copy' finished.
Test 'write_file_fast_copy_change_chunk_128' started...
4.941889986999996
Test 'write_file_fast_copy_change_chunk_128' finished.
Test 'write_file_fast_copy_change_chunk_256' started...
4.925404423999993
Test 'write_file_fast_copy_change_chunk_256' finished.
Test 'write_file_fast_copy_change_chunk_512' started...
4.839120589999993
Test 'write_file_fast_copy_change_chunk_512' finished.
Test 'write_dicom_instance_buffer' started...
4.611101071999997
Test 'write_dicom_instance_buffer' finished.
Test 'write_dicom_instance_buffer_4096' started...
4.702945935999992
Test 'write_dicom_instance_buffer_4096' finished.
Test 'write_dicom_instance' started...
4.79309931100002
Test 'write_dicom_instance' finished.
Tests MAMO finished!
::::::::::::::::::::::::::::::::::::::::::::
Testing MR
Test 'write_file_fast_copy' started...
0.08194350200000144
Test 'write_file_fast_copy' finished.
Test 'write_file_fast_copy_change_chunk_128' started...
0.07718963999997186
Test 'write_file_fast_copy_change_chunk_128' finished.
Test 'write_file_fast_copy_change_chunk_256' started...
0.08061887400003798
Test 'write_file_fast_copy_change_chunk_256' finished.
Test 'write_file_fast_copy_change_chunk_512' started...
0.07632753999996567
Test 'write_file_fast_copy_change_chunk_512' finished.
Test 'write_dicom_instance_buffer' started...
0.07362100500000679
Test 'write_dicom_instance_buffer' finished.
Test 'write_dicom_instance_buffer_4096' started...
0.07274474700000155
Test 'write_dicom_instance_buffer_4096' finished.
Test 'write_dicom_instance' started...
0.0713035929999819
Test 'write_dicom_instance' finished.
Tests MR finished!
::::::::::::::::::::::::::::::::::::::::::::

@amegianeg
Copy link
Author

amegianeg commented Jul 24, 2020

NOTE: using min of the rounds because of this (https://stackoverflow.com/questions/8220801/how-to-use-timeit-module#comment12782516_8220943):

@max Use the min() rather than the average of the timings. That is a recommendation from me, from Tim Peters, and from Guido van Rossum. The fastest time represents the best an algorithm can perform when the caches are loaded and the system isn't busy with other tasks. All the timings are noisy -- the fastest time is the least noisy. It is easy to show that the fastest timings are the most reproducible and therefore the most useful when timing two different implementations. – Raymond Hettinger Apr 3 '12 at 19:43

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment