<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: PatilSpeaks</title>
    <description>The latest articles on DEV Community by PatilSpeaks (@patilspeaks).</description>
    <link>https://dev.to/patilspeaks</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4008774%2Fab155d3c-723c-4755-9028-f325b6d52516.jpg</url>
      <title>DEV Community: PatilSpeaks</title>
      <link>https://dev.to/patilspeaks</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/patilspeaks"/>
    <language>en</language>
    <item>
      <title>My First Open Source Contribution: The Hardest Part Wasn't Writing the Code</title>
      <dc:creator>PatilSpeaks</dc:creator>
      <pubDate>Mon, 29 Jun 2026 22:10:22 +0000</pubDate>
      <link>https://dev.to/patilspeaks/my-first-open-source-contribution-the-hardest-part-wasnt-writing-the-code-1m7e</link>
      <guid>https://dev.to/patilspeaks/my-first-open-source-contribution-the-hardest-part-wasnt-writing-the-code-1m7e</guid>
      <description>&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/upb-cn/MoRAGBench/pull/1" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        Add process CPU utilization metrics to HardwareMetricsEngine
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#1&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/PatilSpeaks" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F95365740%3Fv%3D4" alt="PatilSpeaks avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/PatilSpeaks" rel="noopener noreferrer"&gt;PatilSpeaks&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/upb-cn/MoRAGBench/pull/1" rel="noopener noreferrer"&gt;&lt;time&gt;Jun 04, 2026&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;&lt;strong&gt;Summary&lt;/strong&gt;
Add process CPU utilization metrics to HardwareMetricsEngine.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Changes&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Add CpuSampler based on Process.getElapsedCpuTime() and SystemClock.elapsedRealtime()&lt;/li&gt;
&lt;li&gt;Add CpuMetrics to benchmark results&lt;/li&gt;
&lt;li&gt;Include CPU statistics in MetricsResult&lt;/li&gt;
&lt;li&gt;Generalize PowerStats to FloatMetricStats so the same structure can be reused for power and CPU metrics&lt;/li&gt;
&lt;li&gt;Stop cancelling the caller-owned benchmark scope when stopping HardwareMetricsEngine&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Validation&lt;/strong&gt;
Tested on an Android device.&lt;/p&gt;
&lt;p&gt;Verified that benchmark output now includes CPU metrics in hardware_metrics.json, for example:&lt;/p&gt;
&lt;p&gt;"cpu": {
"processUsagePercent": {
"mean": 356.14523,
"peak": 442.85712
}
}&lt;/p&gt;
&lt;p&gt;Build verification:
./gradlew :cli:assembleDebug&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/upb-cn/MoRAGBench/pull/1" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flz2czhl18doh1i5tddio.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flz2czhl18doh1i5tddio.png" alt="My first contribution to MoRAGBench, which eventually became PR #1" width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Why CPU Metrics Mattered?
&lt;/h2&gt;

&lt;p&gt;When I started exploring MoRAGBench, I wasn't looking for a difficult feature. Quite the opposite.&lt;/p&gt;

&lt;p&gt;As a first time contributor, I wanted something small enough that I wouldn't get lost in an unfamiliar codebase, but interesting enough that I'd learn something from it.&lt;/p&gt;

&lt;p&gt;One thing immediately caught my attention.&lt;/p&gt;

&lt;p&gt;The framework already collected useful hardware metrics such as memory usage and power consumption during benchmark execution.&lt;/p&gt;

&lt;p&gt;At first glance, that seemed sufficient.&lt;/p&gt;

&lt;p&gt;But the more I thought about it, the more I realized there was a missing piece.&lt;/p&gt;

&lt;p&gt;Imagine two retrieval-augmented generation (RAG) pipelines producing identical accuracy.&lt;/p&gt;

&lt;p&gt;One consumes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;150 MB RAM&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;120% CPU utilization&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The other consumes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;400 MB RAM&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;700% CPU utilization&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without CPU metrics, both systems might appear equivalent from an accuracy perspective even though their computational cost is dramatically different.&lt;/p&gt;

&lt;p&gt;MoRAGBench could already answer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;How much memory did the benchmark use?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How much power did it consume?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It couldn't answer:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How much CPU did this benchmark actually consume?&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The First Question That Broke My Assumptions
&lt;/h2&gt;

&lt;p&gt;My original hypothesis sounded almost embarrassingly simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Measure CPU utilization and expose it as another hardware metric.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I assumed the implementation would be the difficult part.&lt;/p&gt;

&lt;p&gt;I was wrong.&lt;/p&gt;

&lt;p&gt;Before writing a single line of Kotlin, I ran into a much bigger question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What exactly should CPU utilization mean?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;At first, the question sounded almost silly.&lt;/p&gt;

&lt;p&gt;But the deeper I looked, the more definitions appeared:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Device-wide CPU utilization.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Process CPU utilization.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Per-core utilization.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Average utilization.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Peak utilization.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each of these measures something different.&lt;/p&gt;

