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

Optimize the Kotlin implementation to double performance #254

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 4 additions & 8 deletions Kotlin/build.gradle
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@

buildscript {

ext.kotlin_version = '1.3.72'
ext.kotlin_version = '2.0.0'

repositories {
google()
jcenter()
mavenCentral()
}

dependencies {
classpath 'com.android.tools.build:gradle:3.5.0'
classpath 'com.android.tools.build:gradle:8.5.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}

Expand All @@ -19,11 +19,7 @@ allprojects {

repositories {
google()
jcenter()
mavenCentral()
}

}

task clean(type: Delete) {
delete rootProject.buildDir
}
20 changes: 13 additions & 7 deletions Kotlin/demo/build.gradle
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

android {

compileSdkVersion 29
namespace "com.wolt.blurhashapp"
compileSdk 34

defaultConfig {
applicationId "com.wolt.blurhash"
minSdkVersion 14
targetSdkVersion 29
minSdkVersion 21
targetSdkVersion 34
versionCode 1
versionName "1.0"
}
Expand All @@ -21,9 +20,16 @@ android {
}
}

compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
kotlinOptions {
jvmTarget = "11"
}
}

dependencies {
implementation project(path: ':lib')
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation project(':lib')
implementation 'androidx.appcompat:appcompat:1.7.0'
}
7 changes: 4 additions & 3 deletions Kotlin/demo/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.wolt.blurhashapp">
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

<application
android:allowBackup="true"
Expand All @@ -9,7 +8,9 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name="com.wolt.blurhashapp.MainActivity">
<activity
android:name="com.wolt.blurhashapp.MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>

Expand Down
29 changes: 14 additions & 15 deletions Kotlin/demo/src/main/java/com/wolt/blurhashapp/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,33 @@ package com.wolt.blurhashapp

import android.graphics.Bitmap
import android.os.Bundle
import android.os.SystemClock
import android.view.View
import android.widget.EditText
import android.widget.ImageView
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import com.wolt.blurhashkt.BlurHashDecoder
import kotlinx.android.synthetic.main.activity_main.*
import kotlin.time.measureTime

class MainActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

val tvDecode: View = findViewById(R.id.tvDecode)
val etInput: EditText = findViewById(R.id.etInput)
val ivResult: ImageView = findViewById(R.id.ivResult)
val ivResultTime: TextView = findViewById(R.id.ivResultTime)

tvDecode.setOnClickListener {
var bitmap: Bitmap? = null
val time = timed {
val bitmap: Bitmap?
val time = measureTime {
bitmap = BlurHashDecoder.decode(etInput.text.toString(), 20, 12)
}
ivResult.setImageBitmap(bitmap)
ivResultTime.text = "Time: $time ms"
ivResultTime.text = "Time: ${time.inWholeMilliseconds} ms"
}
}

}

/**
* Executes a function and return the time spent in milliseconds.
*/
private inline fun timed(function: () -> Unit): Long {
val start = SystemClock.elapsedRealtime()
function()
return SystemClock.elapsedRealtime() - start
}

3 changes: 1 addition & 2 deletions Kotlin/gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
android.enableJetifier=true
android.useAndroidX=true
org.gradle.jvmargs=-Xmx1536m
org.gradle.jvmargs=-Xmx2048m
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
Expand Down
4 changes: 2 additions & 2 deletions Kotlin/gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#Mon Jul 01 10:02:38 EEST 2019
#Sun Jul 07 23:57:08 CEST 2024
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
22 changes: 13 additions & 9 deletions Kotlin/lib/build.gradle
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-android'

android {

compileSdkVersion 29
namespace "com.wolt.blurhashkt"
compileSdk 34

defaultConfig {
minSdkVersion 14
targetSdkVersion 29
minSdkVersion 21
targetSdkVersion 34
versionCode 1
versionName "1.0"

Expand All @@ -22,11 +21,16 @@ android {
}
}

compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
kotlinOptions {
jvmTarget = "11"
}
}

dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
androidTestImplementation 'junit:junit:4.13'
androidTestImplementation 'androidx.test:runner:1.2.0'
androidTestImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test:runner:1.6.1'
}
Original file line number Diff line number Diff line change
@@ -1,24 +1,15 @@
package com.wolt.blurhashkt

import android.graphics.Bitmap
import com.wolt.blurhashkt.BlurHashDecoder.clearCache
import com.wolt.blurhashkt.BlurHashDecoder.decode
import junit.framework.Assert.assertTrue
import org.junit.Before
import org.junit.Assert.assertArrayEquals
import org.junit.Test
import java.nio.ByteBuffer
import java.util.*


