Private
Public Access
Minamp 1.4: faster connecting
- Remember the connection that worked and try it alone first next start - Prefer plain HTTP on the home network (each TLS handshake costs seconds on a 600 MHz phone); new setting "Encrypt at home too" to keep HTTPS - Try secure addresses one at a time instead of in parallel, so they don't all time out together - TLS 1.2 with session resumption: reconnects skip the full handshake - Cache certificate chains already verified; changing the trusted roots clears that cache and all TLS sessions - README: updated connection order; test: session resumption check and HandshakeProfile Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
58d21b6d68
commit
6fd17bc9c5
9 files changed
+284
-67
No files matched your search
@@ -0,0 +1,49 @@
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
import com.minamp.net.*;
|
||||
|
||||
/** Samples the handshake thread's stack to see where TLS time goes (run with -Xint). */
|
||||
public class HandshakeProfile {
|
||||
public static void main(String[] a) throws Exception {
|
||||
CertVerifier.setRootStore(new PlexTest.RootDir(new File(a[0])));
|
||||
final String url = a[1];
|
||||
final int rounds = Integer.parseInt(a[2]);
|
||||
final Map<String, Integer> buckets = new TreeMap<String, Integer>();
|
||||
final long[] times = new long[rounds];
|
||||
final Thread[] worker = new Thread[1];
|
||||
worker[0] = Threads.create(new Runnable() { public void run() {
|
||||
for (int i = 0; i < rounds; i++) {
|
||||
Http.evictAll();
|
||||
long t0 = System.nanoTime();
|
||||
try { Http.get(url, null, 60000).readAll(); } catch (Exception e) { System.out.println(e); }
|
||||
times[i] = (System.nanoTime() - t0) / 1000000;
|
||||
}
|
||||
}}, "hs");
|
||||
worker[0].start();
|
||||
while (worker[0].isAlive()) {
|
||||
StackTraceElement[] st = worker[0].getStackTrace();
|
||||
String b = "other";
|
||||
for (StackTraceElement e : st) {
|
||||
String c = e.getClassName() + "." + e.getMethodName();
|
||||
if (c.startsWith("com.minamp.net.CertVerifier.signatureValid")) { b = "our chain check: signature math"; break; }
|
||||
if (c.startsWith("com.minamp.net.CertVerifier")) { b = "our chain check: other"; break; }
|
||||
if (c.contains("Ed25519") || c.contains("X25519") || c.contains("rfc7748")) { b = "X25519 key exchange"; break; }
|
||||
if (c.contains("ECDSASigner") || c.contains("DSADigestSigner")) { b = "ECDSA verify (server signature)"; break; }
|
||||
if (c.contains("RSA")) { b = "RSA"; break; }
|
||||
if (c.contains("math.ec")) { b = "EC math (other)"; break; }
|
||||
if (c.contains("asn1")) { b = "ASN.1 parsing"; break; }
|
||||
if (c.contains("ChaCha") || c.contains("Poly1305") || c.contains("AES") || c.contains("GCM")) { b = "symmetric cipher"; break; }
|
||||
if (c.contains("Digest") || c.contains("HMAC") || c.contains("HKDF")) { b = "hashing/HKDF"; break; }
|
||||
if (c.contains("SecureRandom") || c.contains("Random")) { b = "random"; break; }
|
||||
if (c.contains("java.net") || c.contains("SocketInputStream") || c.contains("NioSocket") || c.contains("read0")) { b = "network wait"; break; }
|
||||
}
|
||||
Integer n = buckets.get(b); buckets.put(b, n == null ? 1 : n + 1);
|
||||
Thread.sleep(3);
|
||||
}
|
||||
int total = 0; for (int v : buckets.values()) total += v;
|
||||
System.out.println("handshake ms: " + Arrays.toString(times));
|
||||
List<Map.Entry<String, Integer>> l = new ArrayList<Map.Entry<String, Integer>>(buckets.entrySet());
|
||||
Collections.sort(l, new Comparator<Map.Entry<String, Integer>>() { public int compare(Map.Entry<String, Integer> x, Map.Entry<String, Integer> y) { return y.getValue() - x.getValue(); } });
|
||||
for (Map.Entry<String, Integer> e : l) System.out.printf(" %5.1f%% %s%n", 100.0 * e.getValue() / total, e.getKey());
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user