&lt;p&gt;A technically correct implementation built on the wrong definition would still produce a misleading benchmark metric.&lt;/p&gt;

&lt;p&gt;This was the first lesson of the project:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Defining a metric is often harder than implementing it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Before touching code, I spent time understanding how MoRAGBench already collected hardware metrics and where CPU utilization would fit into that architecture.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsfvp12roamuui7t0un30.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsfvp12roamuui7t0un30.png" alt="Understanding the existing hardware metrics pipeline before introducing a new metric" width="800" height="455"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Technical Exploration
&lt;/h2&gt;

&lt;p&gt;Android doesn't provide a convenient API that simply returns "CPU utilization."&lt;/p&gt;

&lt;p&gt;Instead, it exposes lower-level building blocks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Process CPU time.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Wall-clock time.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Number of available processors.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;CPU utilization has to be derived from those values.&lt;/p&gt;

&lt;p&gt;The implementation eventually centered around:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;CPU Utilization = (Process CPU Time Delta / Wall Clock Time Delta) × 100&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The idea is straightforward:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Measure how much CPU time the process consumed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Measure how much real-world time passed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Compare the two.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Initially, this seemed like a solved problem.&lt;/p&gt;

&lt;p&gt;Then I ran the benchmark.&lt;/p&gt;




&lt;h2&gt;
  
  
  The First Time I Thought My Implementation Was Broken
&lt;/h2&gt;

&lt;p&gt;The numbers looked wrong.&lt;/p&gt;

&lt;p&gt;Some runs reported:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;356%&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;399%&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;452%&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;My immediate reaction was:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Something must be wrong.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;CPU utilization is a percentage. Percentages shouldn't exceed 100%. Right?&lt;/p&gt;

&lt;p&gt;I spent quite a while questioning my implementation before I questioned my assumption.&lt;/p&gt;

&lt;p&gt;The problem wasn't the code. It was my mental model.&lt;/p&gt;

&lt;p&gt;Modern Android devices have multiple CPU cores. A process can execute work across several cores simultaneously.&lt;/p&gt;

&lt;p&gt;On an eight core device, the process can legitimately consume close to 800% CPU utilization because utilization is aggregated across all available cores.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Active Cores&lt;/th&gt;
&lt;th&gt;Utilization&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1 core&lt;/td&gt;
&lt;td&gt;100%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4 cores&lt;/td&gt;
&lt;td&gt;400%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8 cores&lt;/td&gt;
&lt;td&gt;800%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The implementation wasn't wrong. My intuition was.&lt;/p&gt;

&lt;p&gt;That realization completely changed how I interpreted every CPU number afterward.&lt;/p&gt;

&lt;p&gt;A benchmark reporting 700% utilization wasn't necessarily broken. It simply meant the process was heavily utilizing approximately seven CPU cores.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjb1n624zue3pyhy99erv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjb1n624zue3pyhy99erv.png" alt="CPU utilization can exceed 100% on multi-core systems because utilization is aggregated across cores." width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Reviewer Found the Real Problem
&lt;/h2&gt;

&lt;p&gt;Once I was reasonably confident in the implementation, I opened my pull request.&lt;/p&gt;

&lt;p&gt;I expected comments about Kotlin style, Android APIs or code structure.&lt;/p&gt;

&lt;p&gt;Instead, the reviewer asked a question I hadn't considered.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This code reports CPU usage time for all cores. Can Android expose per-core or per-thread utilization? If not, can we expose the number of CPU cores and calculate average utilization per core?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Reading that comment felt strange. The implementation worked. The reviewer agreed it worked. Yet the feature still wasn't finished.&lt;/p&gt;

&lt;p&gt;That was probably the first time I realized that &lt;strong&gt;writing software and designing software are different activities&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The reviewer wasn't asking me to fix a bug. He was asking me to improve the meaning of the metric.&lt;/p&gt;

&lt;p&gt;If someone later saw 650% CPU utilization, would they know whether that meant six busy CPU cores or a broken implementation?&lt;/p&gt;

&lt;p&gt;Without additional context, the metric was technically correct but practically confusing.&lt;/p&gt;

&lt;p&gt;That feedback fundamentally changed the feature.&lt;/p&gt;

&lt;p&gt;Instead of reporting only aggregate utilization, the final implementation exposed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Process CPU utilization&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Average utilization per core&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Available processor count&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nothing about the calculation changed. Everything about the interpretation improved.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fy3l13xymj7358q64o1rj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fy3l13xymj7358q64o1rj.png" alt="A review comment that shifted the conversation from implementation details to metric semantics" width="800" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This became the most valuable part of the entire contribution.&lt;/p&gt;




&lt;h1&gt;
  
  
  Validation
&lt;/h1&gt;

&lt;p&gt;One mistake I often see in engineering projects including my own is treating compilation as validation.&lt;/p&gt;

&lt;p&gt;Compilation proves syntax.&lt;/p&gt;

