我正在嘗試使用ASM儀器Java同步塊。問題是,在測試之後,同步塊的執行時間需要更多時間。在Linux上,它從2毫秒增加到200毫秒。同步塊需要更多的時間後,使用ASM
我正在通過識別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));
}
這裏instrumention代碼(這裏System.currentMilliSeconds()給出了在該instrumention發生的時間,其沒有執行時間的措施,excecution時間是從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'調用都在synchronized塊中。順便說一下,'s'是什麼?你有什麼關於在同步該對象時發生的爭用的知識? – Holger
** s **是同步完成的String對象。這裏我只使用一個線程,同步塊運行10次。每次(t2-t1)時間都被計算出來。我正在使用塊內的currentTimeMillis bcoz,它是這個塊的服務時間,對於所有線程都是一樣的。這是我的動機,爲什麼它在儀器儀表後增加很多。請不要考慮爭用部分。至少執行時間應該保持不變。 – user3032258
您正在測量JVM優化未使用/無意義代碼的能力,並且似乎在特定位置添加打印語句(該效果在外部可見)會干擾優化。順便說一下,'String'是一個不同尋常的對象。不是真的推薦。 – Holger