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

Performance follow ups #355

Merged
merged 6 commits into from
Dec 19, 2024
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -556,31 +556,27 @@ class ClientTest {
val time3 = end3.time - start3.time
Log.d("PERF", "Built a client with inboxId in ${time3 / 1000.0}s")

runBlocking { Client.connectToApiBackend(ClientOptions.Api(XMTPEnvironment.DEV, true)) }
val start4 = Date()
val buildClient3 = runBlocking {
Client().build(
fakeWallet.address,
runBlocking {
Client().create(
PrivateKeyBuilder(),
options = ClientOptions(
ClientOptions.Api(XMTPEnvironment.DEV, true),
appContext = context,
dbEncryptionKey = key
),
inboxId = client.inboxId,
apiClient = client.apiClient
)
}
val end4 = Date()
val time4 = end4.time - start4.time
Log.d("PERF", "Built a client with inboxId and apiClient in ${time4 / 1000.0}s")
Log.d("PERF", "Create a client after prebuilding apiClient in ${time4 / 1000.0}s")

assert(time2 < time1)
assert(time3 < time1)
assert(time3 < time2)
assert(time4 < time1)
assert(time4 < time2)
assert(time4 < time3)
assertEquals(client.inboxId, buildClient1.inboxId)
assertEquals(client.inboxId, buildClient2.inboxId)
assertEquals(client.inboxId, buildClient3.inboxId)
}
}
4 changes: 2 additions & 2 deletions library/src/main/java/libxmtp-version.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
Version: b5f32373
Version: eccce061
Branch: main
Date: 2024-12-17 19:57:56 +0000
Date: 2024-12-18 17:39:46 +0000
50 changes: 25 additions & 25 deletions library/src/main/java/org/xmtp/android/library/Client.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package org.xmtp.android.library

import android.content.Context
import com.google.protobuf.api
import kotlinx.coroutines.runBlocking
import org.xmtp.android.library.codecs.ContentCodec
import org.xmtp.android.library.codecs.TextCodec
Expand Down Expand Up @@ -49,7 +48,6 @@ class Client() {
lateinit var conversations: Conversations
lateinit var environment: XMTPEnvironment
lateinit var dbPath: String
lateinit var apiClient: XmtpApiClient
val libXMTPVersion: String = getVersionInfo()
private lateinit var ffiClient: FfiXmtpClient

Expand All @@ -62,14 +60,26 @@ class Client() {
registry
}

private val apiClientCache = mutableMapOf<String, XmtpApiClient>()
private val cacheLock = Any()

suspend fun connectToApiBackend(api: ClientOptions.Api): XmtpApiClient {
return connectToBackend(api.env.getUrl(), api.isSecure)
val cacheKey = api.env.getUrl()
return synchronized(cacheLock) {
apiClientCache.getOrPut(cacheKey) {
runBlocking {
connectToBackend(api.env.getUrl(), api.isSecure)
}
}
}
}

suspend fun getOrCreateInboxId(environment: ClientOptions.Api, address: String): String {
suspend fun getOrCreateInboxId(
api: ClientOptions.Api,
address: String,
): String {
var inboxId = getInboxIdForAddress(
host = environment.env.getUrl(),
isSecure = environment.isSecure,
api = connectToApiBackend(api),
accountAddress = address.lowercase()
)
if (inboxId.isNullOrBlank()) {
Expand All @@ -86,7 +96,6 @@ class Client() {
accountAddresses: List<String>,
appContext: Context,
api: ClientOptions.Api,
apiClient: XmtpApiClient? = null
): Map<String, Boolean> {
val accountAddress = "0x0000000000000000000000000000000000000000"
val inboxId = getOrCreateInboxId(api, accountAddress)
Expand All @@ -97,7 +106,7 @@ class Client() {
val dbPath = directoryFile.absolutePath + "/$alias.db3"

val ffiClient = createClient(
api = apiClient ?: connectToApiBackend(api),
api = connectToApiBackend(api),
db = dbPath,
encryptionKey = null,
accountAddress = accountAddress.lowercase(),
Expand All @@ -122,7 +131,6 @@ class Client() {
installationId: String,
inboxId: String,
environment: XMTPEnvironment,
apiClient: XmtpApiClient,
) : this() {
this.address = address.lowercase()
this.preferences = PrivatePreferences(client = this, ffiClient = libXMTPClient)
Expand All @@ -133,26 +141,24 @@ class Client() {
this.installationId = installationId
this.inboxId = inboxId
this.environment = environment
this.apiClient = apiClient
}

private suspend fun initializeV3Client(
address: String,
clientOptions: ClientOptions,
signingKey: SigningKey? = null,
inboxId: String? = null,
apiClient: XmtpApiClient? = null,
): Client {
val accountAddress = address.lowercase()
val recoveredInboxId = inboxId ?: getOrCreateInboxId(clientOptions.api, accountAddress)
val recoveredInboxId =
inboxId ?: getOrCreateInboxId(clientOptions.api, accountAddress)

val (ffiClient, dbPath, apiClient) = createFfiClient(
val (ffiClient, dbPath) = createFfiClient(
accountAddress,
recoveredInboxId,
clientOptions,
signingKey,
clientOptions.appContext,
apiClient,
)

return Client(
Expand All @@ -162,18 +168,16 @@ class Client() {
ffiClient.installationId().toHex(),
ffiClient.inboxId(),
clientOptions.api.env,
apiClient
)
}

// Function to create a V3 client with a signing key
suspend fun create(
account: SigningKey,
options: ClientOptions,
apiClient: XmtpApiClient? = null
): Client {
return try {
initializeV3Client(account.address, options, account, apiClient = apiClient)
initializeV3Client(account.address, options, account)
} catch (e: Exception) {
throw XMTPException("Error creating V3 client: ${e.message}", e)
}
Expand All @@ -184,10 +188,9 @@ class Client() {
address: String,
options: ClientOptions,
inboxId: String? = null,
apiClient: XmtpApiClient? = null,
): Client {
return try {
initializeV3Client(address, options, inboxId = inboxId, apiClient = apiClient)
initializeV3Client(address, options, inboxId = inboxId)
} catch (e: Exception) {
throw XMTPException("Error creating V3 client: ${e.message}", e)
}
Expand All @@ -199,8 +202,7 @@ class Client() {
options: ClientOptions,
signingKey: SigningKey?,
appContext: Context,
apiClient: XmtpApiClient? = null,
): Triple<FfiXmtpClient, String, XmtpApiClient> {
): Pair<FfiXmtpClient, String> {
val alias = "xmtp-${options.api.env}-$inboxId"

val mlsDbDirectory = options.dbDirectory
Expand All @@ -212,10 +214,8 @@ class Client() {
directoryFile.mkdir()
dbPath = directoryFile.absolutePath + "/$alias.db3"

val xmtpApiClient =
apiClient ?: connectToApiBackend(options.api)
val ffiClient = createClient(
api = xmtpApiClient,
api = connectToApiBackend(options.api),
db = dbPath,
encryptionKey = options.dbEncryptionKey,
accountAddress = accountAddress.lowercase(),
Expand All @@ -235,7 +235,7 @@ class Client() {
?: throw XMTPException("No signer passed but signer was required.")
ffiClient.registerIdentity(signatureRequest)
}
return Triple(ffiClient, dbPath, xmtpApiClient)
return Pair(ffiClient, dbPath)
}

suspend fun revokeAllOtherInstallations(signingKey: SigningKey) {
Expand Down
12 changes: 5 additions & 7 deletions library/src/main/java/xmtpv3.kt
Original file line number Diff line number Diff line change
Expand Up @@ -1628,7 +1628,7 @@ internal interface UniffiLib : Library {
): RustBuffer.ByValue

fun uniffi_xmtpv3_fn_func_get_inbox_id_for_address(
`host`: RustBuffer.ByValue, `isSecure`: Byte, `accountAddress`: RustBuffer.ByValue,
`api`: Pointer, `accountAddress`: RustBuffer.ByValue,
): Long

fun uniffi_xmtpv3_fn_func_get_version_info(
Expand Down Expand Up @@ -2345,7 +2345,7 @@ private fun uniffiCheckApiChecksums(lib: UniffiLib) {
if (lib.uniffi_xmtpv3_checksum_func_generate_private_preferences_topic_identifier() != 59124.toShort()) {
throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
}
if (lib.uniffi_xmtpv3_checksum_func_get_inbox_id_for_address() != 35414.toShort()) {
if (lib.uniffi_xmtpv3_checksum_func_get_inbox_id_for_address() != 19849.toShort()) {
throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
}
if (lib.uniffi_xmtpv3_checksum_func_get_version_info() != 29277.toShort()) {
Expand Down Expand Up @@ -12249,15 +12249,13 @@ fun `generatePrivatePreferencesTopicIdentifier`(`privateKey`: kotlin.ByteArray):
@Throws(GenericException::class)
@Suppress("ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE")
suspend fun `getInboxIdForAddress`(
`host`: kotlin.String,
`isSecure`: kotlin.Boolean,
`api`: XmtpApiClient,
`accountAddress`: kotlin.String,
): kotlin.String? {
return uniffiRustCallAsync(
UniffiLib.INSTANCE.uniffi_xmtpv3_fn_func_get_inbox_id_for_address(
FfiConverterString.lower(
`host`
), FfiConverterBoolean.lower(`isSecure`), FfiConverterString.lower(`accountAddress`),
FfiConverterTypeXmtpApiClient.lower(`api`),
FfiConverterString.lower(`accountAddress`),
),
{ future, callback, continuation ->
UniffiLib.INSTANCE.ffi_xmtpv3_rust_future_poll_rust_buffer(
Expand Down
Binary file modified library/src/main/jniLibs/arm64-v8a/libuniffi_xmtpv3.so
Binary file not shown.
Binary file modified library/src/main/jniLibs/armeabi-v7a/libuniffi_xmtpv3.so
Binary file not shown.
Binary file modified library/src/main/jniLibs/x86/libuniffi_xmtpv3.so
Binary file not shown.
Binary file modified library/src/main/jniLibs/x86_64/libuniffi_xmtpv3.so
Binary file not shown.
Loading