Skip to content

Commit 63b02b0

Browse files
committed
fix optional dependencies
1 parent c9fbcc3 commit 63b02b0

3 files changed

Lines changed: 68 additions & 29 deletions

File tree

pyproject.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ docs = [
5252
axisarray = [
5353
"numpy>=2.2.6",
5454
]
55+
perf = [
56+
"xarray",
57+
]
5558

5659
[project.scripts]
5760
ezmsg = "ezmsg.core.command:cmdline"

src/ezmsg/util/perf/analysis.py

Lines changed: 43 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from __future__ import annotations
2+
13
import argparse
24
import dataclasses
35
import html
@@ -6,25 +8,43 @@
68
import webbrowser
79

810
from pathlib import Path
9-
10-
from ..messagecodec import MessageDecoder
11-
from .envinfo import TestEnvironmentInfo, format_env_diff
12-
from .impl import Metrics, TestLogEntry, TestParameters
11+
from typing import TYPE_CHECKING, Any
1312

1413
import ezmsg.core as ez
1514

16-
try:
15+
if TYPE_CHECKING:
16+
import numpy as np
17+
import pandas as pd
1718
import xarray as xr
18-
import pandas as pd # xarray depends on pandas
19-
except ImportError:
20-
ez.logger.error("ezmsg perf analysis requires xarray")
21-
raise
19+
from .envinfo import TestEnvironmentInfo
2220

23-
try:
24-
import numpy as np
25-
except ImportError:
26-
ez.logger.error("ezmsg perf analysis requires numpy")
27-
raise
21+
xr: Any | None = None
22+
pd: Any | None = None
23+
np: Any | None = None
24+
25+
26+
def _load_analysis_dependencies() -> tuple[Any, Any, Any]:
27+
global xr, pd, np
28+
29+
if xr is None or pd is None:
30+
try:
31+
import xarray as _xr
32+
import pandas as _pd # xarray depends on pandas
33+
except ImportError:
34+
ez.logger.error("ezmsg perf analysis requires xarray")
35+
raise
36+
xr = _xr
37+
pd = _pd
38+
39+
if np is None:
40+
try:
41+
import numpy as _np
42+
except ImportError:
43+
ez.logger.error("ezmsg perf analysis requires numpy")
44+
raise
45+
np = _np
46+
47+
return xr, pd, np
2848

2949
TEST_DESCRIPTION = """
3050
Configurations (config):
@@ -112,7 +132,12 @@ class ReportBundle:
112132

113133

114134
def load_perf(perf: Path) -> xr.Dataset:
115-
all_results: dict[TestParameters, dict[int, list[Metrics]]] = dict()
135+
xr, _, np = _load_analysis_dependencies()
136+
from ..messagecodec import MessageDecoder
137+
from .envinfo import TestEnvironmentInfo
138+
from .impl import Metrics, TestLogEntry
139+
140+
all_results: dict[Any, dict[int, list[Any]]] = dict()
116141
run_idx = 0
117142

118143
with open(perf, "r") as perf_f:
@@ -326,6 +351,9 @@ def _terminal_delta_summary(
326351

327352

328353
def build_report_bundle(perf_path: Path, baseline_path: Path | None = None) -> ReportBundle:
354+
_load_analysis_dependencies()
355+
from .envinfo import format_env_diff
356+
329357
candidate = load_perf(perf_path)
330358
info: TestEnvironmentInfo = candidate.attrs["info"]
331359
candidate_frame = _display_frame(_frame_from_dataset(candidate), relative=False)

src/ezmsg/util/perf/run.py

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from __future__ import annotations
2+
13
import os
24
import sys
35
import json
@@ -14,20 +16,10 @@
1416
import ezmsg.core as ez
1517
from ezmsg.core.graphserver import GraphServer
1618

17-
from ..messagecodec import MessageEncoder
18-
from .envinfo import TestEnvironmentInfo
19-
from .util import warmup
20-
from .impl import (
21-
TestParameters,
22-
TestLogEntry,
23-
perform_test,
24-
Communication,
25-
CONFIGS,
26-
)
27-
2819
DEFAULT_MSG_SIZES = [2**4, 2**20]
2920
DEFAULT_N_CLIENTS = [1, 16]
30-
DEFAULT_COMMS = [c for c in Communication]
21+
DEFAULT_COMMS = ["local", "shm", "tcp", "shm_spread", "tcp_spread"]
22+
DEFAULT_CONFIGS = ["fanin", "fanout", "relay"]
3123

3224

3325
# --- Output Suppression Context Manager ---
@@ -103,6 +95,18 @@ def output_paths_for_name(name: str) -> tuple[Path, Path]:
10395
return Path(f"perf_{name}.txt"), Path(f"report_{name}.html")
10496

10597

98+
def warmup(*args, **kwargs):
99+
from .util import warmup as _warmup
100+
101+
return _warmup(*args, **kwargs)
102+
103+
104+
def perform_test(**kwargs):
105+
from .impl import perform_test as _perform_test
106+
107+
return _perform_test(**kwargs)
108+
109+
106110
def benchmark(
107111
max_duration: float,
108112
num_msgs: int,
@@ -118,6 +122,10 @@ def benchmark(
118122
name: str | None = None,
119123
open_browser: bool = True,
120124
) -> tuple[Path, Path | None]:
125+
from ..messagecodec import MessageEncoder
126+
from .envinfo import TestEnvironmentInfo
127+
from .impl import Communication, CONFIGS, TestLogEntry, TestParameters
128+
121129
if n_clients is None:
122130
n_clients = DEFAULT_N_CLIENTS
123131
if any(c < 0 for c in n_clients):
@@ -339,15 +347,15 @@ def setup_benchmark_cmdline(subparsers: argparse._SubParsersAction) -> None:
339347
type=str,
340348
default=None,
341349
nargs="*",
342-
help=f"communication strategies to test (default = {[c.value for c in DEFAULT_COMMS]})",
350+
help=f"communication strategies to test (default = {DEFAULT_COMMS})",
343351
)
344352

345353
p_run.add_argument(
346354
"--configs",
347355
type=str,
348356
default=None,
349357
nargs="*",
350-
help=f"configurations to test (default = {[c for c in CONFIGS]})",
358+
help=f"configurations to test (default = {DEFAULT_CONFIGS})",
351359
)
352360

353361
p_run.add_argument(

0 commit comments

Comments
 (0)