class BlurHashDecoderTest {
@Before
@Throws(Exception::class)
fun setUp() {
clearCache()
}

@Test
fun decode_smallImage_cacheEnabled_shouldGetTheSameBitmapInManyRequests() {
fun decode_smallImage_shouldGetTheSameBitmapInManyRequests() {
val bmp1 = decode("LEHV6nWB2yk8pyo0adR*.7kCMdnj", 20, 12)!!
val bmp2 = decode("LEHV6nWB2yk8pyo0adR*.7kCMdnj", 20, 12)!!
val bmp3 = decode("LEHV6nWB2yk8pyo0adR*.7kCMdnj", 20, 12)!!
Expand All @@ -28,61 +19,20 @@ class BlurHashDecoderTest {
}

@Test
fun decode_smallImage_differentCache_shouldGetTheSameBitmapInManyRequests() {
val bmp1 = decode("LEHV6nWB2yk8pyo0adR*.7kCMdnj", 20, 12)!!
val bmp2 = decode("LEHV6nWB2yk8pyo0adR*.7kCMdnj", 20, 12, useCache = false)!!
val bmp3 = decode("LEHV6nWB2yk8pyo0adR*.7kCMdnj", 20, 12)!!

bmp1.assertEquals(bmp2)
bmp2.assertEquals(bmp3)
}

@Test
fun decode_smallImage_cacheDisabled_shouldGetTheSameBitmapInManyRequests() {
val bmp1 = decode("LEHV6nWB2yk8pyo0adR*.7kCMdnj", 20, 12, useCache = false)!!
val bmp2 = decode("LEHV6nWB2yk8pyo0adR*.7kCMdnj", 20, 12, useCache = false)!!
val bmp3 = decode("LEHV6nWB2yk8pyo0adR*.7kCMdnj", 20, 12, useCache = false)!!

bmp1.assertEquals(bmp2)
bmp2.assertEquals(bmp3)
}

@Test
fun decode_bigImage_cacheEnabled_shouldGetTheSameBitmapInManyRequests() {
fun decode_bigImage_shouldGetTheSameBitmapInManyRequests() {
val bmp1 = decode("LEHV6nWB2yk8pyo0adR*.7kCMdnj", 100, 100)!!
val bmp2 = decode("LEHV6nWB2yk8pyo0adR*.7kCMdnj", 100, 100)!!
val bmp3 = decode("LEHV6nWB2yk8pyo0adR*.7kCMdnj", 100, 100)!!

bmp1.assertEquals(bmp2)
bmp2.assertEquals(bmp3)
}

@Test
fun decode_bigImage_differentCache_shouldGetTheSameBitmapInManyRequests() {
val bmp1 = decode("LEHV6nWB2yk8pyo0adR*.7kCMdnj", 100, 100)!!
val bmp2 = decode("LEHV6nWB2yk8pyo0adR*.7kCMdnj", 100, 100, useCache = false)!!
val bmp3 = decode("LEHV6nWB2yk8pyo0adR*.7kCMdnj", 100, 100)!!

bmp1.assertEquals(bmp2)
bmp2.assertEquals(bmp3)
}

@Test
fun decode_bigImage_cacheDisabled_shouldGetTheSameBitmapInManyRequests() {
val bmp1 = decode("LEHV6nWB2yk8pyo0adR*.7kCMdnj", 100, 100, useCache = false)!!
val bmp2 = decode("LEHV6nWB2yk8pyo0adR*.7kCMdnj", 100, 100, useCache = false)!!
val bmp3 = decode("LEHV6nWB2yk8pyo0adR*.7kCMdnj", 100, 100, useCache = false)!!

bmp1.assertEquals(bmp2)
bmp2.assertEquals(bmp3)
}
}

fun Bitmap.assertEquals(bitmap2: Bitmap) {
val buffer1: ByteBuffer = ByteBuffer.allocate(height * rowBytes)
copyPixelsToBuffer(buffer1)
val buffer2: ByteBuffer = ByteBuffer.allocate(bitmap2.height * bitmap2.rowBytes)
bitmap2.copyPixelsToBuffer(buffer2)
val equals = Arrays.equals(buffer1.array(), buffer2.array())
assertTrue(equals)
assertArrayEquals(buffer1.array(), buffer2.array())
}
1 change: 0 additions & 1 deletion Kotlin/lib/src/main/AndroidManifest.xml

This file was deleted.

Loading