簡體   English   中英

Java - LinkedList - 性能隨着其中不同類的數量而減少

[英]Java - LinkedList - Performance decreases with the number of different classes in it

以下代碼測量從接口處理程序 100次調用方法句柄(對象o)所花費的時間(是的,它的質量差異分析):

package test;

import java.util.LinkedList;

public class Test {

    static int i = 0;

    private interface Handler {
        public void handle(Object o);
    }
    private static class SuperHandler implements Handler {
        public void handle(Object o) { i += 1; }
    }
    private static class NoSuperHandler implements Handler {
        public void handle(Object o) { i += 1; }
    }
    private static class LulSuperHandler implements Handler {
        public void handle(Object o) { i += 1; }
    }
    private static class LilSuperHandler implements Handler {
        public void handle(Object o) { i += 1; }
    }
    private static class LolSuperHandler implements Handler {
        public void handle(Object o) { i += 1; }
    }
    private static class LalSuperHandler implements Handler {
        public void handle(Object o) { i += 1; }
    }
    private static class LylSuperHandler implements Handler {
        public void handle(Object o) { i += 1; }
    }
    private static class LzlSuperHandler implements Handler {
        public void handle(Object o) { i += 1; }
    }

    public static void main(String[] args) {
        LinkedList<Handler> ll = new LinkedList<Handler>();
        for(int j = 0; j < 100; j++) {
            if((j % 8) == 0) ll.add(new SuperHandler());
            if((j % 8) == 1) ll.add(new NoSuperHandler());
            if((j % 8) == 2) ll.add(new LulSuperHandler());
            if((j % 8) == 3) ll.add(new LilSuperHandler());
            if((j % 8) == 4) ll.add(new LolSuperHandler());
            if((j % 8) == 5) ll.add(new LalSuperHandler());
            if((j % 8) == 6) ll.add(new LylSuperHandler());
            if((j % 8) == 7) ll.add(new LzlSuperHandler());
        }
        long begin = System.currentTimeMillis();
        for(int j = 0; j < 1000000; j++) for(Handler h: ll) h.handle(null);
        System.out.println("time in ms: " + (System.currentTimeMillis() - begin));
        System.out.println("i: " + i);
    }
}

事實是,如果LinkedList只包含一種Handler ,例如SuperHandler ,則執行時間小於它們是2,3等不同種類的Handler 每次我在列表中添加一種新的Handler時,性能會下降。

例如,當我只改變這部分時,我獲得了比上面更好的表現:

for(int j = 0; j < 100; j++) {
    if((j % 2) == 0) ll.add(new SuperHandler());
    if((j % 2) == 1) ll.add(new NoSuperHandler());
}

這里有特殊的優化操作嗎? JAVA架構中的性能會降低多少? 我的測試是錯誤的,因為未使用的Handler被編譯器“刪除”或“隱藏”了嗎? (我正在使用Linux Ubuntu - 來自Oracle的JAVA 1.7)

這里有特殊的優化操作嗎?

是。 Hotspot非常聰明地處理虛擬方法。 如果只有一些接口的實現,並且這些實現很小,它可以通過檢查正確的類型和內聯代碼來避免完整的vtable-lookup。

當你有幾個不同的實現時,它會回到vtable實現。 (Hotspot非常聰明,可以撤銷不再實用的優化。我很震驚,它們都掛在一起,但顯然確實如此。)

請注意,這不是列表中有多少不同的類 - 這里有更多的內容。 有關詳細信息,請參閱Peter的答案。

我同意Jon的回答,但我相信它是在代碼點調用的類型數量之間產生差異。 在下面的示例中,將加載所有8個類,並且對於列表中相同數量的元素運行相同的代碼,除了一個列表有8個,另一個列表有2個不同類型。

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class Test {

    static int i = 0;

    private interface Handler {
        public void handle();
    }

    public static void main(String[] args) {
        List<Handler> ll8 = new ArrayList<Handler>();
        for (int j = 0; j < 128; j += 8) {
            ll8.add(new SuperHandler());
            ll8.add(new NoSuperHandler());
            ll8.add(new LulSuperHandler());
            ll8.add(new LilSuperHandler());
            ll8.add(new LolSuperHandler());
            ll8.add(new LalSuperHandler());
            ll8.add(new LylSuperHandler());
            ll8.add(new LzlSuperHandler());
        }
        List<Handler> ll2 = new ArrayList<Handler>();
        for (int j = 0; j < 128; j += 2) {
            ll2.add(new SuperHandler());
            ll2.add(new NoSuperHandler());
        }
        for (int j = 0; j < 5; j++) {
            test8(ll8);
            test8a(ll8);
            test2(ll2);
        }
        System.out.println("i: " + i);
    }

    private static void test8(List<Handler> ll8) {
        long begin = System.nanoTime();
        for (int j = 0; j < 1000000; j++) for (Handler h : ll8) h.handle();
        System.out.println("8 classes, time in ms: " + (System.nanoTime() - begin) / 100000 / 10.0);
    }

    private static void test8a(List<Handler> ll8) {
        long begin = System.nanoTime();
        for (int j = 0; j < 1000000; j++)
            for (int k = 0; k < ll8.size(); k += 8) {
                ll8.get(k + 0).handle();
                ll8.get(k + 1).handle();
                ll8.get(k + 2).handle();
                ll8.get(k + 3).handle();
                ll8.get(k + 4).handle();
                ll8.get(k + 5).handle();
                ll8.get(k + 6).handle();
                ll8.get(k + 7).handle();
            }
        System.out.println("8 classes unrolled, time in ms: " + (System.nanoTime() - begin) / 100000 / 10.0);
    }

    private static void test2(List<Handler> ll2) {
        long begin = System.nanoTime();
        for (int j = 0; j < 1000000; j++) for (Handler h : ll2) h.handle();
        System.out.println("2 classes, time in ms: " + (System.nanoTime() - begin) / 100000 / 10.0);
    }

    private static class SuperHandler implements Handler {
        public void handle() { i += 1; }
    }

    private static class NoSuperHandler implements Handler {
        public void handle() { i += 1; }
    }

    private static class LulSuperHandler implements Handler {
        public void handle() { i += 1; }
    }

    private static class LilSuperHandler implements Handler {
        public void handle() { i += 1; }
    }

    private static class LolSuperHandler implements Handler {
        public void handle() { i += 1; }
    }

    private static class LalSuperHandler implements Handler {
        public void handle() { i += 1; }
    }

    private static class LylSuperHandler implements Handler {
        public void handle() { i += 1; }
    }

    private static class LzlSuperHandler implements Handler {
        public void handle() { i += 1; }
    }
}

版畫

8 classes, time in ms: 1467.9
8 classes unrolled, time in ms: 144.7
2 classes, time in ms: 515.8
8 classes, time in ms: 1455.1
8 classes unrolled, time in ms: 126.2
2 classes, time in ms: 509.6
8 classes, time in ms: 1234.1
8 classes unrolled, time in ms: 107.8
2 classes, time in ms: 274.3
8 classes, time in ms: 1212.0
8 classes unrolled, time in ms: 108.1
2 classes, time in ms: 273.0
8 classes, time in ms: 1208.8
8 classes unrolled, time in ms: 107.8
2 classes, time in ms: 274.5
i: 1920000000

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM