質問

I have a time-sensitive application that gets data from a third party library. What would be the performance hit associated with wrapping their objects into more appropriate interfaces for my application?

Note: I am posting an answer here (Q&A style), but if it's wrong please correct me!

役に立ちましたか?

解決

There's some overhead with indirection, but it's hard to measure. The OP's benchmark took about 4 ns per iteration while mine needs about 1 ns (for the fastest experiment). This means that they were measuring mostly the overhead of the ArrayList, Iterator, and cycle probably together with a virtual call overhead.

The overhead to be measured is so small that you need to use arrays and either add an inner loop or use masking for accessing them.

The results of my benchmark show that there's a measureable overhead of both using an interface and an indirection. This overhead ranges from maybe 20% to 50%, which looks like a lot. However, the important part is 20-50% of what. It's a fraction of specially crafted benchmark doing nothing but exercising the code. In any realistic piece code the relative overhead will be ten, hundred, or thousand times lower.

So unless you're designing a high-performance library doing some very basic and fast operations, just forget it. Use indirection and interfaces at will and concentrate on good design. Even if performance is important, there are probably other places where you can gain more.

WrappingBenchmark

他のヒント

After attempting to work with their classes for months, today I decided to make a test. It seems that it doesn't add much if any overhead. Here are the results - which are actually not all that consistent, here's one that actually has unwrapped being SLOWER:

 0% Scenario{vm=java, trial=0, benchmark=Unwrapped} 3.96 ns; ?=0.02 ns @ 3 trials
33% Scenario{vm=java, trial=0, benchmark=Copy} 3.93 ns; ?=0.01 ns @ 3 trials
67% Scenario{vm=java, trial=0, benchmark=Backing} 3.94 ns; ?=0.01 ns @ 3 trials

benchmark   ns linear runtime
Unwrapped 3.96 ==============================
     Copy 3.93 =============================
  Backing 3.94 =============================

vm: java
trial: 0

Source code (Caliper 0.5-rc1, Guava 2.0+):

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;

import com.google.caliper.Runner;
import com.google.caliper.SimpleBenchmark;
import com.google.common.collect.Iterables;

public class WrapperTest {
    public static class Unwrapped {
        private int inner;

        public Unwrapped(int inner) {
            this.inner = inner;
        }

        public int getInner() {
            return inner;
        }
    }

    public static interface Outer {
        public int getOuter();
    }

    public static class CopyOuter implements Outer {
        private int outer;

        public CopyOuter(int outer) {
            this.outer = outer;
        }

        public int getOuter() {
            return outer;
        }
    }

    public static class BackingOuter implements Outer {
        private Unwrapped inner;

        public BackingOuter(Unwrapped inner) {
            this.inner = inner;
        }

        public int getOuter() {
            return inner.getInner();
        }
    }

    public static class TestBenchmark extends SimpleBenchmark {
        private Iterable<Unwrapped> cycle;

        @Override
        protected void setUp() {
            List<Unwrapped> backing = new ArrayList<Unwrapped>(16384);
            Random r = new Random();
            for(int i = 0; i < 16384; i++) {
                backing.add(new Unwrapped(Math.abs(r.nextInt())));
            }
            cycle = Iterables.cycle(backing);
        }

        public long timeUnwrapped(int reps) {
            long total = 0;
            Iterator<Unwrapped> iter = cycle.iterator();
            for(int i = 0; i < reps; i++) {
                total += iter.next().getInner();
            }
            return total;
        }

        public long timeCopy(int reps) {
            long total = 0;
            Iterator<Unwrapped> iter = cycle.iterator();
            for(int i = 0; i < reps; i++) {
                total += new CopyOuter(iter.next().getInner()).getOuter();
            }
            return total;
        }

        public long timeBacking(int reps) {
            long total = 0;
            Iterator<Unwrapped> iter = cycle.iterator();
            for(int i = 0; i < reps; i++) {
                total += new BackingOuter(iter.next()).getOuter();
            }
            return total;
        }
    }

    public static void main(String[] args) {
        Runner.main(TestBenchmark.class, new String[0]);
    }
}
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top