1+ package com.whispercppdemo.whisper
2+
3+ import android.util.Log
4+ import java.io.BufferedReader
5+ import java.io.FileReader
6+
7+ object WhisperCpuConfig {
8+ val preferredThreadCount: Int
9+ // Always use at least 2 threads:
10+ get() = CpuInfo .getHighPerfCpuCount().coerceAtLeast(2 )
11+ }
12+
13+ private class CpuInfo (private val lines : List <String >) {
14+ private fun getHighPerfCpuCount (): Int = try {
15+ getHighPerfCpuCountByFrequencies()
16+ } catch (e: Exception ) {
17+ Log .d(LOG_TAG , " Couldn't read CPU frequencies" , e)
18+ getHighPerfCpuCountByVariant()
19+ }
20+
21+ private fun getHighPerfCpuCountByFrequencies (): Int =
22+ getCpuValues(property = " processor" ) { getMaxCpuFrequency(it.toInt()) }
23+ .also { Log .d(LOG_TAG , " Binned cpu frequencies (frequency, count): ${it.binnedValues()} " ) }
24+ .countDroppingMin()
25+
26+ private fun getHighPerfCpuCountByVariant (): Int =
27+ getCpuValues(property = " CPU variant" ) { it.substringAfter(" 0x" ).toInt(radix = 16 ) }
28+ .also { Log .d(LOG_TAG , " Binned cpu variants (variant, count): ${it.binnedValues()} " ) }
29+ .countKeepingMin()
30+
31+ private fun List<Int>.binnedValues () = groupingBy { it }.eachCount()
32+
33+ private fun getCpuValues (property : String , mapper : (String ) -> Int ) = lines
34+ .asSequence()
35+ .filter { it.startsWith(property) }
36+ .map { mapper(it.substringAfter(' :' ).trim()) }
37+ .sorted()
38+ .toList()
39+
40+
41+ private fun List<Int>.countDroppingMin (): Int {
42+ val min = min()
43+ return count { it > min }
44+ }
45+
46+ private fun List<Int>.countKeepingMin (): Int {
47+ val min = min()
48+ return count { it == min }
49+ }
50+
51+ companion object {
52+ private const val LOG_TAG = " WhisperCpuConfig"
53+
54+ fun getHighPerfCpuCount (): Int = try {
55+ readCpuInfo().getHighPerfCpuCount()
56+ } catch (e: Exception ) {
57+ Log .d(LOG_TAG , " Couldn't read CPU info" , e)
58+ // Our best guess -- just return the # of CPUs minus 4.
59+ (Runtime .getRuntime().availableProcessors() - 4 ).coerceAtLeast(0 )
60+ }
61+
62+ private fun readCpuInfo () = CpuInfo (
63+ BufferedReader (FileReader (" /proc/cpuinfo" ))
64+ .useLines { it.toList() }
65+ )
66+
67+ private fun getMaxCpuFrequency (cpuIndex : Int ): Int {
68+ val path = " /sys/devices/system/cpu/cpu${cpuIndex} /cpufreq/cpuinfo_max_freq"
69+ val maxFreq = BufferedReader (FileReader (path)).use { it.readLine() }
70+ return maxFreq.toInt()
71+ }
72+ }
73+ }
0 commit comments