Skip to content

Commit 26b1589

Browse files
perf: improve gcir (#258)
Run jProfile and found that `toMap()` function inside the `ClientInitializeResponse` is a hotspot. Rather than using `gson` , manually turning the fields into a map. Huge improvement on this change: **using `perf-benchmark` test** | Before | After | | -- | -- | |![image](https://github.com/statsig-io/private-java-server-sdk/assets/158090588/2703693f-9ff6-461d-8c9d-34fc74e95490)| ![image](https://github.com/statsig-io/private-java-server-sdk/assets/158090588/9675395c-9da6-48f0-9171-e10d47fd3978)| ----- **using regression test** <img width="1534" alt="image" src="https://github.com/statsig-io/private-java-server-sdk/assets/158090588/19502cae-f0f7-4739-958b-0c11e5205178"> ----- **using jProfile** | Before | After | | -- | -- | | ![image](https://github.com/statsig-io/private-java-server-sdk/assets/158090588/930635b9-c109-4d33-a541-3f05443c0a7f)| ![image](https://github.com/statsig-io/private-java-server-sdk/assets/158090588/1cfe7034-45d9-4625-980d-7daa6dded0c4) | I would trust jProfile and regression test more 🙂
1 parent 36d37dc commit 26b1589

File tree

1 file changed

+32
-6
lines changed

1 file changed

+32
-6
lines changed

src/main/kotlin/com/statsig/sdk/ClientInitializeFormatter.kt

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package com.statsig.sdk
22

3-
import com.google.gson.Gson
43
import com.google.gson.annotations.SerializedName
5-
import com.google.gson.reflect.TypeToken
64

75
internal data class ClientInitializeResponse(
86
@SerializedName("feature_gates") var feature_gates: Map<String, ClientConfig>,
@@ -16,10 +14,20 @@ internal data class ClientInitializeResponse(
1614
@SerializedName("hash_used") var hash_used: String,
1715
@SerializedName("user_hash") var user_hash: String,
1816
) {
17+
1918
fun toMap(): Map<String, Any> {
20-
val gson = Gson()
21-
val json = gson.toJson(this)
22-
return gson.fromJson(json, object : TypeToken<Map<String, Any>>() {}.type)
19+
val map = mutableMapOf<String, Any>()
20+
map["feature_gates"] = feature_gates.mapValues { (_, config) -> config.toMap() }
21+
map["dynamic_configs"] = dynamic_configs.mapValues { (_, config) -> config.toMap() }
22+
map["layer_configs"] = layer_configs.mapValues { (_, config) -> config.toMap() }
23+
map["sdkParams"] = sdkParams
24+
map["has_updates"] = has_updates
25+
map["time"] = time
26+
map["generator"] = generator
27+
map["evaluated_keys"] = evaluated_keys
28+
map["hash_used"] = hash_used
29+
map["user_hash"] = user_hash
30+
return map
2331
}
2432

2533
fun isEmpty(): Boolean {
@@ -41,7 +49,24 @@ internal data class ClientConfig(
4149
@SerializedName("explicit_parameters") var explicitParameters: Array<String>? = null,
4250
@SerializedName("is_in_layer") var isInLayer: Boolean? = null,
4351
@SerializedName("is_device_based") var isDeviceBased: Boolean? = null,
44-
)
52+
) {
53+
fun toMap(): Map<String, Any?> {
54+
val map = mutableMapOf<String, Any?>()
55+
map["name"] = name
56+
map["value"] = value
57+
map["rule_id"] = ruleID
58+
map["secondary_exposures"] = secondaryExposures
59+
if (undelegatedSecondaryExposures != null) map["undelegated_secondary_exposures"] = undelegatedSecondaryExposures
60+
if (group != null) map["group"] = group
61+
if (allocatedExperimentName != null) map["allocated_experiment_name"] = allocatedExperimentName
62+
if (isUserInExperiment != null) map["is_user_in_experiment"] = isUserInExperiment
63+
if (isExperimentActive != null) map["is_experiment_active"] = isExperimentActive
64+
if (explicitParameters != null) map["explicit_parameters"] = explicitParameters
65+
if (isInLayer != null) map["is_in_layer"] = isInLayer
66+
if (isDeviceBased != null) map["is_device_based"] = isDeviceBased
67+
return map
68+
}
69+
}
4570

4671
internal class ClientInitializeFormatter(
4772
private val specStore: SpecStore,
@@ -158,6 +183,7 @@ internal class ClientInitializeFormatter(
158183
val evalResult = ConfigEvaluation()
159184
evalFun(user, configSpec, evalResult)
160185
val hashedName = hashName(configName)
186+
161187
val result = ClientConfig(
162188
hashedName,
163189
"value" to false,

0 commit comments

Comments
 (0)