(raw, data, sizes, output_dir: Path, plot_prefix: str)
| 232 | |
| 233 | |
| 234 | def generate_markdown_report(raw, data, sizes, output_dir: Path, plot_prefix: str): |
| 235 | context = raw.get("context", {}) |
| 236 | system_info = get_system_info() |
| 237 | |
| 238 | if context.get("python_implementation"): |
| 239 | system_info["Python Implementation"] = context["python_implementation"] |
| 240 | if context.get("platform"): |
| 241 | system_info["Benchmark Platform"] = context["platform"] |
| 242 | |
| 243 | datatypes = [dt for dt in DATATYPE_ORDER if dt in data] |
| 244 | operations = ["serialize", "deserialize"] |
| 245 | |
| 246 | md = [ |
| 247 | "# Python Benchmark Performance Report\n\n", |
| 248 | f"_Generated on {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}_\n\n", |
| 249 | "## How to Generate This Report\n\n", |
| 250 | "```bash\n", |
| 251 | "cd benchmarks/python\n", |
| 252 | "./run.sh\n", |
| 253 | "```\n\n", |
| 254 | "## Benchmark Plot\n\n", |
| 255 | "The plot shows throughput (ops/sec); higher is better.\n\n", |
| 256 | f"\n\n", |
| 257 | "## Hardware & OS Info\n\n", |
| 258 | "| Key | Value |\n", |
| 259 | "|-----|-------|\n", |
| 260 | ] |
| 261 | |
| 262 | for key, value in system_info.items(): |
| 263 | md.append(f"| {key} | {value} |\n") |
| 264 | |
| 265 | md.append("\n## Benchmark Configuration\n\n") |
| 266 | md.append("| Key | Value |\n") |
| 267 | md.append("|-----|-------|\n") |
| 268 | for key in ["warmup", "iterations", "repeat", "number", "list_size"]: |
| 269 | if key in context: |
| 270 | md.append(f"| {key} | {context[key]} |\n") |
| 271 | |
| 272 | md.append("\n## Benchmark Results\n\n") |
| 273 | md.append("### Timing Results (nanoseconds)\n\n") |
| 274 | timing_headers = [ |
| 275 | f"{SERIALIZER_LABELS.get(lib, lib)} (ns)" for lib in SERIALIZER_ORDER |
| 276 | ] |
| 277 | md.append( |
| 278 | "| Datatype | Operation | " + " | ".join(timing_headers) + " | Fastest |\n" |
| 279 | ) |
| 280 | md.append( |
| 281 | "|----------|-----------|" |
| 282 | + "|".join("-" * (len(header) + 2) for header in timing_headers) |
| 283 | + "|---------|\n" |
| 284 | ) |
| 285 | |
| 286 | for datatype in datatypes: |
| 287 | for operation in operations: |
| 288 | times = { |
| 289 | lib: data.get(datatype, {}).get(operation, {}).get(lib, 0) |
| 290 | for lib in SERIALIZER_ORDER |
| 291 | } |
no test coverage detected