|
@@ -61,8 +61,9 @@ public abstract class FileSystemCounterGroup<C extends Counter>
|
|
|
|
|
|
// C[] would need Array.newInstance which requires a Class<C> reference.
|
|
|
// Just a few local casts probably worth not having to carry it around.
|
|
|
- private final Map<String, Object[]> map =
|
|
|
- new ConcurrentSkipListMap<String, Object[]>();
|
|
|
+ // Initialized lazily, since in some situations millions of empty maps can
|
|
|
+ // waste a substantial (e.g. 4% as we observed) portion of the heap
|
|
|
+ private Map<String, Object[]> map;
|
|
|
private String displayName;
|
|
|
|
|
|
private static final Joiner NAME_JOINER = Joiner.on('_');
|
|
@@ -214,6 +215,9 @@ public abstract class FileSystemCounterGroup<C extends Counter>
|
|
|
@SuppressWarnings("unchecked")
|
|
|
public synchronized C findCounter(String scheme, FileSystemCounter key) {
|
|
|
final String canonicalScheme = checkScheme(scheme);
|
|
|
+ if (map == null) {
|
|
|
+ map = new ConcurrentSkipListMap<>();
|
|
|
+ }
|
|
|
Object[] counters = map.get(canonicalScheme);
|
|
|
int ord = key.ordinal();
|
|
|
if (counters == null) {
|
|
@@ -247,10 +251,12 @@ public abstract class FileSystemCounterGroup<C extends Counter>
|
|
|
protected abstract C newCounter(String scheme, FileSystemCounter key);
|
|
|
|
|
|
@Override
|
|
|
- public int size() {
|
|
|
+ public synchronized int size() {
|
|
|
int n = 0;
|
|
|
- for (Object[] counters : map.values()) {
|
|
|
- n += numSetCounters(counters);
|
|
|
+ if (map != null) {
|
|
|
+ for (Object[] counters : map.values()) {
|
|
|
+ n += numSetCounters(counters);
|
|
|
+ }
|
|
|
}
|
|
|
return n;
|
|
|
}
|
|
@@ -271,19 +277,23 @@ public abstract class FileSystemCounterGroup<C extends Counter>
|
|
|
* FileSystemGroup ::= #scheme (scheme #counter (key value)*)*
|
|
|
*/
|
|
|
@Override
|
|
|
- public void write(DataOutput out) throws IOException {
|
|
|
- WritableUtils.writeVInt(out, map.size()); // #scheme
|
|
|
- for (Map.Entry<String, Object[]> entry : map.entrySet()) {
|
|
|
- WritableUtils.writeString(out, entry.getKey()); // scheme
|
|
|
- // #counter for the above scheme
|
|
|
- WritableUtils.writeVInt(out, numSetCounters(entry.getValue()));
|
|
|
- for (Object counter : entry.getValue()) {
|
|
|
- if (counter == null) continue;
|
|
|
- @SuppressWarnings("unchecked")
|
|
|
- FSCounter c = (FSCounter) ((Counter)counter).getUnderlyingCounter();
|
|
|
- WritableUtils.writeVInt(out, c.key.ordinal()); // key
|
|
|
- WritableUtils.writeVLong(out, c.getValue()); // value
|
|
|
+ public synchronized void write(DataOutput out) throws IOException {
|
|
|
+ if (map != null) {
|
|
|
+ WritableUtils.writeVInt(out, map.size()); // #scheme
|
|
|
+ for (Map.Entry<String, Object[]> entry : map.entrySet()) {
|
|
|
+ WritableUtils.writeString(out, entry.getKey()); // scheme
|
|
|
+ // #counter for the above scheme
|
|
|
+ WritableUtils.writeVInt(out, numSetCounters(entry.getValue()));
|
|
|
+ for (Object counter : entry.getValue()) {
|
|
|
+ if (counter == null) continue;
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
+ FSCounter c = (FSCounter) ((Counter) counter).getUnderlyingCounter();
|
|
|
+ WritableUtils.writeVInt(out, c.key.ordinal()); // key
|
|
|
+ WritableUtils.writeVLong(out, c.getValue()); // value
|
|
|
+ }
|
|
|
}
|
|
|
+ } else {
|
|
|
+ WritableUtils.writeVInt(out, 0);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -310,8 +320,8 @@ public abstract class FileSystemCounterGroup<C extends Counter>
|
|
|
@Override
|
|
|
public Iterator<C> iterator() {
|
|
|
return new AbstractIterator<C>() {
|
|
|
- Iterator<Object[]> it = map.values().iterator();
|
|
|
- Object[] counters = it.hasNext() ? it.next() : null;
|
|
|
+ Iterator<Object[]> it = map != null ? map.values().iterator() : null;
|
|
|
+ Object[] counters = (it != null && it.hasNext()) ? it.next() : null;
|
|
|
int i = 0;
|
|
|
@Override
|
|
|
protected C computeNext() {
|
|
@@ -322,7 +332,7 @@ public abstract class FileSystemCounterGroup<C extends Counter>
|
|
|
if (counter != null) return counter;
|
|
|
}
|
|
|
i = 0;
|
|
|
- counters = it.hasNext() ? it.next() : null;
|
|
|
+ counters = (it != null && it.hasNext()) ? it.next() : null;
|
|
|
}
|
|
|
return endOfData();
|
|
|
}
|
|
@@ -343,8 +353,10 @@ public abstract class FileSystemCounterGroup<C extends Counter>
|
|
|
public synchronized int hashCode() {
|
|
|
// need to be deep as counters is an array
|
|
|
int hash = FileSystemCounter.class.hashCode();
|
|
|
- for (Object[] counters : map.values()) {
|
|
|
- if (counters != null) hash ^= Arrays.hashCode(counters);
|
|
|
+ if (map != null) {
|
|
|
+ for (Object[] counters : map.values()) {
|
|
|
+ if (counters != null) hash ^= Arrays.hashCode(counters);
|
|
|
+ }
|
|
|
}
|
|
|
return hash;
|
|
|
}
|