diff --git a/platform/platform-impl/src/com/intellij/internal/statistic/collectors/fus/os/SystemRuntimeCollector.kt b/platform/platform-impl/src/com/intellij/internal/statistic/collectors/fus/os/SystemRuntimeCollector.kt index 2aa5499f28cd..eed8ae58f405 100644 --- a/platform/platform-impl/src/com/intellij/internal/statistic/collectors/fus/os/SystemRuntimeCollector.kt +++ b/platform/platform-impl/src/com/intellij/internal/statistic/collectors/fus/os/SystemRuntimeCollector.kt @@ -28,12 +28,12 @@ class SystemRuntimeCollector : ApplicationUsagesCollector() { override fun getMetrics(): Set { val result = HashSet() - result.add(CORES.metric(StatisticsUtil.getUpperBound(Runtime.getRuntime().availableProcessors(), - intArrayOf(1, 2, 4, 6, 8, 12, 16, 20, 24, 32, 64)))) + result.add(CORES.metric(StatisticsUtil.roundToUpperBound(Runtime.getRuntime().availableProcessors(), + intArrayOf(1, 2, 4, 6, 8, 12, 16, 20, 24, 32, 64)))) val osMxBean = ManagementFactory.getOperatingSystemMXBean() as OperatingSystemMXBean - val totalPhysicalMemory = StatisticsUtil.getUpperBound((osMxBean.totalPhysicalMemorySize.toDouble() / (1 shl 30)).roundToInt(), - intArrayOf(1, 2, 4, 8, 12, 16, 24, 32, 48, 64, 128, 256)) + val totalPhysicalMemory = StatisticsUtil.roundToUpperBound((osMxBean.totalPhysicalMemorySize.toDouble() / (1 shl 30)).roundToInt(), + intArrayOf(1, 2, 4, 8, 12, 16, 24, 32, 48, 64, 128, 256)) result.add(MEMORY_SIZE.metric(totalPhysicalMemory)) var totalSwapSize = (osMxBean.totalSwapSpaceSize.toDouble() / (1 shl 30)).roundToInt() diff --git a/platform/platform-tests/testSrc/com/intellij/internal/statistics/StatisticsUtilTest.kt b/platform/platform-tests/testSrc/com/intellij/internal/statistics/StatisticsUtilTest.kt index 40525e5a70b2..54cd1b2d6171 100644 --- a/platform/platform-tests/testSrc/com/intellij/internal/statistics/StatisticsUtilTest.kt +++ b/platform/platform-tests/testSrc/com/intellij/internal/statistics/StatisticsUtilTest.kt @@ -8,6 +8,7 @@ import com.intellij.internal.statistic.utils.StatisticsUtil import com.intellij.internal.statistic.utils.StatisticsUtil.getCurrentHourInUTC import com.intellij.internal.statistic.utils.StatisticsUtil.getNextPowerOfTwo import com.intellij.internal.statistic.utils.StatisticsUtil.roundToPowerOfTwo +import com.intellij.internal.statistic.utils.StatisticsUtil.roundToUpperBound import com.intellij.testFramework.LightPlatformTestCase import junit.framework.TestCase import org.junit.Test @@ -119,6 +120,37 @@ class StatisticsUtilTest : LightPlatformTestCase() { assertEquals(expected, roundToPowerOfTwo(value), "Incorrect key for value `$value`") } + @Test + fun `test round to upper bound`() { + // Test empty bounds return next power of two + testRoundToUpperBound(0, intArrayOf(), 0) + testRoundToUpperBound(1, intArrayOf(), 1) + testRoundToUpperBound(2, intArrayOf(), 2) + testRoundToUpperBound(3, intArrayOf(), 4) + testRoundToUpperBound(10, intArrayOf(), 16) + testRoundToUpperBound(Int.MAX_VALUE, intArrayOf(), Int.MAX_VALUE) + + // Test with bounds + // on the edge + testRoundToUpperBound(0, intArrayOf(0, 1, 2), 0) + testRoundToUpperBound(1, intArrayOf(0, 1, 2), 1) + testRoundToUpperBound(2, intArrayOf(0, 1, 2), 2) + // between bounds + testRoundToUpperBound(5, intArrayOf(1, 10, 100), 10) + testRoundToUpperBound(50, intArrayOf(1, 10, 100), 100) + // out of bounds + testRoundToUpperBound(-1, intArrayOf(0, 1, 2), 0) + testRoundToUpperBound(3, intArrayOf(0, 1, 2), 2) + // corner cases + testRoundToUpperBound(Int.MIN_VALUE, intArrayOf(0, 1, 2), 0) + testRoundToUpperBound(Int.MAX_VALUE, intArrayOf(0, 1, 2), 2) + + } + + private fun testRoundToUpperBound(value: Int, bounds: IntArray, expected: Int) { + assertEquals(expected, roundToUpperBound(value, bounds), "Incorrect key for value `$value`") + } + @Test fun `test hash sensitive data`() { diff --git a/platform/statistics/src/com/intellij/internal/statistic/utils/StatisticsUtil.kt b/platform/statistics/src/com/intellij/internal/statistic/utils/StatisticsUtil.kt index 8dbbc273f26c..7aa4b5b85901 100644 --- a/platform/statistics/src/com/intellij/internal/statistic/utils/StatisticsUtil.kt +++ b/platform/statistics/src/com/intellij/internal/statistic/utils/StatisticsUtil.kt @@ -73,14 +73,14 @@ object StatisticsUtil { /** * Anonymizes value by finding upper bound in provided bounds. - * Allows more fine tuning then `com.intellij.internal.statistic.utils.StatisticsUtil#getNextPowerOfTwo` + * Allows more fine tuning then `com.intellij.internal.statistic.utils.StatisticsUtil#roundToPowerOfTwo` * but requires manual maintaining. * * @param bounds is an integer array sorted in ascending order (required, but not checked) * @return value upper bound or next power of two if no bounds were provided (as fallback) * */ @JvmStatic - fun getUpperBound(value: Int, bounds: IntArray): Int { + fun roundToUpperBound(value: Int, bounds: IntArray): Int { if (bounds.isEmpty()) return roundToPowerOfTwo(value) for (bound in bounds) @@ -88,6 +88,10 @@ object StatisticsUtil { return bounds.last() } + @JvmStatic + @Deprecated(message = "Use roundToUpperBound instead", replaceWith = ReplaceWith("roundToUpperBound")) + fun getUpperBound(value: Int, bounds: IntArray): Int = roundToUpperBound(value, bounds) + /** * Anonymizes sensitive project properties by rounding it to the next value in steps list. * See `com.intellij.internal.statistic.collectors.fus.fileTypes.FileTypeUsagesCollector`