mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2025-04-09 04:18:11 +02:00
Increasing the speed of the Robohash SVG to buffer function
This commit is contained in:
parent
0429c4dc3a
commit
4b9a55e178
@ -30,9 +30,10 @@ import coil.fetch.Fetcher
|
||||
import coil.fetch.SourceResult
|
||||
import coil.request.ImageRequest
|
||||
import coil.request.Options
|
||||
import com.vitorpamplona.amethyst.commons.Robohash
|
||||
import com.vitorpamplona.amethyst.service.checkNotInMainThread
|
||||
import com.vitorpamplona.quartz.utils.Robohash
|
||||
import okio.Buffer
|
||||
import okio.buffer
|
||||
import okio.source
|
||||
import java.nio.charset.Charset
|
||||
|
||||
@Stable
|
||||
@ -43,14 +44,10 @@ class HashImageFetcher(
|
||||
) : Fetcher {
|
||||
override suspend fun fetch(): SourceResult {
|
||||
checkNotInMainThread()
|
||||
|
||||
val source =
|
||||
try {
|
||||
val buffer = Buffer()
|
||||
buffer.writeString(
|
||||
Robohash.assemble(data.toString(), isLightTheme),
|
||||
Charset.defaultCharset(),
|
||||
)
|
||||
buffer
|
||||
Robohash.assemble(data.toString(), isLightTheme).byteInputStream(Charset.defaultCharset()).source().buffer()
|
||||
} finally {
|
||||
}
|
||||
|
||||
|
@ -18,16 +18,20 @@
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.benchmark
|
||||
package com.vitorpamplona.amethyst.benchmark
|
||||
|
||||
import androidx.benchmark.junit4.BenchmarkRule
|
||||
import androidx.benchmark.junit4.measureRepeated
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import com.vitorpamplona.quartz.utils.Robohash
|
||||
import com.vitorpamplona.amethyst.commons.Robohash
|
||||
import junit.framework.TestCase.assertEquals
|
||||
import okio.Buffer
|
||||
import okio.buffer
|
||||
import okio.source
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import java.nio.charset.Charset
|
||||
|
||||
/**
|
||||
* Benchmark, which will execute on an Android device.
|
||||
@ -41,7 +45,7 @@ class RobohashBenchmark {
|
||||
|
||||
val warmHex = "f4f016c739b8ec0d6313540a8b12cf48a72b485d38338627ec9d427583551f9a"
|
||||
val testHex = "48a72b485d38338627ec9d427583551f9af4f016c739b8ec0d6313540a8b12cf"
|
||||
val resultingSVG =
|
||||
val expectedTestSVG =
|
||||
"<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 300 300\">" +
|
||||
"<defs>" +
|
||||
"<style>" +
|
||||
@ -196,7 +200,26 @@ class RobohashBenchmark {
|
||||
Robohash.assemble(warmHex, true)
|
||||
benchmarkRule.measureRepeated {
|
||||
val result = Robohash.assemble(testHex, true)
|
||||
assertEquals(resultingSVG, result)
|
||||
assertEquals(expectedTestSVG, result)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun createSVGInBufferCopy() {
|
||||
// warm up
|
||||
Robohash.assemble(warmHex, true)
|
||||
benchmarkRule.measureRepeated {
|
||||
val buffer = Buffer()
|
||||
buffer.writeString(Robohash.assemble(testHex, true), Charset.defaultCharset())
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun createSVGInBufferViaInputStream() {
|
||||
// warm up
|
||||
Robohash.assemble(warmHex, true)
|
||||
benchmarkRule.measureRepeated {
|
||||
Robohash.assemble(testHex, true).byteInputStream(Charset.defaultCharset()).source().buffer()
|
||||
}
|
||||
}
|
||||
}
|
@ -35,6 +35,8 @@ android {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation project(path: ':quartz')
|
||||
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
|
||||
|
@ -18,10 +18,9 @@
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.utils
|
||||
package com.vitorpamplona.amethyst.commons
|
||||
|
||||
import android.util.Log
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.vitorpamplona.quartz.crypto.CryptoUtils
|
||||
import com.vitorpamplona.quartz.encoders.Hex
|
||||
import com.vitorpamplona.quartz.encoders.HexValidator
|
||||
@ -55,9 +54,7 @@ object Robohash {
|
||||
private fun reduce(
|
||||
start: Int,
|
||||
channel: Byte,
|
||||
): Int {
|
||||
return (start + (channel.toUByte().toInt() * 0.3906f)).toInt()
|
||||
}
|
||||
) = (start + (channel.toUByte().toInt() * 0.3906f)).toInt()
|
||||
|
||||
private fun bytesToRGB(
|
||||
r: Byte,
|
||||
@ -85,6 +82,7 @@ object Robohash {
|
||||
Log.w("Robohash", "$msg is not a hex")
|
||||
CryptoUtils.sha256(msg.toByteArray())
|
||||
}
|
||||
|
||||
val bgColor = bytesToRGB(hash[0], hash[1], hash[2], isLightTheme)
|
||||
val fgColor = bytesToRGB(hash[3], hash[4], hash[5], !isLightTheme)
|
||||
val body = bodies[byteMod10(hash[6])]
|
||||
@ -110,41 +108,42 @@ object Robohash {
|
||||
BACKGROUND.length +
|
||||
END.length
|
||||
|
||||
val result = StringBuilder(capacity)
|
||||
val result =
|
||||
buildString(capacity) {
|
||||
append(HEADER)
|
||||
|
||||
result.append(HEADER)
|
||||
append(".cls-bg{fill:")
|
||||
append(bgColor)
|
||||
append(";}.cls-fill-1{fill:")
|
||||
append(fgColor)
|
||||
append(";}.cls-fill-2{fill:")
|
||||
append(fgColor)
|
||||
append(";}")
|
||||
|
||||
result.append(".cls-bg{fill:")
|
||||
result.append(bgColor)
|
||||
result.append(";}.cls-fill-1{fill:")
|
||||
result.append(fgColor)
|
||||
result.append(";}.cls-fill-2{fill:")
|
||||
result.append(fgColor)
|
||||
result.append(";}")
|
||||
append(body.style)
|
||||
append(face.style)
|
||||
append(eye.style)
|
||||
append(mouth.style)
|
||||
append(accessory.style)
|
||||
|
||||
result.append(body.style)
|
||||
result.append(face.style)
|
||||
result.append(eye.style)
|
||||
result.append(mouth.style)
|
||||
result.append(accessory.style)
|
||||
append(MID)
|
||||
|
||||
result.append(MID)
|
||||
append(BACKGROUND)
|
||||
append(body.paths)
|
||||
append(face.paths)
|
||||
append(eye.paths)
|
||||
append(mouth.paths)
|
||||
append(accessory.paths)
|
||||
|
||||
result.append(BACKGROUND)
|
||||
result.append(body.paths)
|
||||
result.append(face.paths)
|
||||
result.append(eye.paths)
|
||||
result.append(mouth.paths)
|
||||
result.append(accessory.paths)
|
||||
append(END)
|
||||
}
|
||||
|
||||
result.append(END)
|
||||
check(result.length == capacity) { "${result.length} was different from $capacity" }
|
||||
|
||||
val resultStr = result.toString()
|
||||
check(resultStr.length == capacity) { "${resultStr.length} was different from $capacity" }
|
||||
return resultStr
|
||||
return result
|
||||
}
|
||||
|
||||
@Immutable private data class Part(val style: String, val paths: String)
|
||||
private data class Part(val style: String, val paths: String)
|
||||
|
||||
const val HEADER =
|
||||
"<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 300 300\"><defs><style>"
|
Loading…
x
Reference in New Issue
Block a user