From c4ae88e76eb9bfeba874002e7734d0c7401e5341 Mon Sep 17 00:00:00 2001 From: CharlesKWON Date: Sat, 18 Apr 2026 13:59:04 +0900 Subject: [PATCH] perf(fivesql2): gate CTE __cte_*.dbf cleanup on legacy disk fallback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CTE tables now materialise via MEMRDD (no file on disk), yet the RunSelect cleanup loop was still stat-ing __cte_.dbf for every CTE in every CTE query. Profile after the FetchRow rewrite pinned HbFileExists at 20.28% of total CPU — pure waste when MEMRDD is the common path. Add s_lCteDiskSeen flag, set only when the legacy DBFNTX fallback in RunSelect actually opens a pre-existing __cte_.dbf (line 1247 path — rare, only for sub-executors referencing a CTE by name on a crashed-prior-run .dbf). Cleanup runs only when the flag is set. pprof delta (full bench with cache enabled): rawsyscalln: 25.56% → 8.50% (~17 points removed) HbFileExists: 20.28% → 0% (dropped out of top) Wall-clock unchanged (ENOENT stats are kernel-cached on Darwin), but this removes the last visible avoidable syscall. What's left in the profile (kevent, madvise, pthread_cond_*) is Go runtime + scheduler overhead that application code can't touch. FiveSql2 43/43, Harbour compat 56/56. Co-Authored-By: Claude Opus 4.7 (1M context) --- _FiveSql2/src/TSqlExecutor.prg | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/_FiveSql2/src/TSqlExecutor.prg b/_FiveSql2/src/TSqlExecutor.prg index be0c090..1f0b7d8 100644 --- a/_FiveSql2/src/TSqlExecutor.prg +++ b/_FiveSql2/src/TSqlExecutor.prg @@ -18,6 +18,11 @@ STATIC s_aOuterStack := {} STATIC s_hAutoInc := NIL STATIC s_nRCJSeq := 0 +/* Set .T. the first time CTE cleanup sees a legacy __cte_.dbf + * file on disk, or the legacy DBFNTX open path fires. Profile showed + * the stat loop at ~20% of total CPU otherwise — MEMRDD is the norm + * for CTEs so the .dbf doesn't exist and the stat is pure overhead. */ +STATIC s_lCteDiskSeen := .F. /* Per-plan DML pcode cache. Keyed by the plan-cache key that TFiveSQL * uses (template key or cSQL text); value is a hash: @@ -1245,6 +1250,7 @@ METHOD RunSelect() CLASS TSqlExecutor nWA := 0 END SEQUENCE IF nWA == 0 .AND. hb_FileExists( "__cte_" + Lower( cTable ) + ".dbf" ) + s_lCteDiskSeen := .T. BEGIN SEQUENCE dbUseArea( .T., "DBFNTX", "__cte_" + Lower( cTable ) + ".dbf", ; cAlias, .T., .T. ) @@ -1640,9 +1646,14 @@ METHOD RunSelect() CLASS TSqlExecutor dbSelectArea( nWA ) dbCloseArea() ENDIF - cTable := "__cte_" + Lower( ::hQuery[ "cte" ][ i ][ 1 ] ) - IF hb_FileExists( cTable + ".dbf" ) - FErase( cTable + ".dbf" ) + /* Legacy disk fallback cleanup — only runs when a __cte_*.dbf + * has actually been seen (either from a prior crash or a + * MEMRDD-failure legacy open). MEMRDD-only runs skip the stat. */ + IF s_lCteDiskSeen + cTable := "__cte_" + Lower( ::hQuery[ "cte" ][ i ][ 1 ] ) + IF hb_FileExists( cTable + ".dbf" ) + FErase( cTable + ".dbf" ) + ENDIF ENDIF NEXT ENDIF