Skip to content

Commit e668acc

Browse files
committed
make benchmark scripts gh actions ready.
1 parent 8c31b17 commit e668acc

8 files changed

Lines changed: 416 additions & 424 deletions

File tree

‎.github/workflows/run_benchmark.yml‎

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ jobs:
77
benchmark:
88
runs-on: ubuntu-latest
99

10+
env:
11+
# Make token available to scripts
12+
REPLICATE_API_TOKEN: ${{ secrets.REPLICATE_API_TOKEN }}
13+
1014
steps:
1115
- name: Checkout repository
1216
uses: actions/checkout@v5
@@ -23,20 +27,31 @@ jobs:
2327
2428
- name: Run all benchmark scripts
2529
run: |
26-
BENCH_DIR="/workspaces/quantized-containerized-models/benchmark"
30+
BENCH_DIR="./benchmark"
31+
RESULTS_DIR="./benchmark/results"
32+
33+
mkdir -p "$RESULTS_DIR"
34+
2735
echo "Running benchmarks in: $BENCH_DIR"
2836
37+
# Run each benchmark script and ensure results get saved
2938
find "$BENCH_DIR" -type f -name "benchmark.py" | while read script; do
3039
echo "=============================================="
3140
echo "Executing: $script"
3241
echo "=============================================="
42+
43+
# Ensure each script can detect output directory
44+
RESULTS_ENV="BENCHMARK_OUTPUT_DIR=$RESULTS_DIR"
45+
46+
# Run the benchmark with env vars applied
47+
REPLICATE_API_TOKEN="$REPLICATE_API_TOKEN" \
48+
BENCHMARK_OUTPUT_DIR="$RESULTS_DIR" \
3349
python "$script"
3450
done
3551
3652
- name: Upload all benchmark results
3753
uses: actions/upload-artifact@v4
3854
with:
3955
name: benchmark-results
40-
path: |
41-
/quantized-containerized-models/benchmark
56+
path: benchmark/results
4257
if-no-files-found: warn

‎Makefile‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ deployment: ## Run deployment tests
112112
# CI → Unit+Linting tests only
113113
# ----------------------------------------
114114
.PHONY: ci
115-
ci: lint unit
115+
ci: lint unit
116116

117117

118118
# ----------------------------------------
Lines changed: 83 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,56 @@
1-
import replicate
1+
import os
22
import time
33
import json
44
import logging
55
from datetime import datetime
6+
from pathlib import Path
7+
8+
import replicate
9+
10+
11+
# ============================================================
12+
# Output directory (for GitHub Actions artifacts)
13+
# ============================================================
14+
OUTPUT_DIR = Path(os.getenv("BENCHMARK_OUTPUT_DIR", "benchmark_results_flux_text2img"))
15+
OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
16+
17+
LOG_FILE = OUTPUT_DIR / "benchmark_flux_lora_text2img.log"
618

7-
# ---------------------------------------------------------
8-
# Logging Setup
9-
# ---------------------------------------------------------
1019
logging.basicConfig(
1120
level=logging.INFO,
1221
format="%(asctime)s - %(levelname)s - %(message)s",
13-
handlers=[logging.FileHandler("benchmark_flux_lora_text2img.log"), logging.StreamHandler()],
22+
handlers=[logging.FileHandler(LOG_FILE), logging.StreamHandler()],
1423
)
1524
logger = logging.getLogger(__name__)
1625

1726

18-
# ---------------------------------------------------------
27+
# ============================================================
1928
# Benchmark Function
20-
# ---------------------------------------------------------
29+
# ============================================================
2130
def benchmark_flux_lora_text2img(
2231
num_runs=3,
2332
prompt="A majestic dragon soaring above a futuristic city.",
2433
trigger_word="Painting",
2534
):
2635
"""
27-
Benchmark for Flux Fast LoRA (text-to-image) variant.
28-
Only uses prompt + trigger_word as required by schema.
36+
Benchmark Flux Fast LoRA (text → image).
37+
Only uses: prompt + trigger_word (schema compliant).
2938
"""
3039

