https://kotlinlang.org logo
Title
a

Andre Servidoni

07/27/2021, 2:55 PM
hello all, i’m trying to download a 512 mb file with ktor, but after 250mb the app throws OOM. I’m justing showing what I receive
val bytes = this
val byteBufferSize = 1024 * 100
val byteBuffer = ByteArray(byteBufferSize)

do {
    val currentRead = bytes.readAvailable(byteBuffer, 0, byteBufferSize)
    if (currentRead > 0) {
        println("received: $currentRead")
    }

} while (currentRead > 0)
a

Aleksei Tirman [JB]

07/28/2021, 10:04 AM
I cannot reproduce OOM with a following code:
val client = HttpClient(CIO)
client.get<HttpStatement>("<https://mirror.linux-ia64.org/ubuntu-releases/20.04.2.0/ubuntu-20.04.2.0-desktop-amd64.iso>").execute { response ->
    val channel: ByteReadChannel = response.receive()
    val byteBufferSize = 1024 * 100
    val byteBuffer = ByteArray(byteBufferSize)
    do {
        val currentRead = channel.readAvailable(byteBuffer, 0, byteBufferSize)
        if (currentRead > 0) {
            println("received: $currentRead")
        }
    } while (currentRead > 0)
}
Could you please share a complete code snippet?
a

Andre Servidoni

07/28/2021, 10:05 AM
did you tried on a mobile device? I’m using on android
a

Aleksei Tirman [JB]

07/28/2021, 10:08 AM
On a real device or an emulator?
a

Andre Servidoni

07/28/2021, 10:09 AM
real device. This is my client setup
private val httpClient = HttpClient(engineConfig) {
    expectSuccess = false

    install(JsonFeature) {
        val json = kotlinx.serialization.json.Json {
            ignoreUnknownKeys = true
            encodeDefaults = true
        }
        serializer = KotlinxSerializer(json)
    }
    install(Logging) {
        logger = Logger.DEFAULT
        level = LogLevel.ALL
    }
    defaultRequest {
        url {
            protocol = URLProtocol.HTTPS
            host = cloudHost
        }
    }
}
a

Aleksei Tirman [JB]

07/28/2021, 10:10 AM
What engine do you use?
a

Andre Servidoni

07/28/2021, 10:11 AM
CIO, since this part is on the shared code module
a

Aleksei Tirman [JB]

07/28/2021, 10:45 AM
I cannot reproduce it on a real device too. According to profiler data, GC doesn't let that happen.
a

Andre Servidoni

07/28/2021, 11:51 AM
😞 I run again and get the same issue, Failed to allocate and OOM
I don’t know what I’m doing wrong, my call is
suspend fun getFile(fileId: String, objectPath: String): HttpStatement =
    httpClient.get("$START_PATH/$userId/$fileId/$objectPath") {
            onDownload { received, contentLength ->
                println("Received $received bytes from $contentLength")
            }
        }
a

Aleksei Tirman [JB]

07/28/2021, 12:24 PM
Could you please share a sample project?
a

Andre Servidoni

07/28/2021, 12:26 PM
I can prepare one
another question
do {
        val currentRead = channel.readAvailable(byteBuffer, 0, byteBufferSize)
        if (currentRead > 0) {
            println("received: $currentRead")
        }
    } while (currentRead > 0)
I’m not using the offset, maybe I need to use it?
a

Aleksei Tirman [JB]

07/28/2021, 12:34 PM
This works fine with zero offset.
a

Andre Servidoni

07/28/2021, 12:41 PM
I tried with the offset like (offset += currentRead) and it just stop after 4-5MB downloaded
if I left it 0, it will download the same range infinitelly. I save what I was downloading in a file and after oom it was 10GB but the file is 512mb
a

Aleksei Tirman [JB]

07/28/2021, 12:43 PM
The following code works as expected:
val client = HttpClient(CIO)
val output = File("output.txt")

client.get<HttpStatement>("<https://ars.els-cdn.com/content/image/1-s2.0-S0960982203005347-mmc6.txt>").execute { response ->
    val channel: ByteReadChannel = response.receive()
    val byteBufferSize = 1024 * 5
    val byteBuffer = ByteArray(byteBufferSize)
    do {
        val currentRead = channel.readAvailable(byteBuffer, 0, byteBufferSize)
        output.appendBytes(byteBuffer)
        if (currentRead > 0) {
            println("received: $currentRead")
        }
    } while (currentRead > 0)
}