Created
August 9, 2017 11:13
-
-
Save akarnokd/64430b072e7f042a8be8b1e476efb383 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import org.openjdk.jmh.annotations.*; | |
import java.lang.invoke.*; | |
import java.util.concurrent.*; | |
import java.util.concurrent.atomic.AtomicReference; | |
@BenchmarkMode(Mode.Throughput) | |
@Warmup(iterations = 5) | |
@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS) | |
@OutputTimeUnit(TimeUnit.SECONDS) | |
@Fork(value = 1) | |
@State(Scope.Thread) | |
public class VarHandleCostPerf { | |
AtomicReference<Flow.Subscription> z = new AtomicReference<>() { }; | |
AtomicReference<Flow.Subscription> y = new AtomicReference<>() { }; | |
AtomicReference<Flow.Subscription> x = new AtomicReference<>() { }; | |
AtomicReference<Flow.Subscription> w = new AtomicReference<>() { }; | |
AtomicReference<Flow.Subscription> v = new AtomicReference<>() { }; | |
AtomicReference<Flow.Subscription> u = new AtomicReference<>() { }; | |
AtomicReference<Flow.Subscription> t = new AtomicReference<>() { }; | |
A a = new A(); | |
B b = new B(); | |
C c = new C(); | |
D d = new D(); | |
E e = new E(); | |
F f = new F(); | |
G g = new G(); | |
@Benchmark | |
public void baseline1() { | |
AtomicReference<Flow.Subscription> t = this.t; | |
cancel(t); | |
t.setPlain(null); | |
} | |
@Benchmark | |
public void baseline2() { | |
cancel(t); | |
cancel(u); | |
t.setPlain(null); | |
u.setPlain(null); | |
} | |
@Benchmark | |
public void baseline3() { | |
cancel(t); | |
cancel(u); | |
cancel(v); | |
t.setPlain(null); | |
u.setPlain(null); | |
v.setPlain(null); | |
} | |
@Benchmark | |
public void baseline4() { | |
cancel(t); | |
cancel(u); | |
cancel(v); | |
cancel(w); | |
t.setPlain(null); | |
u.setPlain(null); | |
v.setPlain(null); | |
w.setPlain(null); | |
} | |
@Benchmark | |
public void baseline5() { | |
cancel(t); | |
cancel(u); | |
cancel(v); | |
cancel(w); | |
cancel(x); | |
t.setPlain(null); | |
u.setPlain(null); | |
v.setPlain(null); | |
w.setPlain(null); | |
x.setPlain(null); | |
} | |
@Benchmark | |
public void baseline6() { | |
cancel(t); | |
cancel(u); | |
cancel(v); | |
cancel(w); | |
cancel(x); | |
cancel(y); | |
t.setPlain(null); | |
u.setPlain(null); | |
v.setPlain(null); | |
w.setPlain(null); | |
x.setPlain(null); | |
y.setPlain(null); | |
} | |
@Benchmark | |
public void baseline7() { | |
cancel(t); | |
cancel(u); | |
cancel(v); | |
cancel(w); | |
cancel(x); | |
cancel(y); | |
cancel(z); | |
t.setPlain(null); | |
u.setPlain(null); | |
v.setPlain(null); | |
w.setPlain(null); | |
x.setPlain(null); | |
y.setPlain(null); | |
z.setPlain(null); | |
} | |
@Benchmark | |
public void bench1() { | |
a.cancel(); | |
a.upstream = null; | |
} | |
@Benchmark | |
public void bench2() { | |
a.cancel(); | |
b.cancel(); | |
a.upstream = null; | |
b.upstream = null; | |
} | |
@Benchmark | |
public void bench3() { | |
a.cancel(); | |
b.cancel(); | |
c.cancel(); | |
a.upstream = null; | |
b.upstream = null; | |
c.upstream = null; | |
} | |
@Benchmark | |
public void bench4() { | |
a.cancel(); | |
b.cancel(); | |
c.cancel(); | |
d.cancel(); | |
a.upstream = null; | |
b.upstream = null; | |
c.upstream = null; | |
d.upstream = null; | |
} | |
@Benchmark | |
public void bench5() { | |
a.cancel(); | |
b.cancel(); | |
c.cancel(); | |
d.cancel(); | |
e.cancel(); | |
a.upstream = null; | |
b.upstream = null; | |
c.upstream = null; | |
d.upstream = null; | |
e.upstream = null; | |
} | |
@Benchmark | |
public void bench6() { | |
a.cancel(); | |
b.cancel(); | |
c.cancel(); | |
d.cancel(); | |
e.cancel(); | |
f.cancel(); | |
a.upstream = null; | |
b.upstream = null; | |
c.upstream = null; | |
d.upstream = null; | |
e.upstream = null; | |
f.upstream = null; | |
} | |
@Benchmark | |
public void bench7() { | |
a.cancel(); | |
b.cancel(); | |
c.cancel(); | |
d.cancel(); | |
e.cancel(); | |
f.cancel(); | |
g.cancel(); | |
a.upstream = null; | |
b.upstream = null; | |
c.upstream = null; | |
d.upstream = null; | |
e.upstream = null; | |
f.upstream = null; | |
g.upstream = null; | |
} | |
static final class A { | |
Flow.Subscription upstream; | |
static final VarHandle UPSTREAM; | |
static { | |
try { | |
UPSTREAM = MethodHandles.lookup().findVarHandle(A.class, "upstream", Flow.Subscription.class); | |
} catch (Throwable ex) { | |
throw new InternalError(ex); | |
} | |
} | |
void cancel() { | |
VarHandleCostPerf.cancel(this, UPSTREAM); | |
} | |
} | |
static final class B { | |
Flow.Subscription upstream; | |
static final VarHandle UPSTREAM; | |
static { | |
try { | |
UPSTREAM = MethodHandles.lookup().findVarHandle(B.class, "upstream", Flow.Subscription.class); | |
} catch (Throwable ex) { | |
throw new InternalError(ex); | |
} | |
} | |
void cancel() { | |
VarHandleCostPerf.cancel(this, UPSTREAM); | |
} | |
} | |
static final class C { | |
Flow.Subscription upstream; | |
static final VarHandle UPSTREAM; | |
static { | |
try { | |
UPSTREAM = MethodHandles.lookup().findVarHandle(C.class, "upstream", Flow.Subscription.class); | |
} catch (Throwable ex) { | |
throw new InternalError(ex); | |
} | |
} | |
void cancel() { | |
VarHandleCostPerf.cancel(this, UPSTREAM); | |
} | |
} | |
static final class D { | |
Flow.Subscription upstream; | |
static final VarHandle UPSTREAM; | |
static { | |
try { | |
UPSTREAM = MethodHandles.lookup().findVarHandle(D.class, "upstream", Flow.Subscription.class); | |
} catch (Throwable ex) { | |
throw new InternalError(ex); | |
} | |
} | |
void cancel() { | |
VarHandleCostPerf.cancel(this, UPSTREAM); | |
} | |
} | |
static final class E { | |
Flow.Subscription upstream; | |
static final VarHandle UPSTREAM; | |
static { | |
try { | |
UPSTREAM = MethodHandles.lookup().findVarHandle(E.class, "upstream", Flow.Subscription.class); | |
} catch (Throwable ex) { | |
throw new InternalError(ex); | |
} | |
} | |
void cancel() { | |
VarHandleCostPerf.cancel(this, UPSTREAM); | |
} | |
} | |
static final class F { | |
Flow.Subscription upstream; | |
static final VarHandle UPSTREAM; | |
static { | |
try { | |
UPSTREAM = MethodHandles.lookup().findVarHandle(F.class, "upstream", Flow.Subscription.class); | |
} catch (Throwable ex) { | |
throw new InternalError(ex); | |
} | |
} | |
void cancel() { | |
VarHandleCostPerf.cancel(this, UPSTREAM); | |
} | |
} | |
static final class G { | |
Flow.Subscription upstream; | |
static final VarHandle UPSTREAM; | |
static { | |
try { | |
UPSTREAM = MethodHandles.lookup().findVarHandle(G.class, "upstream", Flow.Subscription.class); | |
} catch (Throwable ex) { | |
throw new InternalError(ex); | |
} | |
} | |
void cancel() { | |
VarHandleCostPerf.cancel(this, UPSTREAM); | |
} | |
} | |
public static boolean cancel(AtomicReference<Flow.Subscription> field) { | |
Flow.Subscription a = field.getAcquire(); | |
if (a != CANCELLED) { | |
a = field.getAndSet(CANCELLED); | |
if (a != CANCELLED) { | |
if (a != null) { | |
a.cancel(); | |
} | |
return true; | |
} | |
} | |
return false; | |
} | |
public static boolean cancel(Object target, VarHandle upstream) { | |
Flow.Subscription a = (Flow.Subscription)upstream.getAcquire(target); | |
if (a != CANCELLED) { | |
a = (Flow.Subscription)upstream.getAndSet(target, CANCELLED); | |
if (a != CANCELLED) { | |
if (a != null) { | |
a.cancel(); | |
} | |
return true; | |
} | |
} | |
return false; | |
} | |
static final Flow.Subscription CANCELLED = new Flow.Subscription() { | |
@Override | |
public void request(long n) { | |
} | |
@Override | |
public void cancel() { | |
} | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment