Performance testing of a mobile application

NOVASOLUTIONS.TECHNOLOGY is engaged in the development, support and maintenance of iOS, Android, PWA mobile applications. We have extensive experience and expertise in publishing mobile applications in popular markets like Google Play, App Store, Amazon, AppGallery and others.
Development and support of all types of mobile applications:
Information and entertainment mobile applications
News apps, games, reference guides, online catalogs, weather apps, fitness and health apps, travel apps, educational apps, social networks and messengers, quizzes, blogs and podcasts, forums, aggregators
E-commerce mobile applications
Online stores, B2B apps, marketplaces, online exchanges, cashback services, exchanges, dropshipping platforms, loyalty programs, food and goods delivery, payment systems.
Business process management mobile applications
CRM systems, ERP systems, project management, sales team tools, financial management, production management, logistics and delivery management, HR management, data monitoring systems
Electronic services mobile applications
Classified ads platforms, online schools, online cinemas, electronic service platforms, cashback platforms, video hosting, thematic portals, online booking and scheduling platforms, online trading platforms

These are just some of the types of mobile applications we work with, and each of them may have its own specific features and functionality, tailored to the specific needs and goals of the client.

Showing 1 of 1 servicesAll 1735 services
Performance testing of a mobile application
Complex
~3-5 business days
FAQ
Our competencies:
Development stages
Latest works
  • image_mobile-applications_feedme_467_0.webp
    Development of a mobile application for FEEDME
    756
  • image_mobile-applications_xoomer_471_0.webp
    Development of a mobile application for XOOMER
    624
  • image_mobile-applications_rhl_428_0.webp
    Development of a mobile application for RHL
    1050
  • image_mobile-applications_zippy_411_0.webp
    Development of a mobile application for ZIPPY
    947
  • image_mobile-applications_affhome_429_0.webp
    Development of a mobile application for Affhome
    862
  • image_mobile-applications_flavors_409_0.webp
    Development of a mobile application for the FLAVORS company
    445

Performance Testing of Mobile Application

App works fine on iPhone 15 Pro. On Xiaomi Redmi 10A with Android 11, which a third of audience uses, main screen loads 4 seconds, and list with fast scroll stutters down to 20 fps. Firebase Crashlytics won't show — not a crash. App Store Reviews will show after a week of release.

Performance profiling is not just running and looking. It's reproducible measurements with specific numbers, before/after comparison, root cause localization to specific method.

iOS: Xcode Instruments

Instruments is main tool on iOS. Templates we use:

Time Profiler — where CPU spends time. Run heavy scenario (scroll, screen load), see Call Tree with Invert Call Tree + Hide System Libraries. See own code with load percentages.

Core Animation (Rendering) — FPS and drop causes. Commit — layer formation time, Render — GPU time. High Commit — main thread issue. Red line at 16.67 ms (60 fps) or 8.33 ms (120 fps, ProMotion) — clear boundary.

Allocations — memory allocation patterns. Run, do action, see Generation Analysis. If memory doesn't drop after Release navigation — leak.

Real problem example: one project's photo collection screen stuttered on scroll. Time Profiler showed 23% time on UIImage(data:) in cellForItemAt. Synchronous JPEG decoding on main thread. Solution: ImageIO + kCGImageSourceShouldCacheImmediately: false + decoding on background queue with DispatchQueue.global(qos: .userInitiated). FPS rose from 35 to 58.

Startup Metrics

MetricKit (iOS 13+) collects production metrics from real user devices:

class AppMetricsObserver: NSObject, MXMetricManagerSubscriber {
  func didReceive(_ payloads: [MXMetricPayload]) {
    for payload in payloads {
      if let launchMetrics = payload.applicationLaunchMetrics {
        // resumeTime — time on background→foreground
        // timeToFirstDraw — cold start
        let coldStart = launchMetrics.histogrammedTimeToFirstDraw
        // send to analytics
      }
    }
  }
}

Not synthetic measurements in tests, but real data from user devices. Complements Instruments profiling.

Android: Android Profiler and Macrobenchmark

In Android Studio — Android Profiler. CPU profiler in Sample Java/Kotlin Methods mode for overview, Trace Java/Kotlin Methods for precise tracing (with overhead). System Trace — for GPU interaction, Choreographer, RenderThread.

Janky frames (>16 ms): adb shell dumpsys gfxinfo com.example.app | grep "Janky frames". More than 5% janky — issue.

Macrobenchmark — Jetpack library for reproducible measurements:

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

  @Test
  fun startup() = benchmarkRule.measureRepeated(
    packageName = "com.example.myapp",
    metrics = listOf(StartupTimingMetric()),
    iterations = 5,
    startupMode = StartupMode.COLD,
  ) {
    pressHome()
    startActivityAndWait()
  }
}

Runs on real device (not emulator), returns timeToInitialDisplay and timeToFullDisplay in milliseconds. Stable between runs — these are measurements, not stopwatch pressing.

Slow Rendering: Jetpack Compose

For Compose — Recomposition counter in Layout Inspector. More precise — ComposeUiTest with measureRepeated:

@Test
fun scrollPerformance() {
  benchmarkRule.measureRepeated(
    packageName = "com.example.myapp",
    metrics = listOf(FrameTimingMetric()),
    iterations = 5,
  ) {
    val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
    // scroll list
    device.findObject(UiSelector().resourceId("com.example.myapp:id/feed_list"))
      .flingForward()
  }
}

FrameTimingMetric collects frame data: frameOverrunMs — how much frame exceeded budget.

Flutter: DevTools and flutter_driver

Flutter DevTools → Performance view shows Frame chart with UI thread and Raster thread. Red frames — UI thread busy longer than 16 ms. Yellow — Raster thread.

Common cause of red frames: setState() rebuilds too large subtree. Solution — const constructors where data unchanged, RepaintBoundary for isolating animated elements repaint.

// Bad: entire screen rebuilds on each timer tick
class CounterScreen extends StatefulWidget { ... }

// Better: only counter isolated
class CounterScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(children: [
      const HeaderWidget(),  // const — not rebuilt
      CounterWidget(),       // only this part rebuilds
    ]);
  }
}

What's Included

  • App startup profiling (cold start, warm start)
  • FPS analysis on scroll and navigation
  • Memory leak search via Allocations / Memory Profiler
  • CPU profile analysis on heavy operations
  • Macrobenchmark tests for Android, MetricKit integration for iOS
  • Report with specific before/after numbers and recommendations

Timeline

3–5 days — profiling, problem localization, report. If optimization implementation also needed — estimate separately by change volume. Cost is calculated individually.