Mercurial > hg > orthanc-tests
changeset 926:43b07d7e6fd2
non regression perfs for s3 too
| author | Alain Mazy <am@orthanc.team> |
|---|---|
| date | Fri, 12 Jun 2026 14:17:35 +0200 |
| parents | afc7edf1dff8 |
| children | fe40df898a4d |
| files | NewTests/NonRegressionPerfs/docker-compose.yml NewTests/NonRegressionPerfs/test_non_regression_perfs.py NewTests/requirements.txt |
| diffstat | 3 files changed, 230 insertions(+), 43 deletions(-) [+] |
line wrap: on
line diff
--- a/NewTests/NonRegressionPerfs/docker-compose.yml Thu Jun 11 10:24:23 2026 +0200 +++ b/NewTests/NonRegressionPerfs/docker-compose.yml Fri Jun 12 14:17:35 2026 +0200 @@ -49,8 +49,130 @@ environment: POSTGRES_HOST_AUTH_METHOD: "trust" + + orthanc-ref-s3: + image: orthancteam/orthanc:26.1.0 + depends_on: [orthanc-ref-db-s3] + restart: unless-stopped + ports: ["8242:8042"] + environment: + VERBOSE_ENABLED: "true" + ORTHANC__POSTGRESQL__HOST: "orthanc-ref-db-s3" + ORTHANC_JSON: | + { + "Name": "Orthanc-ref-s3", + "AuthenticationEnabled": false, + "OverwriteInstances": true, + "AwsS3Storage": { + "BucketName": "default-bucket", + "Region": "eu-west-1", + "AccessKey": "minio", + "SecretKey": "miniopwd", + "Endpoint": "http://toxiproxy-ref-s3:9000", + "VirtualAddressing": false + } + } + + orthanc-new-s3: + image: ${ORTHANC_IMAGE_UNDER_TESTS:-orthancteam/orthanc:latest} + depends_on: [orthanc-new-db-s3] + restart: unless-stopped + ports: ["8243:8042"] + environment: + VERBOSE_ENABLED: "true" + ORTHANC__POSTGRESQL__HOST: "orthanc-new-db-s3" + ORTHANC_JSON: | + { + "Name": "Orthanc-under-tests-s3", + "AuthenticationEnabled": false, + "OverwriteInstances": true, + "AwsS3Storage": { + "BucketName": "default-bucket", + "Region": "eu-west-1", + "AccessKey": "minio", + "SecretKey": "miniopwd", + "Endpoint": "http://toxiproxy-new-s3:9000", + "VirtualAddressing": false + } + } + + + orthanc-ref-db-s3: + image: postgres:18 + restart: unless-stopped + volumes: + - "storage-db-ref-s3:/var/lib/postgresql/18/docker" + environment: + POSTGRES_HOST_AUTH_METHOD: "trust" + + orthanc-new-db-s3: + image: postgres:18 + restart: unless-stopped + volumes: + - "storage-db-new-s3:/var/lib/postgresql/18/docker" + environment: + POSTGRES_HOST_AUTH_METHOD: "trust" + + + minio-ref: + image: minio/minio:RELEASE.2025-09-07T16-13-09Z + # don't expose these ports in a real world setup + # ports: [9000:9000, 9001:9001] + environment: + - MINIO_REGION=eu-west-1 + - MINIO_ROOT_USER=minio + - MINIO_ROOT_PASSWORD=miniopwd + volumes: + - storage-minio-ref-s3:/data + entrypoint: sh + command: -c 'mkdir -p /data/default-bucket && /usr/bin/docker-entrypoint.sh server /data --console-address ":9001"' + + minio-new: + image: minio/minio:RELEASE.2025-09-07T16-13-09Z + # don't expose these ports in a real world setup + # ports: [9000:9000, 9001:9001] + environment: + - MINIO_REGION=eu-west-1 + - MINIO_ROOT_USER=minio + - MINIO_ROOT_PASSWORD=miniopwd + volumes: + - storage-minio-new-s3:/data + entrypoint: sh + command: -c 'mkdir -p /data/default-bucket && /usr/bin/docker-entrypoint.sh server /data --console-address ":9001"' + + toxiproxy-ref-s3: + depends_on: + - minio-ref + # ports: ["19200:9000"] + image: ghcr.io/shopify/toxiproxy + + toxiproxy-new-s3: + depends_on: + - minio-new + # ports: ["19201:9000"] + image: ghcr.io/shopify/toxiproxy + + + toxiproxy-config: + image: curlimages/curl + depends_on: + - toxiproxy-ref-s3 + - toxiproxy-new-s3 + restart: on-failure + entrypoint: > + sh -c "sleep 3; + curl -sf -X POST http://toxiproxy-ref-s3:8474/proxies -H 'Content-Type: application/json' -d '{\"name\":\"minio\",\"listen\":\"0.0.0.0:9000\",\"upstream\":\"minio-ref:9000\"}'; + curl -sf -X POST http://toxiproxy-ref-s3:8474/proxies/minio/toxics -H 'Content-Type: application/json' -d '{\"type\":\"latency\",\"attributes\":{\"latency\":10,\"jitter\":0}}'; + curl -sf -X POST http://toxiproxy-new-s3:8474/proxies -H 'Content-Type: application/json' -d '{\"name\":\"minio\",\"listen\":\"0.0.0.0:9000\",\"upstream\":\"minio-new:9000\"}'; + curl -sf -X POST http://toxiproxy-new-s3:8474/proxies/minio/toxics -H 'Content-Type: application/json' -d '{\"type\":\"latency\",\"attributes\":{\"latency\":10,\"jitter\":0}}'; + " + volumes: storage-orthanc-ref: storage-orthanc-new: storage-db-ref: - storage-db-new: \ No newline at end of file + storage-db-new: + storage-minio-ref-s3: + storage-minio-new-s3: + storage-db-ref-s3: + storage-db-new-s3: \ No newline at end of file
--- a/NewTests/NonRegressionPerfs/test_non_regression_perfs.py Thu Jun 11 10:24:23 2026 +0200 +++ b/NewTests/NonRegressionPerfs/test_non_regression_perfs.py Fri Jun 12 14:17:35 2026 +0200 @@ -15,16 +15,22 @@ here = pathlib.Path(__file__).parent.resolve() -test_configs = { - "ref": { - "orthanc-url": "http://localhost:8142" - }, - "new": { - "orthanc-url": "http://localhost:8143" - } -} +# test_configs = { +# "ref": { +# "orthanc-url": "http://localhost:8142" +# }, +# "new": { +# "orthanc-url": "http://localhost:8143" +# }, +# "ref-s3": { +# "orthanc-url": "http://localhost:8242" +# }, +# "new-s3": { +# "orthanc-url": "http://localhost:8243" +# } +# } -test_results = {} +# test_results = {} # Download a file localy (only the first time) and return its local_path and content def download_test_file(url: str) -> Tuple[str, bytes]: @@ -49,23 +55,23 @@ subprocess.run(["docker", "compose", "down", "-v", "--remove-orphans"], check=True) - @classmethod - def setUpClass(cls): - os.chdir(here) - subprocesss_env = os.environ.copy() - subprocesss_env["ORTHANC_IMAGE_UNDER_TESTS"] = Helpers.orthanc_under_tests_docker_image + # @classmethod + # def setUpClass(cls): + # os.chdir(here) + # subprocesss_env = os.environ.copy() + # subprocesss_env["ORTHANC_IMAGE_UNDER_TESTS"] = Helpers.orthanc_under_tests_docker_image - # print("Pullling containers") - # subprocess.run(["docker", "compose", "pull"], env=subprocesss_env, check=True) + # # print("Pullling containers") + # # subprocess.run(["docker", "compose", "pull"], env=subprocesss_env, check=True) - print("Launching containers") - subprocess.run(["docker", "compose", "up", "-d"], env=subprocesss_env, check=True) + # print("Launching containers") + # subprocess.run(["docker", "compose", "up", "-d"], env=subprocesss_env, check=True) - o_ref = OrthancApiClient(test_configs["ref"]["orthanc-url"]) - o_new = OrthancApiClient(test_configs["new"]["orthanc-url"]) + # o_ref = OrthancApiClient(test_configs["ref"]["orthanc-url"]) + # o_new = OrthancApiClient(test_configs["new"]["orthanc-url"]) - o_ref.wait_started() - o_new.wait_started() + # o_ref.wait_started() + # o_new.wait_started() @classmethod @@ -73,9 +79,7 @@ cls.cleanup() - def measure(self, test_name: str, perform_test: Callable[[OrthancApiClient], None], reapeat_count: int = 1, tolerance_pct = 0.25) -> None: - global test_configs - global test_results + def measure(self, test_name: str, perform_test: Callable[[OrthancApiClient], None], test_configs, test_results, reapeat_count: int = 1, tolerance_pct = 0.25) -> None: test_results[test_name] = {} @@ -108,39 +112,100 @@ test_results[test_name]["success"] = not failed - def test_non_regression(self): - print("Launching tests") + def test_non_regression_s3(self): + print("Launching tests (s3)") + + test_configs = { + "ref": { + "orthanc-url": "http://localhost:8242" + }, + "new": { + "orthanc-url": "http://localhost:8243" + } + } + test_results = {} + self.compare(config_name='s3' + test_configs=test_configs, + test_results=test_results) + + + def test_non_regression_classic(self): + print("Launching tests (classic)") - print("") + test_configs = { + "ref": { + "orthanc-url": "http://localhost:8142" + }, + "new": { + "orthanc-url": "http://localhost:8143" + } + } + test_results = {} + self.compare(config_name='file-system' + test_configs=test_configs, + test_results=test_results) + + + def compare(self, config_name, test_configs, test_results): + + os.chdir(here) + subprocesss_env = os.environ.copy() + subprocesss_env["ORTHANC_IMAGE_UNDER_TESTS"] = Helpers.orthanc_under_tests_docker_image + + # print("Pullling containers") + # subprocess.run(["docker", "compose", "pull"], env=subprocesss_env, check=True) + + print("Launching containers") + subprocess.run(["docker", "compose", "up", "-d"], env=subprocesss_env, check=True) + + o_ref = OrthancApiClient(test_configs["ref"]["orthanc-url"]) + o_new = OrthancApiClient(test_configs["new"]["orthanc-url"]) + + o_ref.wait_started() + o_new.wait_started() + + print(f"---------- {config_name} -----------") print(f"{'TEST NAME':<50} | {'REF ORTHANC [ms]':>20} | {'NEW ORTHANC [ms]':>20} | {'DELTA [PCT]':>20}") print(f"{'-'*119}") - self.measure(test_name="populate with 5 workers", + self.measure(test_name="populate 3000 instances with 5 workers", perform_test=lambda o: OrthancTestDbPopulator(o, studies_count=5, series_count=3, instances_count=120, random_seed=65, worker_threads_count=5).execute(), - reapeat_count=1) + reapeat_count=1, + test_configs=test_configs, + test_results=test_results) - self.measure(test_name="studies statistics", + self.measure(test_name="studies statistics 5x5", perform_test=lambda o: [o.studies.get_json_statistics(i) for i in o.studies.get_all_ids()], - reapeat_count=5) - + reapeat_count=5, + test_configs=test_configs, + test_results=test_results) + reg_of_path, reg_of_content = download_test_file("https://public-files.orthanc.team/test-files/429_MB_REG_OF.dcm") reg_ow_path, reg_ow_content = download_test_file("https://public-files.orthanc.team/test-files/429_MB_REG_OW.dcm") self.measure(test_name="upload large Reg file with OW VectorGridData", perform_test=lambda o: o.upload(reg_ow_content), - reapeat_count=1) - + reapeat_count=1, + test_configs=test_configs, + test_results=test_results) + self.measure(test_name="upload large Reg file with OF VectorGridData", perform_test=lambda o: o.upload(reg_of_content), - reapeat_count=1) + reapeat_count=1, + test_configs=test_configs, + test_results=test_results) - self.measure(test_name="upload same file", + self.measure(test_name="upload same file 50x", perform_test=lambda o: o.upload_file(here / "../../Database/Knee/T1/IM-0001-0001.dcm"), - reapeat_count=50) + reapeat_count=50, + test_configs=test_configs, + test_results=test_results) - self.measure(test_name="upload same file SEG", + self.measure(test_name="upload same file SEG 50x", perform_test=lambda o: o.upload_file(here / "../../Database/DicomSeg.dcm"), - reapeat_count=50) + reapeat_count=50, + test_configs=test_configs, + test_results=test_results) print("Stopping containers") subprocess.run(["docker", "compose", "down"], check=True)
