Я пытаюсь использовать синхронизированный блок Java с помощью ASM. Проблема в том, что после инструментирования время выполнения синхронизированного блока занимает больше времени. Здесь оно увеличивается с 2 мс до 200 мс на Linux.
Я реализую это, идентифицируя код операции MonitorEnter и MonitorExit.
Я пытаюсь инструментировать на трех уровнях 1. непосредственно перед MonitorEnter 2. после MonitorEnter 3. Перед MonitorExit. 1 и 3 вместе работают нормально, но когда я делаю 2, время выполнения резко увеличивается.
Даже если мы настроим еще один SOP-оператор, предназначенный для однократного выполнения, он даст более высокие значения. Вот пример кода (простое число, 10 циклов):
for(int w=0;w<10;w++){
synchronized(s){
long t1 = System.currentTimeMillis();
long num = 2000;
for (long i = 1; i < num; i++) {
long p = i;
int j;
for (j = 2; j < p; j++) {
long n = p % i;
}
}
long t2 = System.currentTimeMillis();
System.out.println("Time>>>>>>>>>>>> " + (t2-t1) );
}
Здесь код для инструментария (здесь System.currentMilliSeconds() дает время, когда произошло инструментирование, это не показатель времени выполнения, время выполнения указано в предыдущем операторе SOP):
public void visitInsn(int opcode)
{
switch(opcode)
{
// Scenario 1
case 194:
visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io /PrintStream;");
visitLdcInsn("TIME Arrive: "+System.currentTimeMillis());
visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V");
break;
// scenario 3
case 195:
visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
visitLdcInsn("TIME exit : "+System.currentTimeMillis());
visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V");
break;
}
super.visitInsn(opcode);
// scenario 2
if(opcode==194)
{
visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
visitLdcInsn("TIME enter: "+System.currentTimeMillis());
visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V");
}
}
Я не могу найти причину, почему это происходит и как это исправить.
Заранее спасибо.
currentTimeMillis
вызова находятся в синхронизированном блоке. Кстати, что такоеs
? Что вы знаете о конфликте, происходящем при синхронизации этого объекта? - person Holger   schedule 25.11.2013String
— необычный объект для синхронизации. Не рекомендуется. - person Holger   schedule 25.11.2013monitorenter
или послеmonitorexit
не имеет никакого значения, поскольку это естественные границы, но вы даже не можете полагаться на это, так как JVM может попытаться оптимизировать и саму синхронизацию. Напомню простую вещь: инструментарий влияет на тайминг. И чем меньше время измерения (а вы охотитесь за очень маленькими интервалами), тем больше становится проблема. Так что не делайте этого; использовать встроенные возможности мониторинга JVM. - person Holger   schedule 25.11.2013