почему доступ к отдельным элементам ByteBuffer медленнее, чем ByteArray с дополнительной копией? - PullRequest
1 голос
/ 16 апреля 2020

это часть анализатора camerax для вращения изображения: буфер y передается в метод set, а отдельные байты считываются через метод get или оператор []

private data class IImage(var byteArray: ByteArray= ByteArray(0), var width: Int=0, var height: Int=0)
{
    //set rotationDegrees to 0 to disable rotation
    fun Set(rotationDegrees:Int,buffer:ByteBuffer,w:Int,h:Int){
        if (byteArray.size != buffer.capacity()) byteArray =ByteArray(buffer.capacity()) //resize buffer
        if(rotationDegrees == 0 || rotationDegrees % 90 != 0){ buffer.get(byteArray); width=w; height=h}
        else
        {
            for (y in 0 until h) // we scan the array by rows
                for (x in 0 until w)
                    when (rotationDegrees) {
                        90 -> byteArray[x * h + h - y - 1] = buffer.get(x + y * w) // Fill from top-right toward left (CW)
                        180 -> byteArray[w * (h - y - 1) + w - x - 1] = buffer.get(x + y * w) // Fill from bottom-right toward up (CW)
                        270 -> byteArray[y + x * h] = buffer.get(y * w + w - x - 1) // The opposite (CCW) of 90 degrees
                    }
            if (rotationDegrees != 180) { height = w; width = h }
        }
    }
}

, и это тот же код, но с использованием дополнительного ByteArray

 private data class IImage2(var byteArray: ByteArray= ByteArray(0), var width: Int=0, var height: Int=0)
{
    //set rotationDegrees to 0 to disable rotation
    fun Set(rotationDegrees:Int,buffer:ByteBuffer,w:Int,h:Int){
        if (byteArray.size != buffer.capacity()) byteArray =ByteArray(buffer.capacity()) //resize buffer
        buffer.get(byteArray); width=w; height=h
        if(rotationDegrees == 0 || rotationDegrees % 90 != 0) return
        else
        {
            val tByteArray=ByteArray(byteArray.size)
            for (y in 0 until h) // we scan the array by rows
                for (x in 0 until w)
                    when (rotationDegrees) {
                        90 -> tByteArray[x * h + h - y - 1] = byteArray[x + y * w] // Fill from top-right toward left (CW)
                        180 -> tByteArray[w * (h - y - 1) + w - x - 1] = byteArray[x + y * w] // Fill from bottom-right toward up (CW)
                        270 -> tByteArray[y + x * h] = byteArray[y * w + w - x - 1] // The opposite (CCW) of 90 degrees
                    }
            byteArray=tByteArray
            if (rotationDegrees != 180) { height = w; width = h }
        }
    }
}

класс анализа хранит один экземпляр IImage или IImage2, код IImage дает 5: 7 к / с, а IImage - 9/10: 12 к / с последовательно на эмуляторе, почему создание другого ByteArray и копирование данных в 2 раза быстрее, чем доступ к отдельным байтам ByteBuffer

...