Если вы хотите быстро сравнить два блока кода / функций, вы можете сделать:
import timeit
start_time = timeit.default_timer()
func1()
print(timeit.default_timer() - start_time)
start_time = timeit.default_timer()
func2()
print(timeit.default_timer() - start_time)
Вы можете легко сделать такую же утилиту, используя HotSpot Serviceability Agent , который по умолчанию включен в JDK.
import sun.jvm.hotspot.memory.SystemDictionary;
import sun.jvm.hotspot.oops.InstanceKlass;
import sun.jvm.hotspot.oops.OopField;
import sun.jvm.hotspot.runtime.VM;
import sun.jvm.hotspot.tools.Tool;
public class InternedStrings extends Tool {
@Override
public void run() {
// Use Reflection-like API to reference String class and String.value field
SystemDictionary dict = VM.getVM().getSystemDictionary();
InstanceKlass stringKlass = (InstanceKlass) dict.find("java/lang/String", null, null);
OopField valueField = (OopField) stringKlass.findField("value", "[C");
// Counters
long[] stats = new long[2];
// Iterate through the String Pool printing out each String object
VM.getVM().getStringTable().stringsDo(s -> {
s.printValueOn(System.out);
System.out.println();
stats[0]++;
stats[1] += s.getObjectSize() + valueField.getValue(s).getObjectSize();
});
System.out.printf("%d strings with total size %d\n", stats[0], stats[1]);
}
public static void main(String[] args) {
// Use default SA tool launcher
new InternedStrings().execute(args);
}
}
Запустите инструмент: java -cp $JAVA_HOME/lib/sa-jdi.jar:. InternedStrings <PID>
Предупреждение: это внешний инструмент, который приостанавливает целевой процесс JVM на время выполнения.
Еще несколько примеров обслуживания здесь здесь .
UPDATE
Если вы хотите сканировать все строки, а не только в String Pool, вы можете использовать аналогичный подход; просто замените getStringTable().stringsDo()
на getObjectHeap().iterateObjectsOfKlass()
. Пример .
UPDATE 2
Также можно выполнить итерацию через Java-кучу из Java-процесса с помощью функции JVMTI IterateThroughHeap . Это будет менее навязчивым, чем агент Serviceability.
jint JNICALL stringCallback(jlong class_tag, jlong size, jlong* tag_ptr,
const jchar* value, jint value_length, void* user_data) {
wprintf(L"%.*s\n", value_length, value);
return 0;
}
JNIEXPORT void JNICALL Java_HeapIterator_printStrings(JNIEnv* env, jclass cls) {
jvmtiHeapCallbacks callbacks = {NULL, NULL, NULL, NULL, stringCallback};
(*jvmti)->IterateThroughHeap(jvmti, 0, NULL, &callbacks, NULL);
}
Полный пример: здесь .
IterateThroughHeap
делает , а не блокировать JVM. Выдержка из документации:During the execution of this function the state of the heap does not change: no objects are allocated, no objects are garbage collected, and the state of objects (including held values) does not change. As a result, threads executing Java programming language code, threads attempting to resume the execution of Java programming language code, and threads attempting to execute JNI functions are typically stalled.
Итак, это тоже «приостанавливает JVM». потому что необходимо обеспечить, чтобы объекты не менялись. – Markus Weninger 22 February 2016 в 14:33