main

square/leakcanary

Last updated at: 29/12/2023 09:39

ConstantMemoryMetricsDualSourceProvider.kt

TLDR

This file contains the ConstantMemoryMetricsDualSourceProvider class, which is responsible for capturing IO read metrics without using much memory. It implements the DualSourceProvider interface and overrides its methods. It also defines some properties and a private method for updating random access stats on read.

Classes

ConstantMemoryMetricsDualSourceProvider

The ConstantMemoryMetricsDualSourceProvider class captures IO read metrics without using much memory. It implements the DualSourceProvider interface and overrides its methods.

Methods

There are no additional methods in this file.

package shark

import okio.Buffer
import kotlin.math.absoluteValue

/**
 * Captures IO read metrics without using much memory.
 */
class ConstantMemoryMetricsDualSourceProvider(
  private val realSourceProvider: DualSourceProvider
) : DualSourceProvider {

  var randomAccessByteReads = 0L
    internal set

  var randomAccessReadCount = 0L
    internal set

  var randomAccessByteTravel = 0L
    internal set

  private var lastRandomAccessPosition = -1L
  private var minPosition = -1L
  private var maxPosition = -1L

  private fun updateRandomAccessStatsOnRead(
    position: Long,
    bytesRead: Long
  ) {
    randomAccessByteReads += bytesRead
    randomAccessReadCount++
    if (lastRandomAccessPosition != -1L) {
      randomAccessByteTravel += (position - lastRandomAccessPosition).absoluteValue
      minPosition = minPosition.coerceAtMost(position)
      maxPosition = maxPosition.coerceAtLeast(position)
    } else {
      minPosition = position
      maxPosition = position
    }


    lastRandomAccessPosition = position
  }

  val byteTravelRange
    get() = (maxPosition - minPosition)

  override fun openStreamingSource() = realSourceProvider.openStreamingSource()

  override fun openRandomAccessSource(): RandomAccessSource {
    val randomAccessSource = realSourceProvider.openRandomAccessSource()
    return object : RandomAccessSource {
      override fun read(
        sink: Buffer,
        position: Long,
        byteCount: Long
      ): Long {
        val bytesRead = randomAccessSource.read(sink, position, byteCount)
        updateRandomAccessStatsOnRead(position, bytesRead)
        return bytesRead
      }

      override fun close() = randomAccessSource.close()
    }
  }
}