From a0166367cd5778de4a14cd44b5b38241165c11ac Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Thu, 13 Aug 2026 19:03:25 -0400 Subject: [PATCH] perf: drop the S (startup) flag from the hand-authored baseline profile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The wildcards added in #3918 were written HSPL — hot + startup + post-startup — on whole packages (quartz, LocalCache, Jackson, okhttp, okio, coroutines). The S was wrong and potentially harmful. S drives DEX layout: startup-flagged classes are grouped into classes.dex for locality, and Android's docs warn that if startup code does not fit there it "will overflow into the next DEX files". Claiming thousands of ingest methods are startup-critical can push genuinely startup-critical code out of the first DEX — hurting the thing the profile is meant to help. For scale, the generated profile marks 32 of its 31,497 rules HSPL; this file claimed it for all 25 of its rules, each covering an entire package. Ingest runs AFTER startup, so HP is what this file actually knows. Startup layout is left to the generated profile (#3919). Re-measured on device (SM-T220, release build, simpleperf --app), share of DefaultDispatcher worker CPU: no profile HSPL HPL nterp 42.9% 4.2% 4.0% app compiled 11.0% 20.8% 21.9% GC read barriers 9.4% 6.7% 6.6% class/method lookup 2.8% 0.3% 0.1% Ingest throughput (RSS growth per unit of CPU): no profile 8.9 MB per core-second HSPL 14.5 HPL 15.8 (n=4, range 14.6-18.4) So dropping S costs nothing — as expected, since S affects DEX layout rather than which methods get compiled. The compiled profile is marginally smaller (16,341 -> 15,532 bytes). The HPL-vs-HSPL numbers are within the noise of these arms (the HPL range alone spans 14.6-18.4), so read this as "no regression", not as an improvement. Co-Authored-By: Claude Opus 5 (1M context) --- amethyst/src/main/baseline-prof.txt | 61 +++++++++++++++++------------ 1 file changed, 35 insertions(+), 26 deletions(-) diff --git a/amethyst/src/main/baseline-prof.txt b/amethyst/src/main/baseline-prof.txt index 8b6b49a8a4..9c62631e80 100644 --- a/amethyst/src/main/baseline-prof.txt +++ b/amethyst/src/main/baseline-prof.txt @@ -24,39 +24,48 @@ # strictly better — it would carry call counts and startup/post-startup flags # that reflect real behaviour instead of whole-package guesses. # -# Flags: H = hot, S = startup, P = post-startup. +# Flags: HP = hot + post-startup, deliberately WITHOUT S (startup). +# +# S drives DEX layout: startup-flagged classes are grouped into classes.dex for +# locality, and Android's docs warn that if startup code does not fit there it +# "will overflow into the next DEX files". These are whole-package wildcards for +# ingest, which runs AFTER startup — flagging them S would claim thousands of +# methods are startup-critical and could push genuinely startup-critical code out +# of the first DEX, hurting the thing it is meant to help. For comparison, the +# generated profile marks 32 of its 31,497 rules HSPL; this file should not claim +# more than that about startup. Startup layout is left to the generated profile. # --- Quartz: protocol core, relay client, crypto, event kinds --- -HSPLcom/vitorpamplona/quartz/nip01Core/**->**(**)** -HSPLcom/vitorpamplona/quartz/nip10Notes/**->**(**)** -HSPLcom/vitorpamplona/quartz/nip19Bech32/**->**(**)** -HSPLcom/vitorpamplona/quartz/nip17Dm/**->**(**)** -HSPLcom/vitorpamplona/quartz/nip22Comments/**->**(**)** -HSPLcom/vitorpamplona/quartz/nip25Reactions/**->**(**)** -HSPLcom/vitorpamplona/quartz/nip18Reposts/**->**(**)** -HSPLcom/vitorpamplona/quartz/nip57Zaps/**->**(**)** -HSPLcom/vitorpamplona/quartz/nip65RelayList/**->**(**)** -HSPLcom/vitorpamplona/quartz/utils/**->**(**)** -HSPLcom/vitorpamplona/quartz/experimental/**->**(**)** +HPLcom/vitorpamplona/quartz/nip01Core/**->**(**)** +HPLcom/vitorpamplona/quartz/nip10Notes/**->**(**)** +HPLcom/vitorpamplona/quartz/nip19Bech32/**->**(**)** +HPLcom/vitorpamplona/quartz/nip17Dm/**->**(**)** +HPLcom/vitorpamplona/quartz/nip22Comments/**->**(**)** +HPLcom/vitorpamplona/quartz/nip25Reactions/**->**(**)** +HPLcom/vitorpamplona/quartz/nip18Reposts/**->**(**)** +HPLcom/vitorpamplona/quartz/nip57Zaps/**->**(**)** +HPLcom/vitorpamplona/quartz/nip65RelayList/**->**(**)** +HPLcom/vitorpamplona/quartz/utils/**->**(**)** +HPLcom/vitorpamplona/quartz/experimental/**->**(**)** # --- Amethyst: the in-memory store and the relay wiring around it --- -HSPLcom/vitorpamplona/amethyst/model/**->**(**)** -HSPLcom/vitorpamplona/amethyst/service/relayClient/**->**(**)** -HSPLcom/vitorpamplona/amethyst/service/okhttp/**->**(**)** -HSPLcom/vitorpamplona/amethyst/commons/model/**->**(**)** -HSPLcom/vitorpamplona/amethyst/commons/richtext/**->**(**)** +HPLcom/vitorpamplona/amethyst/model/**->**(**)** +HPLcom/vitorpamplona/amethyst/service/relayClient/**->**(**)** +HPLcom/vitorpamplona/amethyst/service/okhttp/**->**(**)** +HPLcom/vitorpamplona/amethyst/commons/model/**->**(**)** +HPLcom/vitorpamplona/amethyst/commons/richtext/**->**(**)** # --- JSON: every frame is parsed through Jackson --- -HSPLcom/fasterxml/jackson/core/**->**(**)** -HSPLcom/fasterxml/jackson/databind/**->**(**)** -HSPLcom/fasterxml/jackson/module/kotlin/**->**(**)** +HPLcom/fasterxml/jackson/core/**->**(**)** +HPLcom/fasterxml/jackson/databind/**->**(**)** +HPLcom/fasterxml/jackson/module/kotlin/**->**(**)** # --- Transport: the socket read path under the relay client --- -HSPLokhttp3/internal/ws/**->**(**)** -HSPLokhttp3/internal/connection/**->**(**)** -HSPLokio/**->**(**)** +HPLokhttp3/internal/ws/**->**(**)** +HPLokhttp3/internal/connection/**->**(**)** +HPLokio/**->**(**)** # --- Coroutines: every ingested event crosses the dispatcher --- -HSPLkotlinx/coroutines/scheduling/**->**(**)** -HSPLkotlinx/coroutines/channels/**->**(**)** -HSPLkotlinx/coroutines/flow/**->**(**)** +HPLkotlinx/coroutines/scheduling/**->**(**)** +HPLkotlinx/coroutines/channels/**->**(**)** +HPLkotlinx/coroutines/flow/**->**(**)**