Skip to content
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
10 changes: 10 additions & 0 deletions memory-vault/src/main/java/com/memoryvault/BackupManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,16 @@ class BackupManager(private val vaultFile: File) {
backupSize = restoredSize
)
}

suspend fun cleanupOldBackups(backupDir: File, maxBackups: Int) = withContext(Dispatchers.IO) {
val backups = backupDir.listFiles { file ->
file.name.startsWith("vault_") && file.name.endsWith(".mvlt.gz")
}?.sortedByDescending { it.lastModified() } ?: return@withContext
Comment on lines +80 to +82

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The goal of this PR is performance optimization, but this sorting method is inefficient. sortedByDescending may call it.lastModified() multiple times per file, which is a system call. To truly optimize this, you should cache the lastModified value before sorting, as mentioned in the PR description. This ensures lastModified() is called only once per file.

Suggested change
val backups = backupDir.listFiles { file ->
file.name.startsWith("vault_") && file.name.endsWith(".mvlt.gz")
}?.sortedByDescending { it.lastModified() } ?: return@withContext
val backups = backupDir.listFiles { file ->
file.name.startsWith("vault_") && file.name.endsWith(".mvlt.gz")
}?.let { files ->
files.map { it to it.lastModified() }
.sortedByDescending { it.second }
.map { it.first }
} ?: return@withContext

Comment on lines +79 to +82

if (backups.size > maxBackups) {
backups.drop(maxBackups).forEach { it.delete() }
}
Comment on lines +84 to +86
}
}

data class BackupResult(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.memoryvault

import kotlinx.coroutines.runBlocking
import org.junit.Test
import java.io.File
import kotlin.system.measureTimeMillis

class BackupManagerBenchmark {

@Test
fun benchmarkCleanup() {
runBlocking {
val tempDir = File(System.getProperty("java.io.tmpdir"), "backup_benchmark")
tempDir.mkdirs()

// Create 30000 dummy backup files
for (i in 1..30000) {
val file = File(tempDir, "vault_backup_$i.mvlt.gz")
file.createNewFile()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The benchmark is good, but all created files will have very similar lastModified timestamps. This might not fully represent a real-world scenario and could affect the sorting performance measurement. To make the benchmark more robust, consider explicitly setting different last modified times for the files. This will ensure the sorting algorithm is tested against a more varied dataset.

                file.createNewFile()
                file.setLastModified(System.currentTimeMillis() - i * 1000L)

}
Comment on lines +10 to +20

val manager = BackupManager(File("dummy"))

val time = measureTimeMillis {
manager.cleanupOldBackups(tempDir, 10)
}

// Print to standard error as it might bypass gradle's output buffering
System.err.println("Baseline Cleanup Time: $time ms")
tempDir.deleteRecursively()
Comment on lines +7 to +30
}
}
}
Loading