1 package shark 2 3 import okio.Buffer 4 import kotlin.math.absoluteValue 5 6 /** 7 * Captures IO read metrics without using much memory. 8 */ 9 class ConstantMemoryMetricsDualSourceProvider( 10 private val realSourceProvider: DualSourceProvider 11 ) : DualSourceProvider { 12 13 var randomAccessByteReads = 0L 14 internal set 15 16 var randomAccessReadCount = 0L 17 internal set 18 19 var randomAccessByteTravel = 0L 20 internal set 21 22 private var lastRandomAccessPosition = -1L 23 private var minPosition = -1L 24 private var maxPosition = -1L 25 updateRandomAccessStatsOnReadnull26 private fun updateRandomAccessStatsOnRead( 27 position: Long, 28 bytesRead: Long 29 ) { 30 randomAccessByteReads += bytesRead 31 randomAccessReadCount++ 32 if (lastRandomAccessPosition != -1L) { 33 randomAccessByteTravel += (position - lastRandomAccessPosition).absoluteValue 34 minPosition = minPosition.coerceAtMost(position) 35 maxPosition = maxPosition.coerceAtLeast(position) 36 } else { 37 minPosition = position 38 maxPosition = position 39 } 40 41 42 lastRandomAccessPosition = position 43 } 44 45 val byteTravelRange 46 get() = (maxPosition - minPosition) 47 openStreamingSourcenull48 override fun openStreamingSource() = realSourceProvider.openStreamingSource() 49 50 override fun openRandomAccessSource(): RandomAccessSource { 51 val randomAccessSource = realSourceProvider.openRandomAccessSource() 52 return object : RandomAccessSource { 53 override fun read( 54 sink: Buffer, 55 position: Long, 56 byteCount: Long 57 ): Long { 58 val bytesRead = randomAccessSource.read(sink, position, byteCount) 59 updateRandomAccessStatsOnRead(position, bytesRead) 60 return bytesRead 61 } 62 63 override fun close() = randomAccessSource.close() 64 } 65 } 66 }