Do not make the trustlet re-read the whole template on every claim
Selecting a group makes the trustlet reload every template in it from storage, and on this device that is 651276 bytes crossing the listener in chunks. Measured over ten verifications: eleven claims, eleven reloads, fifty-four chunk reads, twenty-six megabytes of round trips. All of it happens before the verify loop starts, so all of it lands in the latency a user feels while being invisible to the daemon's own timing -- which is how it survived this long. It is also unnecessary. The trustlet holds templates in memory once loaded; a successful authentication on stock produces no storage callbacks at all. A group that is already active does not need selecting again, so a repeat claim now answers from what the last real selection reported. Enrolment forces a real selection, because it adds a template and the reload is the point. Measured after: two claims, one real selection, one skipped, and the chunk reads drop from five per claim to two for the pair.
This commit is contained in:
parent
eb50e5b6fb
commit
231a1860ac
1 changed files with 25 additions and 3 deletions
|
|
@ -1206,8 +1206,25 @@ public:
|
||||||
|
|
||||||
// Select a group and count what loads. A template reload needs the init
|
// Select a group and count what loads. A template reload needs the init
|
||||||
// chain to have run first -- Start() guarantees that.
|
// chain to have run first -- Start() guarantees that.
|
||||||
int SetActiveGroup(std::uint32_t gid) {
|
// Selecting a group makes the trustlet RELOAD every template in it from
|
||||||
|
// storage, and on this device that is 651276 bytes crossing the listener in
|
||||||
|
// chunks -- about a megabyte of round trips per call. Measured 2026-09-05:
|
||||||
|
// ten verifications cost eleven reloads and 26 MB, all of it before the
|
||||||
|
// verify loop even starts, so all of it lands in the latency the user sees
|
||||||
|
// while being invisible to the daemon's own timing.
|
||||||
|
//
|
||||||
|
// It is also unnecessary. The trustlet holds templates in memory once
|
||||||
|
// loaded -- a successful authentication on stock produces no storage
|
||||||
|
// callbacks at all -- so a group that is already active does not need
|
||||||
|
// selecting again. `force` is for the cases that genuinely change the
|
||||||
|
// store: an enrolment, or a template removed underneath us.
|
||||||
|
int SetActiveGroup(std::uint32_t gid, bool force = false) {
|
||||||
namespace ta = fingerprintd::ta;
|
namespace ta = fingerprintd::ta;
|
||||||
|
if (!force && gid == gid_ && templatesLoaded_ >= 0) {
|
||||||
|
std::println("SET_ACTIVE_GROUP gid={} skipped (already active, {} template(s))",
|
||||||
|
gid, templatesLoaded_);
|
||||||
|
return templatesLoaded_;
|
||||||
|
}
|
||||||
auto sag = ta::BuildSetActiveGroup(gid, g_groupPath);
|
auto sag = ta::BuildSetActiveGroup(gid, g_groupPath);
|
||||||
std::println("SET_ACTIVE_GROUP gid={}", gid);
|
std::println("SET_ACTIVE_GROUP gid={}", gid);
|
||||||
auto g = SendCommand(app_, ta::Cmd::SetActiveGroup, sag);
|
auto g = SendCommand(app_, ta::Cmd::SetActiveGroup, sag);
|
||||||
|
|
@ -1216,7 +1233,8 @@ public:
|
||||||
Report(ta::Cmd::Enumerate, e);
|
Report(ta::Cmd::Enumerate, e);
|
||||||
std::println(" templates loaded: {}", e.rc);
|
std::println(" templates loaded: {}", e.rc);
|
||||||
gid_ = gid;
|
gid_ = gid;
|
||||||
return e.invoked ? e.rc : -1;
|
templatesLoaded_ = e.invoked ? e.rc : -1;
|
||||||
|
return templatesLoaded_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---- Enrolment
|
// ---- Enrolment
|
||||||
|
|
@ -1244,7 +1262,8 @@ public:
|
||||||
out.why = "store is read-only or RPMB writes disabled";
|
out.why = "store is read-only or RPMB writes disabled";
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
if (gid != gid_) SetActiveGroup(gid);
|
// An enrolment adds a template, so this one reloads for real.
|
||||||
|
SetActiveGroup(gid, /*force*/ true);
|
||||||
|
|
||||||
// Stock's opening sequence. AUTHENTICATE is what arms the capture
|
// Stock's opening sequence. AUTHENTICATE is what arms the capture
|
||||||
// session; CANCEL and RESET_LOCKOUT bracket it.
|
// session; CANCEL and RESET_LOCKOUT bracket it.
|
||||||
|
|
@ -1755,6 +1774,9 @@ private:
|
||||||
Sensor sensor_;
|
Sensor sensor_;
|
||||||
fingerprintd::engine::Baseline baseline_;
|
fingerprintd::engine::Baseline baseline_;
|
||||||
std::uint32_t gid_ = 0xFFFFFFFF;
|
std::uint32_t gid_ = 0xFFFFFFFF;
|
||||||
|
// What the last real SET_ACTIVE_GROUP reported, so a repeat claim can be
|
||||||
|
// answered without making the trustlet re-read the store. -1 = unknown.
|
||||||
|
int templatesLoaded_ = -1;
|
||||||
// Set when a fold succeeded; cleared by the save.
|
// Set when a fold succeeded; cleared by the save.
|
||||||
bool templateDirty_ = false;
|
bool templateDirty_ = false;
|
||||||
// Frames folded during the verify loop itself, carried into the harvest so
|
// Frames folded during the verify loop itself, carried into the harvest so
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue