agentsclimarketplace

Cold start optimization

Skill almasumdev/awesome-mobile-performance-agent-skills/.github/skills/startup/cold-start-optimization

Agent skills for profiling and optimizing mobile app performance (startup, memory, frame-rate, network).

Install
npx -y skills add almasumdev/awesome-mobile-performance-agent-skills --skill cold-start-optimization

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Reduce cold start time (TTID and TTFD) on iOS and Android using baseline profiles, main-thread hygiene, and selective pre-warming. Use when launch latency exceeds the budget in Agent.md.

SKILL.md

5.0 KB, as published. Nobody here has run it

Cold Start Optimization

Instructions

Optimize cold start — the scenario where the OS creates a new process and your app draws its first meaningful frame. Cold start is what app-store reviewers and lab devices measure, so it is the number that matters for reviews and rankings.

1. Define the Target Metrics

Two numbers matter:

  • TTID (Time To Initial Display) — first frame drawn. On Android this is Displayed in logcat. On iOS it is the moment UIWindow commits its first frame.
  • TTFD (Time To Full Display) — first useful frame with real data. On Android call Activity.reportFullyDrawn(). On iOS emit an os_signpost event named TTFD.

Targets (p50 device, release build):

MetriciOS budgetAndroid budget
TTID1.2 s1.5 s
TTFD2.0 s2.5 s

2. Baseline First

Before changing code, capture a baseline.

Android (Macrobenchmark):

@RunWith(AndroidJUnit4::class)
class StartupBenchmark {
  @get:Rule val rule = MacrobenchmarkRule()

  @Test fun coldStartup() = rule.measureRepeated(
      packageName = "com.example.app",
      metrics = listOf(StartupTimingMetric()),
      iterations = 10,
      startupMode = StartupMode.COLD,
  ) { pressHome(); startActivityAndWait() }
}

iOS (XCTest):

func testLaunchPerformance() {
    measure(metrics: [XCTApplicationLaunchMetric()]) {
        XCUIApplication().launch()
    }
}

3. Make the Main Thread Boring

Every millisecond before the first frame is paid on the main thread. Audit and remove:

  • Disk IO in Application.onCreate / UIApplicationDelegate.application(_:didFinishLaunchingWithOptions:).
  • Synchronous network calls, feature-flag fetches, remote-config SDK init.
  • Eager DI container construction (Hilt @EntryPoint, Swinject assembler, get_it registrations) for features not on the start screen.
  • JSON parsing of cached payloads. Defer to Dispatchers.IO / a background DispatchQueue.
  • Heavy reflection or annotation scanning (Jackson, Gson with @SerializedName at startup).

Android pattern — use Initializer from androidx.startup and disable default init for expensive libs:

class AnalyticsInitializer : Initializer<Analytics> {
  override fun create(ctx: Context): Analytics = Analytics.init(ctx)
  override fun dependencies(): List<Class<out Initializer<*>>> = emptyList()
}

iOS pattern — replace +[load] with +initialize or lazy static let. Never do work in +[load].

enum FeatureFlags {
    static let shared = FeatureFlagsClient()   // lazily created on first access
}

4. Ship a Baseline Profile (Android)

Baseline Profiles AOT-compile the hot startup path and typically reduce cold start by 15–30%.

@RunWith(AndroidJUnit4::class)
class BaselineProfileGenerator {
  @get:Rule val rule = BaselineProfileRule()

  @Test fun generate() = rule.collect(packageName = "com.example.app") {
    pressHome(); startActivityAndWait()
    device.findObject(By.res("feed")).scroll(Direction.DOWN, 0.8f)
  }
}

Commit the produced baseline-prof.txt into src/main/ and add androidx.profileinstaller.

5. Pre-warm Only What the First Frame Needs

  • iOS: prebuild the root UIView / SwiftUI View tree off the critical path using Task.detached for side data only — never for the first frame's view tree.
  • Android: in Application.onCreate, post non-critical work with Handler(Looper.getMainLooper()).post {} so it runs after first frame.
  • Flutter: use SchedulerBinding.instance.addPostFrameCallback to defer work until after the first frame; mark shell route with HeroMode(enabled: false) during launch.
  • React Native: enable Hermes; move bridge-heavy native modules to lazy registration via TurboModule on the New Architecture.

6. Splash Screen, Not Blank Window

Use the OS-provided splash APIs — SplashScreen on Android 12+, LaunchScreen.storyboard / .xcassets on iOS. A themed splash hides the process-creation window and improves perceived TTID without adding real time.

7. Measure Again, Record in CI

Add the benchmark to CI. Fail the build on > 5% regression vs a committed baseline JSON. See startup-profiling skill.

Checklist

  • TTID and TTFD budgets documented.
  • Baseline numbers captured on a p50 device in release/profile mode.
  • No disk IO, network, or JSON parsing on the main thread before first frame.
  • Expensive SDK initializers moved off the startup path (AndroidX Startup, lazy singletons).
  • Android: Baseline Profile generated and installed via androidx.profileinstaller.
  • iOS: no work in +[load]; Task.detached used for side effects only.
  • Splash theme / launch screen configured to avoid white flash.
  • CI benchmark fails on > 5% regression.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.