-
Notifications
You must be signed in to change notification settings - Fork 26
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Expose api for attaching and detaching Storage.localMarkHolder #5
Comments
@marcoferrer would using two Does kotlin expose some other unique identifier as opposed to ThreadId? It may be possible to record using a coroutine id, and stitch the results back together when reading out the marks. |
Coroutine id is an internal value and only populated while running in debug mode. There is coroutine name and it is public and configurable. suspend fun doSomething(){
withContext(CoroutineName("someuniq-value")) {
PerfMark.startTask("doSomething")
try {
longRunningOperation()
} finally {
// Code is resumed on a different thread, but the coroutine dispatcher
// took care of ensuring our thread local is present before execution.
PerfMark.stopTask("doSomething")
}
}
}
Coroutine name doe not enforce uniqueness though. Also its a widely used API, and its value is easily overwritten. This would make its usage painful. I think a safer approach would be implementing a context element specific to perfmark. suspend fun doSomething(){
withContext(PerfMarkTaskId("someuniq-value")) {
val taskId = coroutineContext[PerfMarkTaskId]
// PerfMark.setRecordId(taskId) ???
PerfMark.startTask("doSomething")
try {
longRunningOperation()
} finally {
// PerfMark.setRecordId(taskId) ???
PerfMark.stopTask("doSomething")
}
}
}
We would even be able to provide a PerfMark API specific to coroutines and keep the perfmark context element private. suspend fun doSomething(){
perfMarkTask("doSomething"){
longRunningOperation()
}
}
inline suspend fun perfMarkTask(taskName: String, block: ()-> Unit){
// coroutineContext is implicit in suspending functions
// It is propagated via the compiler
val currentTaskId = coroutineContext[PerfMarkTaskId]
val pTaskId = if (currentPTaskId != null) {
// Link new sub task using currentTaskId ???
// Create uid for this new task
PerfMarkTaskId("something-uniqe")
} else {
PerfMarkTaskId("something-uniqe")
}
withContext(pTaskId){
try {
PerfMark.startTaskInContext(coroutineContext, taskName)
block()
} finally {
withContext(NonCancellable){
PerfMark.stopTaskFromContext(taskName)
}
}
}
}
Coroutines propagate their context down to their children. So if there is a parent task it will always be available provided uses follow best practices of coroutines structure concurrency. Im not thoroughly familiar with perfmarks internals so I dont know how much of this makes sense but at least its an idea. |
@marcoferrer If At the moment, getting the current threadlocal costs about 10-15ns (hash table look up), along with recording the values in the MarkHolder (3-6ns), and for most operations getting System.nanoTime (around 25-30ns). I think something that could work with the Kotlin context based approach you show would be using a ConcurrentHashMap instead of the threadlocal, and keyed on an id allocated upon entering the top level context. Some questions:
|
I know this is very late after the the original request but I have come up with an API that I think allows Kotlin to enter and exit the coroutines. I would be interested in your feedback @marcoferrer with the changes made in https://github.com/perfmark/perfmark/releases/tag/v0.26.0 |
Hi there. I know this project is primarily targeting java, but I was interested in using it with Kotlins Coroutines (Fibers).
One thing holding me back is that suspending methods in kotlin can pause and resume on a different thread than the one it was invoked on.
The coroutines API does provide ways to handle this but they would require access to the
thread local.
We ran into the same issue previously with
io.grpc.Context
and were able to leverage theattach()
anddetach()
APIs to get maintain the correct context on the thread during coroutine execution. GrpcContextElement.ktWould exposing similar methods unnecessarily complicate PerkMarks internals? Ive considered using
linkIn
but I dont think it was designed with this particular use-case in mind.The text was updated successfully, but these errors were encountered: