Project

General

Profile

Actions

Feature #22250

open

Add an only: keyword to Coverage.peek_result

Feature #22250: Add an only: keyword to Coverage.peek_result

Added by sferik (Erik Berlin) about 16 hours ago. Updated about 8 hours ago.

Status:
Open
Assignee:
-
Target version:
-
[ruby-core:126431]

Description

I am a maintainer of SimpleCov and working on adding a feature that attributes coverage to individual tests (see https://github.com/simplecov-ruby/simplecov/pull/1277). This feature works by work by diffing Coverage.peek_result snapshots around each test. That means thousands of peek_result calls per test run, but each call only needs the line counters, since per-test attribution is computed from line execution count deltas.

peek_result always builds the full result for every measured type. With branch and method coverage enabled, building the branch and method structures dominates the cost, so each snapshot is an order of magnitude more expensive than the lines the caller actually reads. On a real test suite measuring lines, branches, and methods, per-test tracking causes the test suite to run in ~30 seconds vs. ~3 seconds when it's disabled. Nearly all of this additional time is spent in peek_result, building results that are immediately discarded. Line-only filtering is significantly cheaper because the line result is a flat array dup, while branch and method results are rebuilt hashes.

Proposal

Allow callers to request only the types they need:

Coverage.start(lines: true, branches: true, methods: true)
Coverage.peek_result(only: :lines)
# => {"file.rb" => {lines: [1, 2, nil]}, ...}

Coverage.peek_result(only: [:lines, :branches])
# => {"file.rb" => {lines: [1, 2, nil], branches: {...}}, ...}

only: should accept one of :lines, :oneshot_lines, :branches, or :methods, or an Array of them. Each file's hash then contains only the requested keys, and the result construction for the other measured types is skipped entirely (the branch structure walk and the method table iteration never run). Requesting a type that is not being measured should raise a RuntimeError, consistent with the existing "coverage measurement is not enabled" error. An unknown type should raise an ArgumentError.

A patch with tests and documentation is at https://github.com/sferik/ruby-lang/tree/coverage-peek-result-only

The change is confined to ext/coverage/coverage.c. The existing coverage_peek_result_i iteration takes a filter mask (defaulting to current_mode, so the unfiltered path is byte-for-byte the current behavior), and Coverage.result reuses the same internal function with the full mask. I am happy to open a pull request if this direction is acceptable.

Actions

Also available in: PDF Atom