Rely more on the C library level DNS caching.
This change:
1. decreases the size of the libcore cache (to 16 hostnames).
2. brings the positive and negative TTLs way down (to 2s).
3. removes the dead code for the broken TTL-setting system properties.
Bug: 5841178
Bug: http://code.google.com/p/android/issues/detail?id=23878
Change-Id: Ib989c72bf3046300b4d59fa5ae49b8fe3ae6c2dc
diff --git a/luni/src/main/java/java/net/AddressCache.java b/luni/src/main/java/java/net/AddressCache.java
index 08f5d81..194761a 100644
--- a/luni/src/main/java/java/net/AddressCache.java
+++ b/luni/src/main/java/java/net/AddressCache.java
@@ -21,18 +21,20 @@
/**
* Implements caching for {@code InetAddress}. We use a unified cache for both positive and negative
* cache entries.
+ *
+ * TODO: benchmark and optimize InetAddress until we get to the point where we can just rely on
+ * the C library level caching. The main thing caching at this level buys us is avoiding repeated
+ * conversions from 'struct sockaddr's to InetAddress[].
*/
class AddressCache {
/**
* When the cache contains more entries than this, we start dropping the oldest ones.
* This should be a power of two to avoid wasted space in our custom map.
*/
- private static final int MAX_ENTRIES = 512;
+ private static final int MAX_ENTRIES = 16;
- // Default time-to-live for positive cache entries. 600 seconds (10 minutes).
- private static final long DEFAULT_POSITIVE_TTL_NANOS = 600 * 1000000000L;
- // Default time-to-live for negative cache entries. 10 seconds.
- private static final long DEFAULT_NEGATIVE_TTL_NANOS = 10 * 1000000000L;
+ // The TTL for the Java-level cache is short, just 2s.
+ private static final long TTL_NANOS = 2 * 1000000000L;
// The actual cache.
private final BasicLruCache<String, AddressCacheEntry> cache
@@ -47,13 +49,13 @@
* The absolute expiry time in nanoseconds. Nanoseconds from System.nanoTime is ideal
* because -- unlike System.currentTimeMillis -- it can never go backwards.
*
- * Unless we need to cope with DNS TTLs of 292 years, we don't need to worry about overflow.
+ * We don't need to worry about overflow with a TTL_NANOS of 2s.
*/
final long expiryNanos;
- AddressCacheEntry(Object value, long expiryNanos) {
+ AddressCacheEntry(Object value) {
this.value = value;
- this.expiryNanos = expiryNanos;
+ this.expiryNanos = System.nanoTime() + TTL_NANOS;
}
}
@@ -85,28 +87,7 @@
* certain length of time.
*/
public void put(String hostname, InetAddress[] addresses) {
- put(hostname, addresses, true);
- }
-
- /**
- * Associates the given 'detailMessage' with 'hostname'. The association will expire after a
- * certain length of time.
- */
- public void put(String hostname, String detailMessage) {
- put(hostname, detailMessage, false);
- }
-
- /**
- * Associates the given 'addresses' with 'hostname'. The association will expire after a
- * certain length of time.
- */
- public void put(String hostname, Object value, boolean isPositive) {
- // Calculate the expiry time.
- String propertyName = isPositive ? "networkaddress.cache.ttl" : "networkaddress.cache.negative.ttl";
- long defaultTtlNanos = isPositive ? DEFAULT_POSITIVE_TTL_NANOS : DEFAULT_NEGATIVE_TTL_NANOS;
- long expiryNanos = System.nanoTime() + defaultTtlNanos;
- // Update the cache.
- cache.put(hostname, new AddressCacheEntry(value, expiryNanos));
+ cache.put(hostname, new AddressCacheEntry(addresses));
}
/**
@@ -114,26 +95,6 @@
* negative cache entry.)
*/
public void putUnknownHost(String hostname, String detailMessage) {
- put(hostname, detailMessage);
- }
-
- private long customTtl(String propertyName, long defaultTtlNanos) {
- String ttlString = System.getProperty(propertyName, null);
- if (ttlString == null) {
- return System.nanoTime() + defaultTtlNanos;
- }
- try {
- long ttlS = Long.parseLong(ttlString);
- // For the system properties, -1 means "cache forever" and 0 means "don't cache".
- if (ttlS == -1) {
- return Long.MAX_VALUE;
- } else if (ttlS == 0) {
- return Long.MIN_VALUE;
- } else {
- return System.nanoTime() + ttlS * 1000000000L;
- }
- } catch (NumberFormatException ex) {
- return System.nanoTime() + defaultTtlNanos;
- }
+ cache.put(hostname, new AddressCacheEntry(detailMessage));
}
}
diff --git a/luni/src/main/java/java/net/InetAddress.java b/luni/src/main/java/java/net/InetAddress.java
index cada6bd..49029c6 100644
--- a/luni/src/main/java/java/net/InetAddress.java
+++ b/luni/src/main/java/java/net/InetAddress.java
@@ -116,15 +116,9 @@
* brackets.
*
* <h4>DNS caching</h4>
- * <p>On Android, addresses are cached for 600 seconds (10 minutes) by default. Failed lookups are
- * cached for 10 seconds. The underlying C library or OS may cache for longer, but you can control
- * the Java-level caching with the usual {@code "networkaddress.cache.ttl"} and
- * {@code "networkaddress.cache.negative.ttl"} system properties. These are parsed as integer
- * numbers of seconds, where the special value 0 means "don't cache" and -1 means "cache forever".
- *
- * <p>Note also that on Android – unlike the RI – the cache is not unbounded. The
- * current implementation caches around 512 entries, removed on a least-recently-used basis.
- * (Obviously, you should not rely on these details.)
+ * <p>In Android 4.0 (Ice Cream Sandwich) and earlier, DNS caching was performed both by
+ * InetAddress and by the C library, which meant that DNS TTLs could not be honored correctly.
+ * In later releases, caching is done solely by the C library and DNS TTLs are honored.
*
* @see Inet4Address
* @see Inet6Address