I'm developing an Android VPN app that fetches and tests V2Ray/Xray proxy configurations. I need to find working servers quickly, but my current implementation using libv2ray.measureOutboundDelay() is too slow and sometimes crashes.
Current Implementation
Test Flow:
- Download configs from multiple sources (~100-150 configs)
- Parse and validate them
- Test each config using
Libv2ray.measureOutboundDelay() - Return working configs sorted by ping
Issues:
- Slow: Testing 100 configs takes 5+ minutes
- Crashes:
OutOfMemoryErrorwhen testing many configs in parallel - Timeout: Some configs take 10+ seconds to test
- Resource intensive: Multiple Xray instances running simultaneously
What I've Tried
Approach 1: Parallel Testing with Coroutines
class RealPingTester(private val context: Context) {
companion object {
private const val TEST_URL = "http://www.gstatic.com/generate_204"
private const val MAX_PARALLEL_TESTS = 10
}
suspend fun testConfigsRealPing(
configs: List,
onProgress: (tested: Int, total: Int) -> Unit
): List = coroutineScope {
val semaphore = Semaphore(MAX_PARALLEL_TESTS)
configs.map { config ->
async(Dispatchers.IO) {
semaphore.withPermit {
val delay = realPing(config)
if (delay > 0 && delay < 8000) {
config.copy(
ping = delay.toInt(),
isWorking = true
)
} else {
null
}
}
}
}.awaitAll().filterNotNull()
}
private suspend fun realPing(profile: ProfileItem): Long {
return withContext(Dispatchers.IO) {
try {
// Generate V2Ray JSON config
val config = ProfileItemManager.generateProfileItem(profile)
// Test using libv2ray
val delay = withTimeoutOrNull(8000L) {
Libv2ray.measureOutboundDelay(config, TEST_URL)
} ?: -1L
delay
} catch (e: Exception) {
-1L
}
}
}
}
Result: Still too slow (~5 minutes for 100 configs), occasional crashes
Data Model
data class ProfileItem(
val configType: ConfigType, // VMESS, VLESS, TROJAN, SHADOWSOCKS
val server: String,
val serverPort: String,
val password: String, // UUID for VMess/VLESS, password for others
// Transport settings
val network: String? = null, // tcp, ws, grpc, etc.
val security: String? = null, // tls, reality, none
val path: String? = null,
val host: String? = null,
// Test results
var ping: Int = 0,
var isWorking: Boolean = false,
var lastTested: Long = 0
)
Questions
What's the best strategy to test 100+ proxy configs efficiently?
Should I use TCP ping first, then real test? How many configs should I test in parallel without crashes? What's the optimal timeout for measureOutboundDelay()? How does v2rayNG test configs so quickly?
They seem to test dozens of configs in seconds Is there a better libv2ray API I'm missing? Do they use a different approach? Are there alternatives to measureOutboundDelay()?
Can I test multiple configs with a single Xray instance? Should I implement native connection testing instead? Is there a batch testing API in libv2ray? Memory management:
How to prevent OutOfMemoryError when testing many configs? Should I test in smaller batches? How to properly cleanup Xray instances?