Draw multi-subplot, multi-group, multi-metric bar charts for time/cpu_time/different payload sizes. Generate separate plots for sync/async and session/non-session combinations.
(df, filename)
| 255 | |
| 256 | |
| 257 | def plot_benchmark_multi(df, filename): |
| 258 | """ |
| 259 | Draw multi-subplot, multi-group, multi-metric bar charts for time/cpu_time/different payload sizes. |
| 260 | Generate separate plots for sync/async and session/non-session combinations. |
| 261 | """ |
| 262 | # Keep only necessary columns |
| 263 | df = df[["name", "session", "threads", "size", "time", "cpu_time"]].copy() |
| 264 | df["threads"] = df["threads"].fillna(1).astype(int) |
| 265 | |
| 266 | # Get unique session types |
| 267 | existing_session_types = df["session"].unique() |
| 268 | |
| 269 | sizes = sorted(df["size"].unique(), key=lambda x: int(x.replace("k", ""))) |
| 270 | stat_types = ["time", "cpu_time"] |
| 271 | |
| 272 | # Separate main sessions (non-threaded) and threaded sessions |
| 273 | main_sessions = [s for s in existing_session_types if not s.startswith("Threaded")] |
| 274 | threaded_sessions = [s for s in existing_session_types if s.startswith("Threaded")] |
| 275 | |
| 276 | # Plot main sessions (sync and async) |
| 277 | if main_sessions: |
| 278 | num_sessions = len(main_sessions) |
| 279 | # Allocate more height for each subplot to ensure sufficient spacing |
| 280 | subplot_height = 8 # Fixed height for each subplot |
| 281 | total_height = subplot_height * num_sessions + 2 # Extra 2 inches for spacing |
| 282 | |
| 283 | fig, axes = plt.subplots( |
| 284 | num_sessions, |
| 285 | 1, |
| 286 | figsize=(20, total_height), |
| 287 | constrained_layout=False, # Disable constrained_layout, use manual layout |
| 288 | ) |
| 289 | |
| 290 | if num_sessions == 1: |
| 291 | axes = [axes] |
| 292 | |
| 293 | for idx, session in enumerate(main_sessions): |
| 294 | ax = axes[idx] |
| 295 | subdf = df[df["session"] == session] |
| 296 | names = subdf["name"].unique() |
| 297 | x = np.arange(len(names)) |
| 298 | width = 0.12 |
| 299 | |
| 300 | max_height = 0 |
| 301 | |
| 302 | for i, size in enumerate(sizes): |
| 303 | for j, stat in enumerate(stat_types): |
| 304 | vals = [] |
| 305 | for name in names: |
| 306 | v = subdf[(subdf["name"] == name) & (subdf["size"] == size)][ |
| 307 | stat |
| 308 | ] |
| 309 | vals.append(v.values[0] if not v.empty else 0) |
| 310 | offset = (i * len(stat_types) + j) * width |
| 311 | rects = ax.bar(x + offset, vals, width, label=f"{stat} {size}") |
| 312 | ax.bar_label(rects, padding=2, fontsize=7, rotation=90) |
| 313 | if vals: |
| 314 | max_height = max(max_height, max(vals)) |