[K/N] Move GCInfo, MemoryUsage, RootSetStatistics into kotlin.native.runtime

As a part of efforts to stabilize Native stdlib #KT-55765.
This commit is contained in:
Abduqodiri Qurbonzoda
2023-03-30 23:15:15 +03:00
parent bb8498b0c5
commit 7a2e2f5f9f
2 changed files with 212 additions and 91 deletions
@@ -5,14 +5,6 @@
package kotlin.native.internal.gc
import kotlin.native.internal.*
import kotlin.native.internal.NativePtr
import kotlin.native.concurrent.*
import kotlin.time.*
import kotlin.time.Duration.Companion.nanoseconds
import kotlinx.cinterop.*
import kotlin.system.*
/**
* This class represents statistics of memory usage in one memory pool.
*
@@ -21,6 +13,8 @@ import kotlin.system.*
* so it can not perfectly match the value received by os tools.
* All alignment and auxiliary object headers are included.
*/
@Deprecated("Use kotlin.native.runtime.MemoryUsage instead.", ReplaceWith("MemoryUsage", "kotlin.native.runtime.MemoryUsage"))
@DeprecatedSinceKotlin(warningSince = "1.9")
@ExperimentalStdlibApi
public class MemoryUsage(
val objectsCount: Long,
@@ -42,6 +36,8 @@ public class MemoryUsage(
* of this API, and internal usages, e.g. inside interop and Worker API.
*/
@ExperimentalStdlibApi
@Deprecated("Use kotlin.native.runtime.RootSetStatistics instead.", ReplaceWith("RootSetStatistics", "kotlin.native.runtime.RootSetStatistics"))
@DeprecatedSinceKotlin(warningSince = "1.9")
public class RootSetStatistics(
val threadLocalReferences: Long,
val stackReferences: Long,
@@ -70,6 +66,10 @@ public class RootSetStatistics(
* Can be empty, of colelction is in progress.
*/
@ExperimentalStdlibApi
@Deprecated("Use kotlin.native.runtime.GCInfo instead.", ReplaceWith("GCInfo", "kotlin.native.runtime.GCInfo"))
@DeprecatedSinceKotlin(warningSince = "1.9")
@OptIn(kotlin.native.runtime.NativeRuntimeApi::class)
@Suppress("DEPRECATION")
public class GCInfo(
val epoch: Long,
val startTimeNs: Long,
@@ -83,88 +83,36 @@ public class GCInfo(
) {
internal companion object {
val lastGCInfo: GCInfo?
get() = getGcInfo(0)
private fun getGcInfo(id: Int) = GCInfoBuilder().apply { fill(id) }.build();
get() {
val info = kotlin.native.runtime.GCInfo.lastGCInfo ?: return null
return GCInfo(
info.epoch,
info.startTimeNs,
info.endTimeNs,
info.pauseStartTimeNs,
info.pauseEndTimeNs,
info.postGcCleanupTimeNs,
info.rootSet.let {
RootSetStatistics(
it.threadLocalReferences,
it.stackReferences,
it.globalReferences,
it.stableReferences
)
},
info.memoryUsageBefore.mapValues { (_, v) ->
MemoryUsage(
v.objectsCount,
v.totalObjectsSizeBytes,
)
},
info.memoryUsageAfter.mapValues { (_, v) ->
MemoryUsage(
v.objectsCount,
v.totalObjectsSizeBytes,
)
}
)
}
}
}
@ExperimentalStdlibApi
private class GCInfoBuilder() {
var epoch: Long? = null
var startTimeNs: Long? = null
var endTimeNs: Long? = null
var pauseStartTimeNs: Long? = null
var pauseEndTimeNs: Long? = null
var postGcCleanupTimeNs: Long? = null
var rootSet: RootSetStatistics? = null
var memoryUsageBefore = mutableMapOf<String, MemoryUsage>()
var memoryUsageAfter = mutableMapOf<String, MemoryUsage>()
@ExportForCppRuntime("Kotlin_Internal_GC_GCInfoBuilder_setEpoch")
private fun setEpoch(value: Long) {
epoch = value
}
@ExportForCppRuntime("Kotlin_Internal_GC_GCInfoBuilder_setStartTime")
private fun setStartTime(value: Long) {
startTimeNs = value
}
@ExportForCppRuntime("Kotlin_Internal_GC_GCInfoBuilder_setEndTime")
private fun setEndTime(value: Long) {
endTimeNs = value
}
@ExportForCppRuntime("Kotlin_Internal_GC_GCInfoBuilder_setPauseStartTime")
private fun setPauseStartTime(value: Long) {
pauseStartTimeNs = value
}
@ExportForCppRuntime("Kotlin_Internal_GC_GCInfoBuilder_setPauseEndTime")
private fun setPauseEndTime(value: Long) {
pauseEndTimeNs = value
}
@ExportForCppRuntime("Kotlin_Internal_GC_GCInfoBuilder_setPostGcCleanupTime")
private fun setFinalizersDoneTime(value: Long) {
postGcCleanupTimeNs = value
}
@ExportForCppRuntime("Kotlin_Internal_GC_GCInfoBuilder_setRootSet")
private fun setRootSet(threadLocalReferences: Long, stackReferences: Long, globalReferences: Long, stableReferences: Long) {
rootSet = RootSetStatistics(threadLocalReferences, stackReferences, globalReferences, stableReferences)
}
@ExportForCppRuntime("Kotlin_Internal_GC_GCInfoBuilder_setMemoryUsageBefore")
private fun setMemoryUsageBefore(name: NativePtr, objectsCount: Long, totalObjectsSize: Long) {
val nameString = interpretCPointer<ByteVar>(name)!!.toKString()
val memoryUsage = MemoryUsage(objectsCount, totalObjectsSize)
memoryUsageBefore[nameString] = memoryUsage
}
@ExportForCppRuntime("Kotlin_Internal_GC_GCInfoBuilder_setMemoryUsageAfter")
private fun setMemoryUsageAfter(name: NativePtr, objectsCount: Long, totalObjectsSize: Long) {
val nameString = interpretCPointer<ByteVar>(name)!!.toKString()
val memoryUsage = MemoryUsage(objectsCount, totalObjectsSize)
memoryUsageAfter[nameString] = memoryUsage
}
fun build(): GCInfo? {
return GCInfo(
epoch ?: return null,
startTimeNs ?: return null,
endTimeNs ?: return null,
pauseStartTimeNs ?: return null,
pauseEndTimeNs ?: return null,
postGcCleanupTimeNs,
rootSet ?: return null,
memoryUsageBefore.toMap(),
memoryUsageAfter.toMap()
)
}
@GCUnsafeCall("Kotlin_Internal_GC_GCInfoBuilder_Fill")
external fun fill(id: Int)
}
@@ -0,0 +1,173 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package kotlin.native.runtime
import kotlin.native.internal.*
import kotlin.native.internal.NativePtr
import kotlin.native.concurrent.*
import kotlin.time.*
import kotlin.time.Duration.Companion.nanoseconds
import kotlinx.cinterop.*
import kotlin.system.*
/**
* This class represents statistics of memory usage in one memory pool.
*
* @property objectsCount The number of allocated objects.
* @property totalObjectsSizeBytes The total size of allocated objects. System allocator overhead is not included,
* so it can not perfectly match the value received by os tools.
* All alignment and auxiliary object headers are included.
*/
@NativeRuntimeApi
@SinceKotlin("1.9")
public class MemoryUsage(
val objectsCount: Long,
val totalObjectsSizeBytes: Long,
)
/**
* This class represents statistics of the root set for garbage collector run, separated by root set pools.
* These nodes are assumed to be used, even if there are no references for them.
*
* @property threadLocalReferences The number of objects in global variables with `@ThreadLocal` annotation.
* Object is counted once per each thread it was initialized in.
* @property stackReferences The number of objects referenced from the stack of any thread.
* These are function local variables and different temporary values, as function call arguments and
* return values. They would be automatically removed from the root set when a corresponding function
* call is finished.
* @property globalReferences The number of objects in global variables. The object is counted only if the variable is initialized.
* @property stableReferences The number of objects referenced by [kotlinx.cinterop.StableRef]. It includes both explicit usage
* of this API, and internal usages, e.g. inside interop and Worker API.
*/
@NativeRuntimeApi
@SinceKotlin("1.9")
public class RootSetStatistics(
val threadLocalReferences: Long,
val stackReferences: Long,
val globalReferences: Long,
val stableReferences: Long
)
/**
* This class represents statistics about the single run of the garbage collector.
* It is supposed to be used for testing and debugging purposes only.
*
* @property epoch ID of garbage collector run.
* @property startTimeNs Time, when garbage collector run is started, meausered by [kotlin.system.getTimeNanos].
* @property endTimeNs Time, when garbage collector run is ended, measured by [kotlin.system.getTimeNanos].
* After this point, most of the memory is reclaimed, and a new garbage collector run can start.
* @property pauseStartTimeNs Time, when mutator threads are suspended, mesured by [kotlin.system.getTimeNanos].
* @property pauseEndTimeNs Time, when mutator threads are unsuspended, mesured by [kotlin.system.getTimeNanos].
* @property postGcCleanupTimeNs Time, when all memory is reclaimed, measured by [kotlin.system.getTimeNanos].
* If null, memory reclamation is still in progress.
* @property rootSet The number of objects in each root set pool. Check [RootSetStatistics] doc for details.
* @property memoryUsageAfter Memory usage at the start of garbage collector run, separated by memory pools.
* The set of memory pools depends on the collector implementation.
* Can be empty, of colelction is in progress.
* @property memoryUsageBefore Memory usage at the end of garbage collector run, separated by memory pools.
* The set of memory pools depends on the collector implementation.
* Can be empty, of colelction is in progress.
*/
@NativeRuntimeApi
@SinceKotlin("1.9")
public class GCInfo(
val epoch: Long,
val startTimeNs: Long,
val endTimeNs: Long,
val pauseStartTimeNs: Long,
val pauseEndTimeNs: Long,
val postGcCleanupTimeNs: Long?,
val rootSet: RootSetStatistics,
val memoryUsageBefore: Map<String, MemoryUsage>,
val memoryUsageAfter: Map<String, MemoryUsage>,
) {
internal companion object {
val lastGCInfo: GCInfo?
get() = getGcInfo(0)
private fun getGcInfo(id: Int) = GCInfoBuilder().apply { fill(id) }.build();
}
}
@NativeRuntimeApi
private class GCInfoBuilder() {
var epoch: Long? = null
var startTimeNs: Long? = null
var endTimeNs: Long? = null
var pauseStartTimeNs: Long? = null
var pauseEndTimeNs: Long? = null
var postGcCleanupTimeNs: Long? = null
var rootSet: RootSetStatistics? = null
var memoryUsageBefore = mutableMapOf<String, MemoryUsage>()
var memoryUsageAfter = mutableMapOf<String, MemoryUsage>()
@ExportForCppRuntime("Kotlin_Internal_GC_GCInfoBuilder_setEpoch")
private fun setEpoch(value: Long) {
epoch = value
}
@ExportForCppRuntime("Kotlin_Internal_GC_GCInfoBuilder_setStartTime")
private fun setStartTime(value: Long) {
startTimeNs = value
}
@ExportForCppRuntime("Kotlin_Internal_GC_GCInfoBuilder_setEndTime")
private fun setEndTime(value: Long) {
endTimeNs = value
}
@ExportForCppRuntime("Kotlin_Internal_GC_GCInfoBuilder_setPauseStartTime")
private fun setPauseStartTime(value: Long) {
pauseStartTimeNs = value
}
@ExportForCppRuntime("Kotlin_Internal_GC_GCInfoBuilder_setPauseEndTime")
private fun setPauseEndTime(value: Long) {
pauseEndTimeNs = value
}
@ExportForCppRuntime("Kotlin_Internal_GC_GCInfoBuilder_setPostGcCleanupTime")
private fun setFinalizersDoneTime(value: Long) {
postGcCleanupTimeNs = value
}
@ExportForCppRuntime("Kotlin_Internal_GC_GCInfoBuilder_setRootSet")
private fun setRootSet(threadLocalReferences: Long, stackReferences: Long, globalReferences: Long, stableReferences: Long) {
rootSet = RootSetStatistics(threadLocalReferences, stackReferences, globalReferences, stableReferences)
}
@ExportForCppRuntime("Kotlin_Internal_GC_GCInfoBuilder_setMemoryUsageBefore")
private fun setMemoryUsageBefore(name: NativePtr, objectsCount: Long, totalObjectsSize: Long) {
val nameString = interpretCPointer<ByteVar>(name)!!.toKString()
val memoryUsage = MemoryUsage(objectsCount, totalObjectsSize)
memoryUsageBefore[nameString] = memoryUsage
}
@ExportForCppRuntime("Kotlin_Internal_GC_GCInfoBuilder_setMemoryUsageAfter")
private fun setMemoryUsageAfter(name: NativePtr, objectsCount: Long, totalObjectsSize: Long) {
val nameString = interpretCPointer<ByteVar>(name)!!.toKString()
val memoryUsage = MemoryUsage(objectsCount, totalObjectsSize)
memoryUsageAfter[nameString] = memoryUsage
}
fun build(): GCInfo? {
return GCInfo(
epoch ?: return null,
startTimeNs ?: return null,
endTimeNs ?: return null,
pauseStartTimeNs ?: return null,
pauseEndTimeNs ?: return null,
postGcCleanupTimeNs,
rootSet ?: return null,
memoryUsageBefore.toMap(),
memoryUsageAfter.toMap()
)
}
@GCUnsafeCall("Kotlin_Internal_GC_GCInfoBuilder_Fill")
external fun fill(id: Int)
}