&lt;p&gt;It does &lt;strong&gt;not&lt;/strong&gt; prove correctness.&lt;/p&gt;

&lt;p&gt;Initially, I assumed that because the calculation looked correct, the implementation was probably correct.&lt;/p&gt;

&lt;p&gt;The reviewer challenged that assumption too. He suggested comparing the benchmark output against an external monitoring application.&lt;/p&gt;

&lt;p&gt;Although external tools report overall device utilization rather than benchmark process utilization, the numbers should still be in the same general range if the benchmark dominates the workload.&lt;/p&gt;

&lt;p&gt;After comparing the benchmark output with DevCheck, the values weren't identical, as expected but they followed similar trends during execution.&lt;/p&gt;

&lt;p&gt;Internally, the metrics were also consistent.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;If a benchmark reported:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Process utilization = 640%&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Available processors = 8&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then:&lt;/p&gt;

&lt;p&gt;640 ÷ 8 = 80%&lt;/p&gt;

&lt;p&gt;which matched the reported per-core utilization. This wasn't mathematical proof.&lt;/p&gt;

&lt;p&gt;But it was strong evidence that the implementation behaved as intended.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fyxh27oyzfgt827rk01j2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fyxh27oyzfgt827rk01j2.png" alt="CPU utilization metrics collected during benchmark execution" width="630" height="546"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  The Lesson That Changed How I View Code Reviews
&lt;/h1&gt;

&lt;p&gt;Before this contribution, I viewed code reviews primarily as implementation reviews. Now I think differently.&lt;/p&gt;

&lt;p&gt;A good reviewer does more than verify code quality. A good reviewer protects metric quality. The most important feedback I received had nothing to do with Android APIs. It had everything to do with interpretation.&lt;/p&gt;

&lt;p&gt;Once a benchmark publishes a number, engineers will compare systems, make decisions and draw conclusions from it.&lt;/p&gt;

&lt;p&gt;That means a performance metric isn't merely another value produced by code. It's a promise.&lt;/p&gt;

&lt;p&gt;If that promise is easy to misunderstand, the implementation isn't really finished even if the code is technically correct.&lt;/p&gt;

&lt;p&gt;That realization fundamentally changed how I think about performance metrics.&lt;/p&gt;




&lt;h1&gt;
  
  
  Final Outcome
&lt;/h1&gt;

&lt;p&gt;The contribution ultimately introduced:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Process CPU utilization metrics&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Per-core Process CPU utilization metrics&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Available processor count&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The pull request was merged as:&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/upb-cn/MoRAGBench/pull/1" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        Add process CPU utilization metrics to HardwareMetricsEngine
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#1&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/PatilSpeaks" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F95365740%3Fv%3D4" alt="PatilSpeaks avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/PatilSpeaks" rel="noopener noreferrer"&gt;PatilSpeaks&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/upb-cn/MoRAGBench/pull/1" rel="noopener noreferrer"&gt;&lt;time&gt;Jun 04, 2026&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;&lt;strong&gt;Summary&lt;/strong&gt;
Add process CPU utilization metrics to HardwareMetricsEngine.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Changes&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Add CpuSampler based on Process.getElapsedCpuTime() and SystemClock.elapsedRealtime()&lt;/li&gt;
&lt;li&gt;Add CpuMetrics to benchmark results&lt;/li&gt;
&lt;li&gt;Include CPU statistics in MetricsResult&lt;/li&gt;
&lt;li&gt;Generalize PowerStats to FloatMetricStats so the same structure can be reused for power and CPU metrics&lt;/li&gt;
&lt;li&gt;Stop cancelling the caller-owned benchmark scope when stopping HardwareMetricsEngine&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Validation&lt;/strong&gt;
Tested on an Android device.&lt;/p&gt;
&lt;p&gt;Verified that benchmark output now includes CPU metrics in hardware_metrics.json, for example:&lt;/p&gt;
&lt;p&gt;"cpu": {
"processUsagePercent": {
"mean": 356.14523,
"peak": 442.85712
}
}&lt;/p&gt;
&lt;p&gt;Build verification:
./gradlew :cli:assembleDebug&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/upb-cn/MoRAGBench/pull/1" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;More importantly, it taught me something that extends far beyond Android development.&lt;/p&gt;

&lt;p&gt;The hardest part of my first open source contribution wasn't implementing CPU utilization.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It was realizing that the real bug wasn't in my Kotlin code.&lt;/p&gt;

&lt;p&gt;It was in the assumptions I brought with me before I wrote the first line.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

&lt;p&gt;📖 Blog: patilspeaks.hashnode.dev&lt;/p&gt;

&lt;p&gt;🐦 X: x.com/PatilSpeaksX&lt;/p&gt;

&lt;p&gt;💻 GitHub: github.com/PatilSpeaks&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>software</category>
      <category>performance</category>
      <category>patilspeaks</category>
    </item>
  </channel>
</rss>
