null, 'suite' => null, 'level' => null, 'model' => null, 'result' => null, ]; private const SORTABLE = [ 'ran_at', 'model_id', 'suite', 'task', 'level', 'ok', 'decode', 'user_tps', 'ttft', 't_answer', 'wall', 'total', ]; public function resetFilters(): void { $this->filters = [ 'search' => null, 'suite' => null, 'level' => null, 'model' => null, 'result' => null, ]; $this->resetPage(); } #[Computed] public function results(): LengthAwarePaginator { $ttl = (int) config('festbench.home_cache_ttl', 300); $user = auth()->user(); // Guest + public-only views are cacheable; any logged-in view may // embed private rows, so it gets a user-scoped key instead. $cacheKey = 'home:'.($user?->id ?? 'guest').':'.md5(json_encode([$this->filters, $this->sortBy, $this->sortDirection, $this->getPage()])); return Cache::remember($cacheKey, $ttl, function () use ($user) { // Default guest view (no filters, no custom sort): the flat // precomputed snapshot — no UNION runs at request time. if ($user === null && $this->isDefaultView()) { return DB::table('home_snapshot')->orderBy('sequence')->paginate(25); } $query = $this->baseQuery($user) ->tap(fn ($q) => $this->applySorting($q)) ->tap(fn ($q) => $this->applyFilters($q)); return $query->paginate(25); }); } private function isDefaultView(): bool { return ($this->sortBy === null || $this->sortBy === 'ran_at') && $this->sortDirection === 'desc' && collect($this->filters)->filter(fn ($v) => $v !== null && $v !== '')->isEmpty() && $this->getPage() === 1; } /** * The combined query. Suite filter unset → the all_results view (one * UNION plan for everything); suite filter set → the concrete suite * table directly (full indexes, no union). */ private function baseQuery($user) { $suite = $this->filters['suite']; $model = $suite !== null && $suite !== '' ? Suites::modelFor($suite) : null; $source = $model !== null ? $model::query()->getModel()->getTable() : 'all_results'; // The concrete suite tables have no suite column; promote it so the // view renders identically for both query paths. $select = $model !== null ? "{$source}.*, '{$suite}' AS suite" : "{$source}.*"; return DB::table($source) ->join('benchmark_runs', 'benchmark_runs.id', '=', "{$source}.benchmark_run_id") ->selectRaw($select) ->addSelect( 'benchmark_runs.model_id', 'benchmark_runs.model_quant', 'benchmark_runs.engine', 'benchmark_runs.run_id', 'benchmark_runs.visibility', 'benchmark_runs.user_id as run_user_id') ->where(BenchmarkRun::visibleClause($user)); } #[Computed] public function suites(): array { return Cache::remember('home:suites', 300, fn () => Suites::active()->all()); } #[Computed] public function models(): array { return Cache::remember('home:models', 300, function () { return BenchmarkRun::visibleTo(auth()->user()) ->distinct()->orderBy('model_id')->pluck('model_id')->all(); }); } private function applySorting($query) { $column = in_array($this->sortBy, self::SORTABLE, true) ? $this->sortBy : 'ran_at'; $source = $this->filters['suite'] !== null && $this->filters['suite'] !== '' ? Suites::modelFor($this->filters['suite'])::make()->getTable() : 'all_results'; return $query->orderBy($column, $this->sortDirection === 'asc' ? 'asc' : 'desc') ->orderBy("{$source}.id", 'desc'); } private function applyFilters($query) { $source = $this->filters['suite'] !== null && $this->filters['suite'] !== '' ? Suites::modelFor($this->filters['suite'])::make()->getTable() : 'all_results'; return $query ->when($this->filters['search'], fn ($q, string $search) => $q->where(function ($q) use ($search, $source) { $q->where("{$source}.task", 'like', "%{$search}%") ->orWhere('benchmark_runs.model_id', 'like', "%{$search}%") ->orWhere('benchmark_runs.label', 'like', "%{$search}%"); })) ->when($this->filters['level'], fn ($q, string $level) => $q->where("{$source}.level", $level)) ->when($this->filters['model'], fn ($q, string $model) => $q->where('benchmark_runs.model_id', $model)) ->when($this->filters['result'] !== null && $this->filters['result'] !== '', fn ($q) => $q->where("{$source}.ok", (bool) $this->filters['result'])); } }; ?>
{{ __('All Task Rows') }} {{ __('Every datapoint festbench captures — sortable.') }}
{{ __('Session summary') }}
{{ __('All suites') }} @foreach ($this->suites as $suite) {{ $suite }} @endforeach {{ __('All levels') }} @foreach (['off', 'low', 'medium', 'xhigh'] as $level) {{ $level }} @endforeach {{ __('All models') }} @foreach ($this->models as $model) {{ $model }} @endforeach {{ __('Any') }} {{ __('Pass') }} {{ __('Fail') }} {{ __('Clear') }}
@if ($this->results->count() > 0)
{{ __('Date') }} {{ __('Model') }} {{ __('Suite') }} {{ __('Task') }} {{ __('Level') }} {{ __('Pass') }} {{ __('User tok/s') }} {{ __('Decode') }} {{ __('TTFT') }} {{ __('Wall') }} {{ __('Tokens') }} @foreach ($this->results as $result) {{ optional($result->ran_at)->format('Y-m-d') }} {{ $result->model_id }} @if ($result->model_quant) {{ $result->model_quant }} @endif {{ $result->suite }} {{ $result->task }} {{ $result->level ?? '—' }} @if ($result->ok) @elseif ($result->ok === null) — @else @endif {{ number_format($result->user_tps, 1) }} {{ number_format($result->decode, 1) }} {{ number_format($result->ttft, 2) }} {{ number_format($result->wall, 2) }} {{ number_format($result->total) }} @endforeach
@else
{{ __('No results') }} {{ __('No benchmark results match the current filters.') }}
@endif