Kotlin i.inc()比i ++慢10倍?

时间:2016-04-05 23:24:53

标签: kotlin

所以今天我了解了kotlin中的num.inc()功能,并决定在我的代码中实现它。毋庸置疑,这为我的代码增加了10倍的延迟时间(从~400ms到4000 + ms)

这是我传统方式的例子(i ++,400ms)

package com.beaudoin

import java.io.BufferedWriter
import java.io.FileInputStream
import java.io.FileWriter
import java.nio.channels.FileChannel

fun main(args: Array<String>) {
    val s = System.currentTimeMillis()

    val channel = FileInputStream("client.dll").channel
    val buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size())
    val data = ByteArray(buffer.capacity())
    buffer.get(data)

    val writer = BufferedWriter(FileWriter("dump.txt", false))
    val bytes = ByteArray(16)

    var offset = 0
    var i = 0
    while (i < data.size) {
        for (j in bytes.indices) {
            bytes[j] = data[i++]
        }
        writer.write(HexRow(offset, bytes).toString())
        writer.newLine()
        offset += 16
    }

    writer.close()

    println(System.currentTimeMillis() - s)
}

private val HEX_ARRAY = "0123456789ABCDEF".toCharArray()
private val bytes = ByteArray(4);

class HexRow(val offset: Int, val values: ByteArray) {

    fun bytesToChar(bytes: ByteArray, width: Int): CharArray {
        val hexChars = CharArray((bytes.size * 2) + (bytes.size / width))

        for (i in bytes.indices) {
            val v = bytes[i].toInt() and 0xFF
            val idx = (i * 2) + i / width

            hexChars[idx] = HEX_ARRAY[v.ushr(4)]
            hexChars[idx + 1] = HEX_ARRAY[v and 0x0F]
            if (idx + 2 < hexChars.size) {
                hexChars[idx + 2] = ' '
            }
        }
        return hexChars;
    }

    fun bytesToHex(value: Int) = String(bytesToChar(toByteArray(value), 6))

    fun bytesToHex(bytes: ByteArray) = String(bytesToChar(bytes, 1))

    fun toByteArray(value: Int): ByteArray {
        bytes[0] = value.ushr(24).toByte()
        bytes[1] = value.ushr(16).toByte()
        bytes[2] = value.ushr(8).toByte()
        bytes[3] = value.toByte()
        return bytes
    }

    override fun toString() = bytesToHex(offset) + " " + bytesToHex(values)

}

以下是使用i.inc()(4000ms +)

的代码
package com.beaudoin

import java.io.BufferedWriter
import java.io.FileInputStream
import java.io.FileWriter
import java.nio.channels.FileChannel

fun main(args: Array<String>) {
    val s = System.currentTimeMillis()

    val channel = FileInputStream("client.dll").channel
    val buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size())
    val data = ByteArray(buffer.capacity())
    buffer.get(data)

    val writer = BufferedWriter(FileWriter("dump.txt", false))
    val bytes = ByteArray(16)

    var offset = 0
/*  var i = 0
    while (i < data.size) {
        for (j in bytes.indices) {
            bytes[j] = data[i++]
        }
        writer.write(HexRow(offset, bytes).toString())
        writer.newLine()
        offset += 16
    }*/

    for (i in data.indices) {
        for (j in bytes.indices) {
            bytes[j] = data[i]
            i.inc()
        }
        writer.write(HexRow(offset, bytes).toString())
        writer.newLine()
        offset += 16
    }

    writer.close()

    println(System.currentTimeMillis() - s)
}

private val HEX_ARRAY = "0123456789ABCDEF".toCharArray()
private val bytes = ByteArray(4);

class HexRow(val offset: Int, val values: ByteArray) {

    fun bytesToChar(bytes: ByteArray, width: Int): CharArray {
        val hexChars = CharArray((bytes.size * 2) + (bytes.size / width))

        for (i in bytes.indices) {
            val v = bytes[i].toInt() and 0xFF
            val idx = (i * 2) + i / width

            hexChars[idx] = HEX_ARRAY[v.ushr(4)]
            hexChars[idx + 1] = HEX_ARRAY[v and 0x0F]
            if (idx + 2 < hexChars.size) {
                hexChars[idx + 2] = ' '
            }
        }
        return hexChars;
    }

    fun bytesToHex(value: Int) = String(bytesToChar(toByteArray(value), 6))

    fun bytesToHex(bytes: ByteArray) = String(bytesToChar(bytes, 1))

    fun toByteArray(value: Int): ByteArray {
        bytes[0] = value.ushr(24).toByte()
        bytes[1] = value.ushr(16).toByte()
        bytes[2] = value.ushr(8).toByte()
        bytes[3] = value.toByte()
        return bytes
    }

    override fun toString() = bytesToHex(offset) + " " + bytesToHex(values)

}

有人可以告诉我为什么i.inc()比i ++慢得多吗?

P.S:将client.dll替换为任何文件(应该是~12mb以获得准确到我的数字或只是在这里下载我的测试文件here

1 个答案:

答案 0 :(得分:7)

代码中的

inc()调用完全是多余的:它不会更改变量:

var x = 0
x.inc()
println(x) // 0

至于运行时间的差异,即使两种实现的语义也不同:

  • 第一个片段:

    while (i < data.size) {
        for (j in bytes.indices) {
            bytes[j] = data[i++]
        }
        //...
    }
    

    内部循环更改i,因此对于每个while都不会是i的迭代,i的某些(甚至是大多数) }将被跳过。

  • 第二个片段:

    for (i in data.indices) {
        for (j in bytes.indices) {
            bytes[j] = data[i] // removed redundant i.inc()
        }
        //...
    }
    

    在外循环中为每个i调用内循环,因此需要更长的时间。

相关问题