3140
deployment_id = (
3241
"paragekbote/flux-fast-lora-hotswap:"
3342
"a958687317369721e1ce66e5436fa989bcff2e40a13537d9b4aa4c6af4a34539"
3443
)
3544

36-
# Schema-compliant input
45+
# Replicate client using secure API token (required)
46+
client = replicate.Client(api_token=os.environ["REPLICATE_API_TOKEN"])
47+
3748
input_params = {
3849
"prompt": prompt,
3950
"trigger_word": trigger_word,
4051
}
4152

53+
# Header logging
4254
logger.info("=" * 90)
4355
logger.info("FLUX FAST LORA (TEXT → IMAGE) BENCHMARK")
4456
logger.info("=" * 90)
@@ -50,44 +62,45 @@ def benchmark_flux_lora_text2img(
5062

5163
results = {
5264
"deployment_id": deployment_id,
53-
"deployment_name": "Flux-Fast-LoRA-Text2Img",
65+
"deployment_name": "flux-fast-lora-text2img",
5466
"timestamp": datetime.now().isoformat(),
5567
"input_params": input_params,
5668
"runs": [],
5769
}
5870

5971
run_times = []
6072

61-
# ---------------------------------------------------------
73+
# ============================================================
6274
# Execute Runs
63-
# ---------------------------------------------------------
75+
# ============================================================
6476
for run_num in range(1, num_runs + 1):
6577
logger.info(f"--- Run {run_num}/{num_runs} ---")
6678

6779
try:
6880
start = time.time()
6981

70-
# Replicate returns a File object for images
71-
output_file = replicate.run(deployment_id, input=input_params)
82+
# Replicate returns a single File object for image output
83+
output_file = client.run(deployment_id, input=input_params)
84+
85+
# Read image bytes
7286
img_bytes = output_file.read()
7387

7488
elapsed = time.time() - start
7589
run_times.append(elapsed)
7690

77-
# Save to disk
78-
out_path = f"flux_lora_text2img_run_{run_num}.png"
79-
with open(out_path, "wb") as f:
80-
f.write(img_bytes)
91+
# Save image output
92+
img_path = OUTPUT_DIR / f"flux_lora_text2img_run_{run_num}.png"
93+
img_path.write_bytes(img_bytes)
8194

8295
logger.info(f"✓ Completed in {elapsed:.2f}s")
83-
logger.info(f" Generated: {out_path}")
96+
logger.info(f" Generated: {img_path}")
8497
logger.info(f" URL: {output_file.url()}")
8598

8699
results["runs"].append(
87100
{
88101
"run_number": run_num,
89102
"elapsed_time": elapsed,
90-
"output_file": out_path,
103+
"output_file": str(img_path),
91104
"file_url": output_file.url(),
92105
"status": "success",
93106
}
@@ -97,85 +110,91 @@ def benchmark_flux_lora_text2img(
97110
err = str(e)
98111
logger.error(f"✗ Run failed: {err}")
99112

100-
results["runs"].append({
101-
"run_number": run_num,
102-
"status": "failed",
103-
"error": err
104-
})
113+
results["runs"].append(
114+
{
115+
"run_number": run_num,
116+
"status": "failed",
117+
"error": err,
118+
}
119+
)
105120

106-
# ---------------------------------------------------------
121+
# ============================================================
107122
# Statistics
108-
# ---------------------------------------------------------
123+
# ============================================================
109124
if run_times:
110-
avg_t = sum(run_times) / len(run_times)
111-
min_t = min(run_times)
112-
max_t = max(run_times)
125+
avg_time = sum(run_times) / len(run_times)
126+
min_time = min(run_times)
127+
max_time = max(run_times)
113128

114-
std = (sum((t - avg_t) ** 2 for t in run_times) / len(run_times)) ** 0.5
115-
cv = (std / avg_t * 100) if avg_t else 0
129+
std_dev = (sum((t - avg_time) ** 2 for t in run_times) / len(run_times)) ** 0.5
130+
cv = (std_dev / avg_time * 100) if avg_time else 0
116131

117-
cold = run_times[0]
118-
warm = run_times[1:]
119-
warm_avg = sum(warm) / len(warm) if warm else None
132+
cold_start = run_times[0]
133+
warm_times = run_times[1:]
134+
warm_avg = sum(warm_times) / len(warm_times) if warm_times else None
120135

121136
results["statistics"] = {
122137
"successful_runs": len(run_times),
123138
"failed_runs": num_runs - len(run_times),
124-
"avg_latency": avg_t,
125-
"min_latency": min_t,
126-
"max_latency": max_t,
127-
"std_dev_latency": std,
139+
"avg_latency": avg_time,
140+
"min_latency": min_time,
141+
"max_latency": max_time,
142+
"std_dev_latency": std_dev,
128143
"latency_cv_percent": cv,
129-
"cold_start_latency": cold,
144+
"cold_start_latency": cold_start,
130145
"warm_avg_latency": warm_avg,
131-
"cold_vs_warm_ratio": cold / warm_avg if warm_avg else None,
146+
"cold_vs_warm_ratio": cold_start / warm_avg if warm_avg else None,
132147
}
133148

134-
# Insights
135149
insights = []
136150

137-
if warm_avg and cold > warm_avg * 1.5:
138-
insights.append(f"Cold start significantly slower ({cold:.2f}s vs warm {warm_avg:.2f}s).")
151+
if warm_avg and cold_start > warm_avg * 1.5:
152+
insights.append(
153+
f"Cold start significantly slower ({cold_start:.2f}s vs warm {warm_avg:.2f}s)."
154+
)
139155

140156
if cv < 20:
141157
insights.append(f"Stable performance (CV {cv:.1f}%).")
142158
elif cv > 50:
143159
insights.append(f"High latency variability (CV {cv:.1f}%).")
144160

145-
if avg_t < 4:
146-
insights.append("Extremely fast text-to-image generation.")
147-
elif avg_t < 8:
161+
if avg_time < 4:
162+
insights.append("Extremely fast image generation.")
163+
elif avg_time < 8:
148164
insights.append("Good generation speed.")
149165
else:
150-
insights.append("Slow generation — possible cold backend or high load.")
166+
insights.append("Slow generation — backend cold or overloaded.")
151167

152168
results["insights"] = insights
153169

154-
# Log summary
170+
# Summary log
155171
logger.info("\n" + "=" * 90)
156172
logger.info("BENCHMARK SUMMARY")
157173
logger.info("=" * 90)
158-
for k, v in results["statistics"].items():
159-
logger.info(f"{k}: {v}")
174+
175+
for key, val in results["statistics"].items():
176+
logger.info(f"{key}: {val}")
177+
160178
logger.info("\nInsights:")
161-
for i in insights:
162-
logger.info(f" • {i}")
179+
for insight in insights:
180+
logger.info(f" • {insight}")
181+
163182
logger.info("=" * 90)
164183

165-
# ---------------------------------------------------------
166-
# Save JSON
167-
# ---------------------------------------------------------
168-
with open("flux_lora_text2img_benchmark.json", "w") as f:
169-
json.dump(results, f, indent=2)
184+
# ============================================================
185+
# Save JSON Results
186+
# ============================================================
187+
json_path = OUTPUT_DIR / "flux_lora_text2img_benchmark.json"
188+
json_path.write_text(json.dumps(results, indent=2))
170189

171-
logger.info("\n✓ Saved: flux_lora_text2img_benchmark.json")
172-
logger.info("✓ Logs: benchmark_flux_lora_text2img.log\n")
190+
logger.info(f"\n✓ JSON saved to {json_path}")
191+
logger.info(f"✓ Logs saved to {LOG_FILE}\n")
173192

174193
return results
175194

176195

177-
# ---------------------------------------------------------
178-
# Run the benchmark
179-
# ---------------------------------------------------------
196+
# ============================================================
197+
# Execute
198+
# ============================================================
180199
if __name__ == "__main__":
181200
benchmark_flux_lora_text2img(num_runs=3)

0 commit comments

Comments
 (0)