Fix datastore performance regression for update_withoutValueChange
Bug: 327517311
Test: ./gradlew :datastore:datastore-core:jvmTest
Change-Id: I5711ccbb5eb21b58075b628b743e476c145f3319
diff --git a/datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/MultiProcessDataStoreSingleProcessTest.kt b/datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/MultiProcessDataStoreSingleProcessTest.kt
index 9ecbb53..cb15048 100644
--- a/datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/MultiProcessDataStoreSingleProcessTest.kt
+++ b/datastore/datastore-core/src/androidInstrumentedTest/kotlin/androidx/datastore/core/MultiProcessDataStoreSingleProcessTest.kt
@@ -952,6 +952,17 @@
StrictMode.allowThreadDiskWrites()
}
+ @Test
+ fun testWriteSameValueSkipDisk() = runTest {
+ // write a non-default value to force a disk write
+ store.updateData { 10 }
+ assertThat(serializerConfig.writeCount).isEqualTo(1)
+
+ // write same value again
+ store.updateData { 10 }
+ assertThat(serializerConfig.writeCount).isEqualTo(1)
+ }
+
// Mutable wrapper around a byte
data class ByteWrapper(var byte: Byte) {
internal class ByteWrapperSerializer() : Serializer<ByteWrapper> {
diff --git a/datastore/datastore-core/src/commonMain/kotlin/androidx/datastore/core/DataStoreImpl.kt b/datastore/datastore-core/src/commonMain/kotlin/androidx/datastore/core/DataStoreImpl.kt
index 89f7160..35caa9c 100644
--- a/datastore/datastore-core/src/commonMain/kotlin/androidx/datastore/core/DataStoreImpl.kt
+++ b/datastore/datastore-core/src/commonMain/kotlin/androidx/datastore/core/DataStoreImpl.kt
@@ -341,7 +341,7 @@
// Check that curData has not changed...
curData.checkHashCode()
- if (curData != newData) {
+ if (curData.value != newData) {
writeData(newData, updateCache = true)
}
newData
diff --git a/datastore/datastore-core/src/commonTest/kotlin/androidx/datastore/core/SingleProcessDataStoreTest.kt b/datastore/datastore-core/src/commonTest/kotlin/androidx/datastore/core/SingleProcessDataStoreTest.kt
index 92f53a3..fb364a6 100644
--- a/datastore/datastore-core/src/commonTest/kotlin/androidx/datastore/core/SingleProcessDataStoreTest.kt
+++ b/datastore/datastore-core/src/commonTest/kotlin/androidx/datastore/core/SingleProcessDataStoreTest.kt
@@ -1142,6 +1142,17 @@
}
}
+ @Test
+ fun testWriteSameValueSkipDisk() = runTest {
+ // write a non-default value to force a disk write
+ store.updateData { 10 }
+ assertThat(serializerConfig.writeCount).isEqualTo(1)
+
+ // write same value again
+ store.updateData { 10 }
+ assertThat(serializerConfig.writeCount).isEqualTo(1)
+ }
+
private class TestingCorruptionHandler(
private val replaceWith: Byte? = null
) : CorruptionHandler<Byte> {
diff --git a/testutils/testutils-datastore/src/commonMain/kotlin/androidx/datastore/TestingOkioSerializer.kt b/testutils/testutils-datastore/src/commonMain/kotlin/androidx/datastore/TestingOkioSerializer.kt
index 61fa156..2a0a0bb 100644
--- a/testutils/testutils-datastore/src/commonMain/kotlin/androidx/datastore/TestingOkioSerializer.kt
+++ b/testutils/testutils-datastore/src/commonMain/kotlin/androidx/datastore/TestingOkioSerializer.kt
@@ -51,6 +51,7 @@
}
override suspend fun writeTo(t: Byte, sink: BufferedSink) {
+ config.writeCount++
if (config.failingWrite) {
throw IOException("I was asked to fail on writes")
}
diff --git a/testutils/testutils-datastore/src/commonMain/kotlin/androidx/datastore/TestingSerializerConfig.kt b/testutils/testutils-datastore/src/commonMain/kotlin/androidx/datastore/TestingSerializerConfig.kt
index 8186ad9..6c9c946 100644
--- a/testutils/testutils-datastore/src/commonMain/kotlin/androidx/datastore/TestingSerializerConfig.kt
+++ b/testutils/testutils-datastore/src/commonMain/kotlin/androidx/datastore/TestingSerializerConfig.kt
@@ -27,4 +27,7 @@
// TestSerializer uses the values from this list in sequence first before it always uses the
// value of failReadWithCorruptionException.
@Volatile var listOfFailReadWithCorruptionException: List<Boolean> = listOf(),
+ // This field enables the TestingSerializer to keep the count of file writes that is readable
+ // from the test methods.
+ @Volatile var writeCount: Int = 0,
)
diff --git a/testutils/testutils-datastore/src/jvmMain/kotlin/androidx/datastore/TestingSerializer.jvm.kt b/testutils/testutils-datastore/src/jvmMain/kotlin/androidx/datastore/TestingSerializer.jvm.kt
index 007d973..ef20c6c 100644
--- a/testutils/testutils-datastore/src/jvmMain/kotlin/androidx/datastore/TestingSerializer.jvm.kt
+++ b/testutils/testutils-datastore/src/jvmMain/kotlin/androidx/datastore/TestingSerializer.jvm.kt
@@ -51,6 +51,7 @@
}
override suspend fun writeTo(t: Byte, output: OutputStream) {
+ config.writeCount++
if (config.failingWrite) {
throw IOException("I was asked to fail on writes")
}