mirror of
https://github.com/corda/corda.git
synced 2025-06-16 14:18:20 +00:00
Merge remote branch 'origin/master' into openjdk
This commit is contained in:
@ -149,16 +149,17 @@ public class HashMap<K, V> implements Map<K, V> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean containsValue(Object value) {
|
public boolean containsValue(Object value) {
|
||||||
if (array != null) {
|
if (array != null) {
|
||||||
int index = array.length - 1;
|
for (int i = 0; i < array.length; ++i) {
|
||||||
for (Cell<K, V> c = array[index]; c != null; c = c.next()) {
|
for (Cell<K, V> c = array[i]; c != null; c = c.next()) {
|
||||||
if (helper.equal(value, c.getValue())) {
|
if (helper.equal(value, c.getValue())) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public V get(Object key) {
|
public V get(Object key) {
|
||||||
@ -450,10 +451,12 @@ public class HashMap<K, V> implements Map<K, V> {
|
|||||||
|
|
||||||
public Entry<K, V> next() {
|
public Entry<K, V> next() {
|
||||||
if (hasNext()) {
|
if (hasNext()) {
|
||||||
if (currentCell != null && currentCell.next() != null) {
|
if (currentCell != null) {
|
||||||
previousCell = currentCell;
|
if (currentCell.next() != null) {
|
||||||
} else {
|
previousCell = currentCell;
|
||||||
previousCell = null;
|
} else {
|
||||||
|
previousCell = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
currentCell = nextCell;
|
currentCell = nextCell;
|
||||||
@ -490,6 +493,7 @@ public class HashMap<K, V> implements Map<K, V> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
currentCell = null;
|
currentCell = null;
|
||||||
|
-- size;
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
}
|
}
|
||||||
|
8
makefile
8
makefile
@ -159,6 +159,8 @@ common-cflags = $(warnings) -fno-rtti -fno-exceptions -fno-omit-frame-pointer \
|
|||||||
build-cflags = $(common-cflags) -fPIC -fvisibility=hidden \
|
build-cflags = $(common-cflags) -fPIC -fvisibility=hidden \
|
||||||
"-I$(JAVA_HOME)/include/linux" -I$(src) -pthread
|
"-I$(JAVA_HOME)/include/linux" -I$(src) -pthread
|
||||||
|
|
||||||
|
converter-cflags = -D__STDC_CONSTANT_MACROS
|
||||||
|
|
||||||
cflags = $(build-cflags)
|
cflags = $(build-cflags)
|
||||||
|
|
||||||
common-lflags = -lm -lz $(classpath-lflags)
|
common-lflags = -lm -lz $(classpath-lflags)
|
||||||
@ -220,7 +222,7 @@ ifeq ($(platform),darwin)
|
|||||||
|
|
||||||
ifeq ($(arch),powerpc)
|
ifeq ($(arch),powerpc)
|
||||||
ifneq (,$(filter i386 x86_64,$(build-arch)))
|
ifneq (,$(filter i386 x86_64,$(build-arch)))
|
||||||
converter-cflags = -DOPPOSITE_ENDIAN
|
converter-cflags += -DOPPOSITE_ENDIAN
|
||||||
endif
|
endif
|
||||||
openjdk-extra-cflags += -arch ppc
|
openjdk-extra-cflags += -arch ppc
|
||||||
cflags += -arch ppc
|
cflags += -arch ppc
|
||||||
@ -230,7 +232,7 @@ ifeq ($(platform),darwin)
|
|||||||
|
|
||||||
ifeq ($(arch),i386)
|
ifeq ($(arch),i386)
|
||||||
ifeq ($(build-arch),powerpc)
|
ifeq ($(build-arch),powerpc)
|
||||||
converter-cflags = -DOPPOSITE_ENDIAN
|
converter-cflags += -DOPPOSITE_ENDIAN
|
||||||
endif
|
endif
|
||||||
openjdk-extra-cflags += -arch i386
|
openjdk-extra-cflags += -arch i386
|
||||||
cflags += -arch i386
|
cflags += -arch i386
|
||||||
@ -240,7 +242,7 @@ ifeq ($(platform),darwin)
|
|||||||
|
|
||||||
ifeq ($(arch),x86_64)
|
ifeq ($(arch),x86_64)
|
||||||
ifeq ($(build-arch),powerpc)
|
ifeq ($(build-arch),powerpc)
|
||||||
converter-cflags = -DOPPOSITE_ENDIAN
|
converter-cflags += -DOPPOSITE_ENDIAN
|
||||||
endif
|
endif
|
||||||
openjdk-extra-cflags += -arch x86_64
|
openjdk-extra-cflags += -arch x86_64
|
||||||
cflags += -arch x86_64
|
cflags += -arch x86_64
|
||||||
|
24
src/heap.cpp
24
src/heap.cpp
@ -69,6 +69,7 @@ void assert(Context*, bool);
|
|||||||
System* system(Context*);
|
System* system(Context*);
|
||||||
void* tryAllocate(Context* c, unsigned size);
|
void* tryAllocate(Context* c, unsigned size);
|
||||||
void free(Context* c, const void* p, unsigned size);
|
void free(Context* c, const void* p, unsigned size);
|
||||||
|
void outOfMemory(Context*);
|
||||||
|
|
||||||
#ifdef USE_ATOMIC_OPERATIONS
|
#ifdef USE_ATOMIC_OPERATIONS
|
||||||
inline void
|
inline void
|
||||||
@ -359,7 +360,7 @@ class Segment {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
abort(context);
|
outOfMemory(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1708,7 +1709,8 @@ collect(Context* c)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void* tryAllocate(Context* c, unsigned size)
|
void*
|
||||||
|
tryAllocate(Context* c, unsigned size)
|
||||||
{
|
{
|
||||||
ACQUIRE(c->lock);
|
ACQUIRE(c->lock);
|
||||||
|
|
||||||
@ -1733,7 +1735,9 @@ void* tryAllocate(Context* c, unsigned size)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void free(Context* c, const void* p, unsigned size) {
|
void
|
||||||
|
free(Context* c, const void* p, unsigned size)
|
||||||
|
{
|
||||||
ACQUIRE(c->lock);
|
ACQUIRE(c->lock);
|
||||||
|
|
||||||
if (DebugAllocation) {
|
if (DebugAllocation) {
|
||||||
@ -1755,10 +1759,18 @@ void free(Context* c, const void* p, unsigned size) {
|
|||||||
c->count -= size;
|
c->count -= size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void free_(Context* c, const void* p, unsigned size) {
|
void
|
||||||
|
free_(Context* c, const void* p, unsigned size)
|
||||||
|
{
|
||||||
free(c, p, size);
|
free(c, p, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
outOfMemory(Context* c)
|
||||||
|
{
|
||||||
|
c->client->outOfMemory();
|
||||||
|
}
|
||||||
|
|
||||||
class MyHeap: public Heap {
|
class MyHeap: public Heap {
|
||||||
public:
|
public:
|
||||||
MyHeap(System* system, unsigned limit):
|
MyHeap(System* system, unsigned limit):
|
||||||
@ -1781,7 +1793,9 @@ class MyHeap: public Heap {
|
|||||||
|
|
||||||
virtual void* allocate(unsigned size) {
|
virtual void* allocate(unsigned size) {
|
||||||
void* p = local::tryAllocate(&c, size);
|
void* p = local::tryAllocate(&c, size);
|
||||||
expect(c.system, p);
|
if (p == 0) {
|
||||||
|
c.client->outOfMemory();
|
||||||
|
}
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,6 +49,7 @@ class Heap: public Allocator {
|
|||||||
virtual unsigned copiedSizeInWords(void*) = 0;
|
virtual unsigned copiedSizeInWords(void*) = 0;
|
||||||
virtual void copy(void*, void*) = 0;
|
virtual void copy(void*, void*) = 0;
|
||||||
virtual void walk(void*, Walker*) = 0;
|
virtual void walk(void*, Walker*) = 0;
|
||||||
|
virtual void outOfMemory() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual void setClient(Client* client) = 0;
|
virtual void setClient(Client* client) = 0;
|
||||||
|
@ -2136,6 +2136,21 @@ class HeapClient: public Heap::Client {
|
|||||||
::walk(m->rootThread, w, o, 0);
|
::walk(m->rootThread, w, o, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void outOfMemory() {
|
||||||
|
#ifdef AVIAN_HEAPDUMP
|
||||||
|
const char* path = findProperty(m->rootThread, "avian.heap.dump");
|
||||||
|
if (path) {
|
||||||
|
FILE* out = vm::fopen(path, "wb");
|
||||||
|
if (out) {
|
||||||
|
dumpHeap(m->rootThread, out);
|
||||||
|
fclose(out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif//AVIAN_HEAPDUMP
|
||||||
|
|
||||||
|
abort(m->system);
|
||||||
|
}
|
||||||
|
|
||||||
void dispose() {
|
void dispose() {
|
||||||
m->heap->free(this, sizeof(*this));
|
m->heap->free(this, sizeof(*this));
|
||||||
}
|
}
|
||||||
|
@ -648,15 +648,22 @@ class MySystem: public System {
|
|||||||
|
|
||||||
int rv = pthread_kill(target->thread, VisitSignal);
|
int rv = pthread_kill(target->thread, VisitSignal);
|
||||||
|
|
||||||
|
int result;
|
||||||
if (rv == 0) {
|
if (rv == 0) {
|
||||||
while (visitTarget) visitLock->wait(t, 0);
|
while (visitTarget) visitLock->wait(t, 0);
|
||||||
|
|
||||||
threadVisitor = 0;
|
result = 0;
|
||||||
|
|
||||||
return 0;
|
|
||||||
} else {
|
} else {
|
||||||
return -1;
|
visitTarget = 0;
|
||||||
|
|
||||||
|
result = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
threadVisitor = 0;
|
||||||
|
|
||||||
|
system->visitLock->notifyAll(t);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual uint64_t call(void* function, uintptr_t* arguments, uint8_t* types,
|
virtual uint64_t call(void* function, uintptr_t* arguments, uint8_t* types,
|
||||||
@ -876,7 +883,9 @@ handleSignal(int signal, siginfo_t* info, void* context)
|
|||||||
default: abort();
|
default: abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (system->oldHandlers[index].sa_flags & SA_SIGINFO) {
|
if (system->oldHandlers[index].sa_flags & SA_SIGINFO
|
||||||
|
and system->oldHandlers[index].sa_sigaction)
|
||||||
|
{
|
||||||
system->oldHandlers[index].sa_sigaction(signal, info, context);
|
system->oldHandlers[index].sa_sigaction(signal, info, context);
|
||||||
} else if (system->oldHandlers[index].sa_handler) {
|
} else if (system->oldHandlers[index].sa_handler) {
|
||||||
system->oldHandlers[index].sa_handler(signal);
|
system->oldHandlers[index].sa_handler(signal);
|
||||||
|
@ -16,8 +16,9 @@ import java.util.Arrays;
|
|||||||
* heap dump generated by Avian's heapdump.cpp. The output is a list
|
* heap dump generated by Avian's heapdump.cpp. The output is a list
|
||||||
* of classes (identified by number in the case of anonymous,
|
* of classes (identified by number in the case of anonymous,
|
||||||
* VM-internal classes), each followed by (1) the total memory
|
* VM-internal classes), each followed by (1) the total memory
|
||||||
* footprint of all instances of the class, and (2) the number of
|
* footprint of all instances of the class in machine words, and (2)
|
||||||
* instances. The output is ordered by instance memory footprint.
|
* the number of instances. The output is ordered by instance memory
|
||||||
|
* footprint.
|
||||||
*/
|
*/
|
||||||
public class DumpStats {
|
public class DumpStats {
|
||||||
private static final int Root = 0;
|
private static final int Root = 0;
|
||||||
@ -107,8 +108,16 @@ public class DumpStats {
|
|||||||
|
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void usageAndExit() {
|
||||||
|
System.err.println("usage: java DumpStats <heap dump> <word size>");
|
||||||
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
|
if (args.length != 2) {
|
||||||
|
usageAndExit();
|
||||||
|
}
|
||||||
|
|
||||||
Map<Integer, Record> map = read
|
Map<Integer, Record> map = read
|
||||||
(new BufferedInputStream(new FileInputStream(args[0])));
|
(new BufferedInputStream(new FileInputStream(args[0])));
|
||||||
|
|
||||||
@ -119,19 +128,22 @@ public class DumpStats {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
int wordSize = Integer.parseInt(args[1]);
|
||||||
|
|
||||||
int footprint = 0;
|
int footprint = 0;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (Record r: array) {
|
for (Record r: array) {
|
||||||
if (r.name == null) {
|
if (r.name == null) {
|
||||||
r.name = String.valueOf(r.key);
|
r.name = String.valueOf(r.key);
|
||||||
}
|
}
|
||||||
System.out.println(r.name + ": " + r.footprint + " " + r.count);
|
System.out.println
|
||||||
|
(r.name + ": " + (r.footprint * wordSize) + " " + r.count);
|
||||||
footprint += r.footprint;
|
footprint += r.footprint;
|
||||||
count += r.count;
|
count += r.count;
|
||||||
}
|
}
|
||||||
|
|
||||||
System.out.println();
|
System.out.println();
|
||||||
System.out.println("total: " + footprint + " " + count);
|
System.out.println("total: " + (footprint * wordSize) + " " + count);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class Record {
|
private static class Record {
|
||||||
|
358
test/extra/QueryDump.java
Normal file
358
test/extra/QueryDump.java
Normal file
@ -0,0 +1,358 @@
|
|||||||
|
package extra;
|
||||||
|
|
||||||
|
import java.io.PrintStream;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.BufferedInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.EOFException;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
public class QueryDump {
|
||||||
|
private static final int Root = 0;
|
||||||
|
private static final int Size = 1;
|
||||||
|
private static final int ClassName = 2;
|
||||||
|
private static final int Push = 3;
|
||||||
|
private static final int Pop = 4;
|
||||||
|
|
||||||
|
private static int readInt(InputStream in) throws IOException {
|
||||||
|
int b1 = in.read();
|
||||||
|
int b2 = in.read();
|
||||||
|
int b3 = in.read();
|
||||||
|
int b4 = in.read();
|
||||||
|
if (b4 == -1) throw new EOFException();
|
||||||
|
return (int) ((b1 << 24) | (b2 << 16) | (b3 << 8) | (b4));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String readString(InputStream in) throws IOException {
|
||||||
|
int count = readInt(in);
|
||||||
|
byte[] b = new byte[count];
|
||||||
|
int offset = 0;
|
||||||
|
int c;
|
||||||
|
while ((c = in.read(b, offset, b.length - offset)) != -1
|
||||||
|
&& offset < b.length)
|
||||||
|
{
|
||||||
|
offset += c;
|
||||||
|
}
|
||||||
|
if (offset != b.length) throw new EOFException();
|
||||||
|
return new String(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Record record(Map<Integer, Record> map, int key) {
|
||||||
|
Record r = map.get(key);
|
||||||
|
if (r == null) {
|
||||||
|
map.put(key, r = new Record(key));
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <T> void push(List<T> stack, T value) {
|
||||||
|
stack.add(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <T> T pop(List<T> stack) {
|
||||||
|
return stack.remove(stack.size() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <T> T peek(List<T> stack, int offset) {
|
||||||
|
return stack.get(stack.size() - 1 - offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <T> T peek(List<T> stack) {
|
||||||
|
return peek(stack, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Set<Node> nodes(Record record) {
|
||||||
|
if (record.nodes == null) {
|
||||||
|
record.nodes = new HashSet<Node>(2);
|
||||||
|
}
|
||||||
|
return record.nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void query(Map<Integer, Node> nodes, Record[] query,
|
||||||
|
List<Instance> stack, int index)
|
||||||
|
{
|
||||||
|
Node node = nodes.get(peek(stack, index).key);
|
||||||
|
if (node != null) {
|
||||||
|
int base = node.index();
|
||||||
|
for (int i = base + 1; i < query.length; ++i) {
|
||||||
|
int peek = index + i - base;
|
||||||
|
if (peek < stack.size()) {
|
||||||
|
Instance instance = peek(stack, peek);
|
||||||
|
if (query[i] == instance.record) {
|
||||||
|
TreeNode next = (TreeNode) nodes.get(instance);
|
||||||
|
if (next == null) {
|
||||||
|
nodes.put(instance.key, next = new TreeNode(instance, i));
|
||||||
|
}
|
||||||
|
next.children.add(node);
|
||||||
|
node = next;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index + query.length - base < stack.size()) {
|
||||||
|
nodes(peek(stack, index + query.length - base).record).add(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void query(Map<Integer, Node> nodes, Record[] query,
|
||||||
|
List<Instance> stack)
|
||||||
|
{
|
||||||
|
if (stack.size() > 1) {
|
||||||
|
Instance instance = peek(stack, 1);
|
||||||
|
if (instance != null && instance.record == query[0]) {
|
||||||
|
Node node = nodes.get(instance.key);
|
||||||
|
if (node == null) {
|
||||||
|
nodes.put(instance.key, new LeafNode(instance));
|
||||||
|
query(nodes, query, stack, 1);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
query(nodes, query, stack, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<Integer, Record> read(InputStream in,
|
||||||
|
String[] queryClasses)
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
|
boolean done = false;
|
||||||
|
boolean popped = false;
|
||||||
|
Map<Integer, Record> records = new HashMap();
|
||||||
|
Map<Integer, Node> nodes = new HashMap();
|
||||||
|
List<Instance> stack = new ArrayList();
|
||||||
|
Record[] query = new Record[queryClasses.length];
|
||||||
|
|
||||||
|
Record roots = new Record(-1, "<roots>");
|
||||||
|
records.put(roots.key, roots);
|
||||||
|
|
||||||
|
while (! done) {
|
||||||
|
int flag = in.read();
|
||||||
|
switch (flag) {
|
||||||
|
case Root: {
|
||||||
|
stack.clear();
|
||||||
|
push(stack, new Instance(readInt(in)));
|
||||||
|
|
||||||
|
query(nodes, query, stack);
|
||||||
|
|
||||||
|
popped = false;
|
||||||
|
// System.out.println("root " + last);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case ClassName: {
|
||||||
|
String name = readString(in);
|
||||||
|
Record r = record(records, peek(stack).key);
|
||||||
|
r.name = name;
|
||||||
|
|
||||||
|
for (int i = 0; i < queryClasses.length; ++i) {
|
||||||
|
if (queryClasses[i].equals(name)) {
|
||||||
|
query[i] = r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
query(nodes, query, stack);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case Push: {
|
||||||
|
int key = readInt(in);
|
||||||
|
|
||||||
|
if (! popped) {
|
||||||
|
peek(stack).record = record(records, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
push(stack, new Instance(key));
|
||||||
|
|
||||||
|
query(nodes, query, stack);
|
||||||
|
|
||||||
|
popped = false;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case Pop: {
|
||||||
|
pop(stack);
|
||||||
|
|
||||||
|
popped = true;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case Size: {
|
||||||
|
peek(stack).size = readInt(in);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case -1:
|
||||||
|
done = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new RuntimeException("bad flag: " + flag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return records;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String[] copy(String[] array, int offset, int length) {
|
||||||
|
String[] copy = new String[length];
|
||||||
|
if (length > 0) {
|
||||||
|
System.arraycopy(array, offset, copy, 0, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void visitLeaves(Set<Node> nodes, LeafVisitor visitor) {
|
||||||
|
for (Node n: nodes) {
|
||||||
|
n.visitLeaves(visitor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void usageAndExit() {
|
||||||
|
System.err.println("usage: java QueryDump <heap dump> <word size> " +
|
||||||
|
"<query class> ...");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
if (args.length < 3) {
|
||||||
|
usageAndExit();
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<Integer, Record> map = read
|
||||||
|
(new BufferedInputStream(new FileInputStream(args[0])),
|
||||||
|
copy(args, 2, args.length - 2));
|
||||||
|
|
||||||
|
for (Iterator<Record> it = map.values().iterator(); it.hasNext();) {
|
||||||
|
final Record r = it.next();
|
||||||
|
if (r.nodes == null) {
|
||||||
|
it.remove();
|
||||||
|
} else {
|
||||||
|
visitLeaves(r.nodes, new LeafVisitor() {
|
||||||
|
private Set<Instance> set = new HashSet();
|
||||||
|
|
||||||
|
public void visit(LeafNode node) {
|
||||||
|
if (! set.contains(node.instance)) {
|
||||||
|
r.footprint += node.instance.size;
|
||||||
|
++ r.count;
|
||||||
|
}
|
||||||
|
set.add(node.instance);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Record[] array = map.values().toArray(new Record[map.size()]);
|
||||||
|
Arrays.sort(array, new Comparator<Record>() {
|
||||||
|
public int compare(Record a, Record b) {
|
||||||
|
return b.footprint - a.footprint;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
int wordSize = Integer.parseInt(args[1]);
|
||||||
|
|
||||||
|
int footprint = 0;
|
||||||
|
int count = 0;
|
||||||
|
for (Record r: array) {
|
||||||
|
if (r.name == null) {
|
||||||
|
r.name = String.valueOf(r.key);
|
||||||
|
}
|
||||||
|
System.out.println
|
||||||
|
(r.name + ": " + (r.footprint * wordSize) + " " + r.count);
|
||||||
|
footprint += r.footprint;
|
||||||
|
count += r.count;
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println();
|
||||||
|
System.out.println("total: " + (footprint * wordSize) + " " + count);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Record {
|
||||||
|
public final int key;
|
||||||
|
public String name;
|
||||||
|
public int footprint;
|
||||||
|
public int count;
|
||||||
|
public Set<Node> nodes;
|
||||||
|
|
||||||
|
public Record(int key) {
|
||||||
|
this(key, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Record(int key, String name) {
|
||||||
|
this.key = key;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Instance {
|
||||||
|
public final int key;
|
||||||
|
public int size;
|
||||||
|
public Record record;
|
||||||
|
|
||||||
|
public Instance(int key) {
|
||||||
|
this.key = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "[" + key + " " + record + "]";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface Node {
|
||||||
|
public void visitLeaves(LeafVisitor visitor);
|
||||||
|
public int index();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class LeafNode implements Node {
|
||||||
|
public final Instance instance;
|
||||||
|
|
||||||
|
public LeafNode(Instance instance) {
|
||||||
|
this.instance = instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void visitLeaves(LeafVisitor visitor) {
|
||||||
|
visitor.visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int index() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class TreeNode implements Node {
|
||||||
|
public final Instance instance;
|
||||||
|
public final int index;
|
||||||
|
|
||||||
|
public final Set<Node> children = new HashSet(2);
|
||||||
|
|
||||||
|
public TreeNode(Instance instance, int index) {
|
||||||
|
this.instance = instance;
|
||||||
|
this.index = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void visitLeaves(LeafVisitor visitor) {
|
||||||
|
QueryDump.visitLeaves(children, visitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int index() {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface LeafVisitor {
|
||||||
|
public void visit(LeafNode node);
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user