From 2c924c31b9d6192064e4d51cec211bcdfc8f1f2f Mon Sep 17 00:00:00 2001 From: Elton Carreiro Date: Thu, 21 May 2026 22:32:54 -0300 Subject: [PATCH] Instrument Tier B visibility cache with hit rate logging Add observability to the fb_hasVisibleDescendants short-circuit by instrumenting cache hit/miss counters. Track calls and hits using atomic operations, logging statistics every 50 calls to measure cache effectiveness without impacting performance. Include last walk depth and result in logs to aid debugging on dense screens. No behavioral changes. Co-Authored-By: Claude --- .../Categories/XCUIElement+FBIsVisible.m | 35 +++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBIsVisible.m b/WebDriverAgentLib/Categories/XCUIElement+FBIsVisible.m index 75a228a3e..c8ab86a1f 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBIsVisible.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBIsVisible.m @@ -8,7 +8,10 @@ #import "XCUIElement+FBIsVisible.h" +#import + #import "FBElementUtils.h" +#import "FBLogger.h" #import "FBXCodeCompatibility.h" #import "FBXCElementSnapshotWrapper+Helpers.h" #import "XCUIElement+FBUtilities.h" @@ -36,12 +39,40 @@ @implementation FBXCElementSnapshotWrapper (FBIsVisible) - (BOOL)fb_hasVisibleDescendants { + // PoC (poc/log-tier-b-cache-hits): observability-only. Instrument the Tier B + // short-circuit so we can measure how often it actually fires vs falls + // through to the Tier C synchronous AX-framework IPC. Counters are + // process-wide and accumulate across requests; logging every 50 calls keeps + // the output volume tractable on dense screens (500+ nodes per /source). + // No behaviour change — this PR only adds the log line. + static _Atomic NSUInteger fbVisCacheTierBCalls = 0; + static _Atomic NSUInteger fbVisCacheTierBHits = 0; + + NSUInteger descendantsWalked = 0; + BOOL hit = NO; for (id descendant in (self._allDescendants ?: @[])) { + descendantsWalked++; if ([fetchSnapshotVisibility(descendant) boolValue]) { - return YES; + hit = YES; + break; } } - return NO; + + NSUInteger calls = atomic_fetch_add(&fbVisCacheTierBCalls, 1) + 1; + if (hit) { + atomic_fetch_add(&fbVisCacheTierBHits, 1); + } + if (0 == (calls % 50)) { + NSUInteger hits = atomic_load(&fbVisCacheTierBHits); + double hitRate = 100.0 * (double)hits / (double)calls; + [FBLogger logFmt:@"[VisCache] Tier-B stats: calls=%lu hits=%lu (%.1f%%) lastWalked=%lu lastResult=%@", + (unsigned long)calls, + (unsigned long)hits, + hitRate, + (unsigned long)descendantsWalked, + hit ? @"YES" : @"NO"]; + } + return hit; } - (BOOL)fb_isVisible