How to Efficiently Test V2Ray/Xray Configs in Android App Using libv2ray?

5 days ago 7
ARTICLE AD BOX

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: OutOfMemoryError when 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<ProfileItem>, onProgress: (tested: Int, total: Int) -> Unit ): List<ProfileItem> = 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?

Read Entire Article