Skip to content
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

High cpu utilization with ktor on Android using GlobalScope.launch #1046

Closed
e5l opened this issue Mar 15, 2019 · 13 comments
Closed

High cpu utilization with ktor on Android using GlobalScope.launch #1046

e5l opened this issue Mar 15, 2019 · 13 comments
Assignees

Comments

@e5l
Copy link
Member

e5l commented Mar 15, 2019

After switching to the fixed thread pool dispatcher in ktor(ktorio/ktor@990ccfb) GlobalScope.launch cpu utilization is much higher than client.launch:

val client = HttpClient {
    install(WebSockets)
}

/* client.launch */
GlobalScope.launch {
    client.ws {
        while(true) {
           // ping
           session?.send(Frame.Text("Hello"))
           // pong
           val frame = session?.incoming?.receive()
        }
    } 
}
@qwwdfsad
Copy link
Collaborator

It looks like the same issue as in #840, I will investigate further

@marcelmatula
Copy link

marcelmatula commented Mar 27, 2019

have same issue with ktor - here is stack trace for thread which does heavy cpu utilization

"DefaultDispatcher-worker-1" #38 daemon prio=5 os_prio=0 cpu=567406063.38ms elapsed=714692.38s tid=0x00007fdc4c01b000 nid=0x56ea runnable  [0x00007fdc50b38000]
   java.lang.Thread.State: RUNNABLE
        at sun.nio.ch.EPoll.wait(java.base@11.0.2/Native Method)
        at sun.nio.ch.EPollSelectorImpl.doSelect(java.base@11.0.2/EPollSelectorImpl.java:120)
        at sun.nio.ch.SelectorImpl.lockAndDoSelect(java.base@11.0.2/SelectorImpl.java:124)
        - locked <0x00000000fcdb65e8> (a sun.nio.ch.Util$2)
        - locked <0x00000000fcdb6498> (a sun.nio.ch.EPollSelectorImpl)
        at sun.nio.ch.SelectorImpl.selectNow(java.base@11.0.2/SelectorImpl.java:146)
        at io.ktor.network.selector.ActorSelectorManager.process(ActorSelectorManager.kt:77)
        at io.ktor.network.selector.ActorSelectorManager$process$1.invokeSuspend(ActorSelectorManager.kt)
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:32)
        at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:233)
        at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:594)
        at kotlinx.coroutines.scheduling.CoroutineScheduler.access$runSafely(CoroutineScheduler.kt:60)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:742)

related code is:

webSocket("/api/ws-endpoint") {
    ...
    try {
        while (true) {
            val frame = incoming.receive()
            if (frame is Frame.Text) call.log.trace("message received: ${frame.readText()}")
        }
    } catch (ex: ClosedReceiveChannelException) {
        call.log.info("ws: ${ex.message}")
    }
}

@avently
Copy link

avently commented May 20, 2019

I will investigate further

@qwwdfsad when your investigation will be ended?

@MrPowerGamerBR
Copy link

MrPowerGamerBR commented Jun 25, 2019

Same here, this project is only using the "Raw Sockets" (this instance was using only the client) feature from ktor.

(Submitted it here because the issue on ktor is waiting for the fix on the coroutines side)

By the way, running on JDK 11

image

@madhead
Copy link

madhead commented Jun 26, 2019

I'm having the same issue as @MrPowerGamerBR above with a code like this:

withTimeout(timeoutMillis) {
    aSocket(ActorSelectorManager(Dispatchers.IO))
        .tcp()
        .connect(InetSocketAddress(host, port)).use { socket ->
            val writeChannel = socket.openWriteChannel()
            val readChannel = socket.openReadChannel()

            writeChannel.writeStringUtf8(input.vowpalWabbitFormat) // just a string ending with two newlines (`\n`)
            writeChannel.flush()

            val payload = readChannel.readUTF8Line()

            RawOutput(payload!!) // return the result
        }
}

I've also tried to force close the read channel like

val payload = readChannel.readUTF8Line()
readChannel.cancel()

…but it seems useless.

@MrPowerGamerBR
Copy link

Is there's any progress on this issue? This is making me avoid using some libraries that rely on coroutines (like ktor, even tho I really like it) and because this is a major bug it becomes kinda difficult to stay with ktor if it makes your application consume 100% CPU for no reason while any other library works fine.

@qwwdfsad
Copy link
Collaborator

Yes, we are targeting the fix to 1.3.2

@fabiomargarido
Copy link

Looks like this fix didn't make it into 1.3.2. Any updated forecasts?

@qwwdfsad
Copy link
Collaborator

qwwdfsad commented Oct 1, 2019

As announced in Slack, we've shifted all the changes for 1.3.2 to 1.3.3 :(

1.3.2 release had no API changes or bug fixes at all and contained only changes necessary for Spring 5.2 GA (some of the reactive Flow bridges became public).

Meanwhile, most of the work is done and now I am mostly in evaluation and small performance tweaks phase.

@samlotti
Copy link

samlotti commented Oct 8, 2019

I'm having the same issue using ktor. 100% cpu utilization

Its appears randomly and stays at 100% until process is restarted. Is there any workaround until 1.3.3?

    DefaultDispatcher-worker-5" - Thread t@45
    java.lang.Thread.State: RUNNABLE
    at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
    at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)
    at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:93)
    at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)
    - locked <752867a8> (a sun.nio.ch.Util$3)
    - locked <5fce1119> (a java.util.Collections$UnmodifiableSet)
    - locked <63b5314> (a sun.nio.ch.EPollSelectorImpl)
    at sun.nio.ch.SelectorImpl.selectNow(SelectorImpl.java:105)
    at io.ktor.network.selector.ActorSelectorManager.process(ActorSelectorManager.kt:81)
    at io.ktor.network.selector.ActorSelectorManager$process$1.invokeSuspend(ActorSelectorManager.kt)
    at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
    at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:241)
    at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:594)
    at kotlinx.coroutines.scheduling.CoroutineScheduler.access$runSafely(CoroutineScheduler.kt:60)
    at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:740)

`

@madhead
Copy link

madhead commented Oct 8, 2019

I've tried to close the ActorSelectorManager implicitly and it seems to help:

ActorSelectorManager(Dispatchers.IO).use {
    aSocket(it)
        .tcp()
        .connect(InetSocketAddress(host, port)).use { socket ->
            val writeChannel = socket.openWriteChannel()
            val readChannel = socket.openReadChannel()

            writeChannel.writeStringUtf8(input.vowpalWabbitFormat) // just a string ending with two newlines (`\n`)
            writeChannel.flush()

            val payload = readChannel.readUTF8Line()

            RawOutput(payload!!) // return the result
        }
}

@fvasco
Copy link
Contributor

fvasco commented Oct 14, 2019

@Anton3
Copy link

Anton3 commented Oct 18, 2019

It looks like the issue is being worked on there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

10 participants