2 Commits

Author SHA1 Message Date
zarazaex69 a04c53a045 fix: real ping IPC stalls by batching and throttling UI updates 2026-04-21 04:27:37 +03:00
zarazaex69 278095015b feat: remove apk 2026-04-21 03:06:16 +03:00
5 changed files with 78 additions and 6 deletions
@@ -164,6 +164,7 @@ object AppConfig {
const val MSG_MEASURE_CONFIG_CANCEL = 72
const val MSG_MEASURE_CONFIG_NOTIFY = 73
const val MSG_MEASURE_CONFIG_FINISH = 74
const val MSG_MEASURE_CONFIG_BATCH = 75
/** Notification channel IDs and names. */
const val RAY_NG_CHANNEL_ID = "RAY_NG_M_CH_ID"
@@ -0,0 +1,14 @@
package xyz.zarazaex.olc.dto
import java.io.Serializable
data class PingResultItem(
val guid: String,
val delay: Long
) : Serializable
data class PingProgressUpdate(
val results: ArrayList<PingResultItem>,
val finished: Int,
val total: Int
) : Serializable
@@ -6,8 +6,12 @@ import kotlinx.coroutines.CoroutineName
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import xyz.zarazaex.olc.AppConfig
import xyz.zarazaex.olc.dto.PingProgressUpdate
import xyz.zarazaex.olc.dto.PingResultItem
import xyz.zarazaex.olc.handler.SettingsManager
import xyz.zarazaex.olc.handler.V2RayNativeManager
import xyz.zarazaex.olc.handler.V2rayConfigManager
@@ -29,12 +33,26 @@ class RealPingWorkerService(
private val totalCount = AtomicInteger(guids.size)
private val finishedCount = AtomicInteger(0)
private val pendingResults = ArrayList<PingResultItem>()
private val pendingLock = Any()
private val delayTestUrl = SettingsManager.getDelayTestUrl()
companion object {
private const val RESULT_BATCH_SIZE = 32
private const val FLUSH_INTERVAL_MS = 1000L
}
data class PingItem(val guid: String, val config: String)
fun start() {
scope.launch(Dispatchers.IO) {
while (isActive) {
delay(FLUSH_INTERVAL_MS)
flushPendingResults()
}
}
scope.launch(Dispatchers.IO) {
try {
// Prepare configurations for batch test and shuffle for better async feel
@@ -67,8 +85,10 @@ class RealPingWorkerService(
)
}
flushPendingResults()
onFinish("0")
} catch (e: Exception) {
flushPendingResults()
onFinish("-1")
} finally {
cancel()
@@ -78,14 +98,42 @@ class RealPingWorkerService(
private fun reportResult(guid: String, delay: Long) {
val finished = finishedCount.incrementAndGet()
val total = guids.size
var readyBatch: PingProgressUpdate? = null
synchronized(pendingLock) {
pendingResults.add(PingResultItem(guid, delay))
if (pendingResults.size >= RESULT_BATCH_SIZE || finished >= totalCount.get()) {
readyBatch = createProgressUpdateLocked(finished)
pendingResults.clear()
}
}
readyBatch?.let(::sendBatchUpdate)
}
// Notify UI about the individual result
MessageUtil.sendMsg2UI(context, AppConfig.MSG_MEASURE_CONFIG_SUCCESS, Pair(guid, delay))
private fun flushPendingResults() {
val finished = finishedCount.get()
val update =
synchronized(pendingLock) {
if (pendingResults.isEmpty()) {
null
} else {
createProgressUpdateLocked(finished).also { pendingResults.clear() }
}
}
update?.let(::sendBatchUpdate)
}
// Notify UI about progress
val left = total - finished
MessageUtil.sendMsg2UI(context, AppConfig.MSG_MEASURE_CONFIG_NOTIFY, "$left / $total")
private fun createProgressUpdateLocked(finished: Int): PingProgressUpdate {
return PingProgressUpdate(
results = ArrayList(pendingResults),
finished = finished,
total = totalCount.get()
)
}
private fun sendBatchUpdate(update: PingProgressUpdate) {
MessageUtil.sendMsg2UI(context, AppConfig.MSG_MEASURE_CONFIG_BATCH, update)
val left = (update.total - update.finished).coerceAtLeast(0)
MessageUtil.sendMsg2UI(context, AppConfig.MSG_MEASURE_CONFIG_NOTIFY, "$left / ${update.total}")
}
fun cancel() {
@@ -15,6 +15,7 @@ import xyz.zarazaex.olc.AngApplication
import xyz.zarazaex.olc.AppConfig
import xyz.zarazaex.olc.R
import xyz.zarazaex.olc.dto.GroupMapItem
import xyz.zarazaex.olc.dto.PingProgressUpdate
import xyz.zarazaex.olc.dto.ServersCache
import xyz.zarazaex.olc.dto.SubscriptionCache
import xyz.zarazaex.olc.dto.SubscriptionUpdateResult
@@ -628,6 +629,14 @@ class MainViewModel(application: Application) : AndroidViewModel(application) {
updateListAction.value = getPosition(resultPair.first)
}
AppConfig.MSG_MEASURE_CONFIG_BATCH -> {
val update = intent.serializable<PingProgressUpdate>("content") ?: return
update.results.forEach { result ->
MmkvManager.encodeServerTestDelayMillis(result.guid, result.delay)
}
updateListAction.value = -1
}
AppConfig.MSG_MEASURE_CONFIG_NOTIFY -> {
val content = intent.getStringExtra("content")
updateTestResultAction.value =
BIN
View File
Binary file not shown.