为什么代理模式这么慢?

ama*_*ara 1 java proxy-pattern

至少在java中,代理模式有很多开销 - 我不记得确切的数字,但是当包装微小方法时,代理需要花费50倍于包装方法的时间.这是,例如,为什么java.awt.image.BufferedImage.setRGB&getRGB真的慢; 有大约三个代理包装实际byte[].

为什么50次?!为什么代理不会加倍?


编辑:=(

正如SO似乎常见的那样,我得到了一堆答案,告诉我我的问题是错的.不是.查看BufferedImage或其他一些真正的代理模式,而不是那些微基准测试.事实上,如果你必须对BufferedImage进行大量像素操作并且你知道它的结构,你可以通过手动撤消代理来实现所谓的巨大加速; 看到这个答案.

哦,这是我50倍来源.正如文章详细说明的那样,代理在包装需要很长时间时没有明显的损失,但是如果你用一个小方法包装它们确实会产生很大的痛苦.

T.J*_*der 7

我不知道那个"50倍"的数字来自哪里,但这是非常可疑的.可能是某个特定代理明显慢于它代理的代理,这取决于它们每个人正在做什么,但是从中推断出"代理模式如此缓慢"是一个非常引人注目和高度可疑的问题.逻辑飞跃.

试试这个:

Thingy.java:

public class Thingy
{
    public int foo(int param1, int param2)
    {
        return param2 - param1;
    }
}
Run Code Online (Sandbox Code Playgroud)

ThingyProxy.java:

public class ThingyProxy
{
    Thingy thingy;

    public ThingyProxy()
    {
        this.thingy = new Thingy();
    }

    public int foo(int param1, int param2)
    {
        return this.thingy.foo(param1, param2);
    }
}
Run Code Online (Sandbox Code Playgroud)

WithoutProxy.java:

public class WithoutProxy
{
    public static final void main(String[] args)
    {
        Thingy t;
        int sum;
        int counter;
        int loops;

        sum = 0;
        t = new Thingy();
        for (loops = 0; loops < 300000000; ++loops) {
            sum = 0;
            for (counter = 0; counter < 100000000; ++counter) {
                sum += t.foo(1, 2);
            }
            if (sum != 100000000) {
                System.out.println("ERROR");
                return;
            }
        }
        System.exit(0);
    }
}
Run Code Online (Sandbox Code Playgroud)

WithProxy.java:

public class WithProxy
{
    public static final void main(String[] args)
    {
        ThingyProxy t;
        int sum;
        int counter;
        int loops;

        sum = 0;
        t = new ThingyProxy();
        for (loops = 0; loops < 300000000; ++loops) {
            sum = 0;
            for (counter = 0; counter < 100000000; ++counter) {
                sum += t.foo(1, 2);
            }
            if (sum != 100000000) {
                System.out.println("ERROR");
                return;
            }
        }
        System.exit(0);
    }
}
Run Code Online (Sandbox Code Playgroud)

我的机器上的简单试验:

$ time java WithoutProxy 

real    0m0.894s
user    0m0.900s
sys     0m0.000s

$ time java WithProxy

real    0m0.934s
user    0m0.940s
sys     0m0.000s

$ time java WithoutProxy 

real    0m0.883s
user    0m0.850s
sys     0m0.040s

$ time java WithProxy

real    0m0.937s
user    0m0.920s
sys     0m0.030s

$ time java WithoutProxy 

real    0m0.898s
user    0m0.880s
sys     0m0.030s

$ time java WithProxy

real    0m0.936s
user    0m0.950s
sys     0m0.000s

稍微慢点?是.慢50倍?没有.

现在,JVM的计时是众所周知的困难,如上所述的简单实验必然是可疑的.但我认为50倍的差异可能会出现.

编辑:我应该已经提到,上面有非常非常少量的循环发布这样的数字:

real    0m0.058s
user    0m0.040s
sys     0m0.020s

...让您了解环境中的VM启动时间.例如,上面的时间主要不是VM启动,实际执行时间差异只有微秒,它们主要是执行时间.