Vorübergehend messen, woher die anderthalb Sekunden der Akte kommen
Some checks failed
CI / Migrationen auf leerer Datenbank (push) Has been cancelled
CI / Lint, Typen, Tests, Build (push) Has started running

Die Akte braucht beim Oeffnen rund 1,5 s. Die Datenbank ist es dem
Anschein nach nicht: eine Rundreise kostet 0,5 ms (nicht 36, wie der
Kommentar hier behauptete), und om_reporting_lines misst 60 ms. Damit
laegen unter zehn Prozent der Zeit in den Abfragen.

Statt weiter zu raten -- heute schon zweimal danebengelegen -- schreibt
loadEmployeeDetail eine Zeile ins Protokoll des Containers: Zeit fuer die
Person, fuer die Hauptabfrage, fuer die Nachschlaege, insgesamt, und wie
viele Berichtslinien uebertragen wurden.

Wieder entfernen, sobald die Ursache feststeht.
This commit is contained in:
2026-09-24 11:52:36 +02:00
parent 499d400fe1
commit c8f9ae8047

View File

@@ -19,7 +19,21 @@ import { offeneStellenAbfrage, resolveOpenPositions, type OffeneStelle } from ".
// darüber, was später passiert ist. Ausgeschrieben ist sichtbar, welche Spalte // darüber, was später passiert ist. Ausgeschrieben ist sichtbar, welche Spalte
// durch zeitstempel() geht — bei selectAll() wäre es unsichtbar falsch. // durch zeitstempel() geht — bei selectAll() wäre es unsichtbar falsch.
// ── Vorübergehende Messung ────────────────────────────────────────
//
// Die Akte braucht beim Öffnen rund anderthalb Sekunden, und es ist unklar,
// wovon. Die Datenbank ist es dem Anschein nach nicht: eine Rundreise kostet
// 0,5 ms, om_reporting_lines 60 ms. Statt weiter zu raten, misst diese Zeile
// die drei Abschnitte und schreibt eine Zeile ins Protokoll des Containers.
//
// **Wieder entfernen**, sobald die Ursache feststeht.
function messen(id: string, marken: [string, number][]) {
const teile = marken.map(([name, ms]) => `${name} ${Math.round(ms)}ms`).join(", ");
console.info(`[Akte ${id.slice(0, 8)}] ${teile}`);
}
export async function loadEmployeeDetail(tx: Tx, id: string, today: string = todayIso()) { export async function loadEmployeeDetail(tx: Tx, id: string, today: string = todayIso()) {
const t0 = performance.now();
// Die Person zuerst, allein: erst aus Eintritt und Austritt ergibt sich der // Die Person zuerst, allein: erst aus Eintritt und Austritt ergibt sich der
// Stichtag, zu dem ihre Organisation überhaupt eine Antwort hat. Eine // Stichtag, zu dem ihre Organisation überhaupt eine Antwort hat. Eine
// Person, die am 01.09. anfängt, hat heute keine laufende Besetzung — zu // Person, die am 01.09. anfängt, hat heute keine laufende Besetzung — zu
@@ -27,6 +41,7 @@ export async function loadEmployeeDetail(tx: Tx, id: string, today: string = tod
// behauptete „Keine Führungskraft", obwohl das Team eine hat. // behauptete „Keine Führungskraft", obwohl das Team eine hat.
const employee = await tx.selectFrom("employees").selectAll().where("id", "=", id).executeTakeFirst(); const employee = await tx.selectFrom("employees").selectAll().where("id", "=", id).executeTakeFirst();
if (!employee) return null; if (!employee) return null;
const t1 = performance.now();
const asOf = orgAsOf(employee, today); const asOf = orgAsOf(employee, today);
@@ -121,6 +136,8 @@ export async function loadEmployeeDetail(tx: Tx, id: string, today: string = tod
]) ])
.executeTakeFirstOrThrow(); .executeTakeFirstOrThrow();
const t2 = performance.now();
const orgMaps = buildOrgMaps(g.units as never, g.locations as never); const orgMaps = buildOrgMaps(g.units as never, g.locations as never);
const line = g.lines.find((l) => l.employee_id === id) ?? null; const line = g.lines.find((l) => l.employee_id === id) ?? null;
const reports = g.lines.filter((l) => l.acting_manager_id === id); const reports = g.lines.filter((l) => l.acting_manager_id === id);
@@ -147,6 +164,15 @@ export async function loadEmployeeDetail(tx: Tx, id: string, today: string = tod
resolveOpenPositions(tx, orgMaps, g.open as OffeneStelle[], today), resolveOpenPositions(tx, orgMaps, g.open as OffeneStelle[], today),
]); ]);
const t3 = performance.now();
messen(id, [
["person", t1 - t0],
["hauptabfrage", t2 - t1],
["nachschlag", t3 - t2],
["gesamt", t3 - t0],
["zeilen", g.lines.length],
]);
return { return {
employee, employee,
line, line,