Skip to content

Commit

Permalink
ISPN-6805 Enforce padding with class hierarchy
Browse files Browse the repository at this point in the history
The JVM is free to reorder fields inside a class, but not to mix
fields from subclasses and superclasses.
  • Loading branch information
danberindei committed Sep 26, 2016
1 parent 3484d57 commit 0b9ac9e
Showing 1 changed file with 78 additions and 70 deletions.
Expand Up @@ -45,7 +45,7 @@ public class CacheMgmtInterceptor extends JmxStatsCommandInterceptor {

private final AtomicLong startNanoseconds = new AtomicLong(0);
private volatile AtomicLong resetNanoseconds = new AtomicLong(0);
private StripedCounters<Stripe> counters = new StripedCounters<Stripe>(Stripe::new);
private StripedCounters<StripeB> counters = new StripedCounters<>(StripeC::new);

@Inject
@SuppressWarnings("unused")
Expand All @@ -66,7 +66,7 @@ public CompletableFuture<Void> visitEvictCommand(InvocationContext ctx, EvictCom
return ctx.continueInvocation();

return ctx.onReturn((rCtx, rCommand, rv, throwable) -> {
counters.increment(Stripe.evictionsFieldUpdater, counters.stripeForCurrentThread());
counters.increment(StripeB.evictionsFieldUpdater, counters.stripeForCurrentThread());
return null;
});
}
Expand All @@ -88,14 +88,14 @@ private CompletableFuture<Void> visitDataReadCommand(InvocationContext ctx, Abst

long start = timeService.time();
return ctx.onReturn((rCtx, rCommand, rv, throwable) -> {
Stripe stripe = counters.stripeForCurrentThread();
StripeB stripe = counters.stripeForCurrentThread();
long intervalMilliseconds = timeService.timeDuration(start, TimeUnit.MILLISECONDS);
if (rv == null) {
counters.add(Stripe.missTimesFieldUpdater, stripe, intervalMilliseconds);
counters.increment(Stripe.missesFieldUpdater, stripe);
counters.add(StripeB.missTimesFieldUpdater, stripe, intervalMilliseconds);
counters.increment(StripeB.missesFieldUpdater, stripe);
} else {
counters.add(Stripe.hitTimesFieldUpdater, stripe, intervalMilliseconds);
counters.increment(Stripe.hitsFieldUpdater, stripe);
counters.add(StripeB.hitTimesFieldUpdater, stripe, intervalMilliseconds);
counters.increment(StripeB.hitsFieldUpdater, stripe);
}
return null;
});
Expand All @@ -120,14 +120,14 @@ public CompletableFuture<Void> visitGetAllCommand(InvocationContext ctx, GetAllC
}

int missCount = requests - hitCount;
Stripe stripe = counters.stripeForCurrentThread();
StripeB stripe = counters.stripeForCurrentThread();
if (hitCount > 0) {
counters.add(Stripe.hitsFieldUpdater, stripe, hitCount);
counters.add(Stripe.hitTimesFieldUpdater, stripe, intervalMilliseconds * hitCount / requests);
counters.add(StripeB.hitsFieldUpdater, stripe, hitCount);
counters.add(StripeB.hitTimesFieldUpdater, stripe, intervalMilliseconds * hitCount / requests);
}
if (missCount > 0) {
counters.add(Stripe.missesFieldUpdater, stripe, missCount);
counters.add(Stripe.missTimesFieldUpdater, stripe, intervalMilliseconds * missCount / requests);
counters.add(StripeB.missesFieldUpdater, stripe, missCount);
counters.add(StripeB.missTimesFieldUpdater, stripe, intervalMilliseconds * missCount / requests);
}
return null;
});
Expand All @@ -144,9 +144,9 @@ public CompletableFuture<Void> visitPutMapCommand(InvocationContext ctx, PutMapC
final long intervalMilliseconds = timeService.timeDuration(start, TimeUnit.MILLISECONDS);
final Map<Object, Object> data = ((PutMapCommand) rCommand).getMap();
if (data != null && !data.isEmpty()) {
Stripe stripe = counters.stripeForCurrentThread();
counters.add(Stripe.storeTimesFieldUpdater, stripe, intervalMilliseconds);
counters.add(Stripe.storesFieldUpdater, stripe, data.size());
StripeB stripe = counters.stripeForCurrentThread();
counters.add(StripeB.storeTimesFieldUpdater, stripe, intervalMilliseconds);
counters.add(StripeB.storesFieldUpdater, stripe, data.size());
}
return null;
});
Expand All @@ -172,9 +172,9 @@ private CompletableFuture<Void> updateStoreStatistics(InvocationContext ctx, Wri
return ctx.onReturn((rCtx, rCommand, rv, throwable) -> {
if (command.isSuccessful()) {
long intervalMilliseconds = timeService.timeDuration(start, TimeUnit.MILLISECONDS);
Stripe stripe = counters.stripeForCurrentThread();
counters.add(Stripe.storeTimesFieldUpdater, stripe, intervalMilliseconds);
counters.increment(Stripe.storesFieldUpdater, stripe);
StripeB stripe = counters.stripeForCurrentThread();
counters.add(StripeB.storeTimesFieldUpdater, stripe, intervalMilliseconds);
counters.increment(StripeB.storesFieldUpdater, stripe);
}
return null;
});
Expand Down Expand Up @@ -206,13 +206,13 @@ public CompletableFuture<Void> visitRemoveCommand(InvocationContext ctx, RemoveC

private void increaseRemoveHits(long start) {
long intervalMilliseconds = timeService.timeDuration(start, TimeUnit.MILLISECONDS);
Stripe stripe = counters.stripeForCurrentThread();
counters.add(Stripe.removeTimesFieldUpdater, stripe, intervalMilliseconds);
counters.increment(Stripe.removeHitsFieldUpdater, stripe);
StripeB stripe = counters.stripeForCurrentThread();
counters.add(StripeB.removeTimesFieldUpdater, stripe, intervalMilliseconds);
counters.increment(StripeB.removeHitsFieldUpdater, stripe);
}

private void increaseRemoveMisses() {
counters.increment(Stripe.removeMissesFieldUpdater, counters.stripeForCurrentThread());
counters.increment(StripeB.removeMissesFieldUpdater, counters.stripeForCurrentThread());
}

@ManagedAttribute(
Expand All @@ -221,7 +221,7 @@ private void increaseRemoveMisses() {
measurementType = MeasurementType.TRENDSUP,
displayType = DisplayType.SUMMARY)
public long getHits() {
return counters.get(Stripe.hitsFieldUpdater);
return counters.get(StripeB.hitsFieldUpdater);
}

@ManagedAttribute(
Expand All @@ -231,7 +231,7 @@ public long getHits() {
displayType = DisplayType.SUMMARY
)
public long getMisses() {
return counters.get(Stripe.missesFieldUpdater);
return counters.get(StripeB.missesFieldUpdater);
}

@ManagedAttribute(
Expand All @@ -241,7 +241,7 @@ public long getMisses() {
displayType = DisplayType.SUMMARY
)
public long getRemoveHits() {
return counters.get(Stripe.removeHitsFieldUpdater);
return counters.get(StripeB.removeHitsFieldUpdater);
}

@ManagedAttribute(
Expand All @@ -251,7 +251,7 @@ public long getRemoveHits() {
displayType = DisplayType.SUMMARY
)
public long getRemoveMisses() {
return counters.get(Stripe.removeMissesFieldUpdater);
return counters.get(StripeB.removeMissesFieldUpdater);
}

@ManagedAttribute(
Expand All @@ -261,7 +261,7 @@ public long getRemoveMisses() {
displayType = DisplayType.SUMMARY
)
public long getStores() {
return counters.get(Stripe.storesFieldUpdater);
return counters.get(StripeB.storesFieldUpdater);
}

@ManagedAttribute(
Expand All @@ -271,7 +271,7 @@ public long getStores() {
displayType = DisplayType.SUMMARY
)
public long getEvictions() {
return counters.get(Stripe.evictionsFieldUpdater);
return counters.get(StripeB.evictionsFieldUpdater);
}

@ManagedAttribute(
Expand All @@ -282,8 +282,8 @@ public long getEvictions() {
)
@SuppressWarnings("unused")
public double getHitRatio() {
long hitsL = counters.get(Stripe.hitsFieldUpdater);
double total = hitsL + counters.get(Stripe.missesFieldUpdater);
long hitsL = counters.get(StripeB.hitsFieldUpdater);
double total = hitsL + counters.get(StripeB.missesFieldUpdater);
// The reason for <= is that equality checks
// should be avoided for floating point numbers.
if (total <= 0)
Expand All @@ -299,10 +299,10 @@ public double getHitRatio() {
)
@SuppressWarnings("unused")
public double getReadWriteRatio() {
long sum = counters.get(Stripe.storesFieldUpdater);
long sum = counters.get(StripeB.storesFieldUpdater);
if (sum == 0)
return 0;
return (((double) (counters.get(Stripe.hitsFieldUpdater) + counters.get(Stripe.missesFieldUpdater)) / (double) sum));
return (((double) (counters.get(StripeB.hitsFieldUpdater) + counters.get(StripeB.missesFieldUpdater)) / (double) sum));
}

@ManagedAttribute(
Expand All @@ -313,10 +313,10 @@ public double getReadWriteRatio() {
)
@SuppressWarnings("unused")
public long getAverageReadTime() {
long total = counters.get(Stripe.hitsFieldUpdater) + counters.get(Stripe.missesFieldUpdater);
long total = counters.get(StripeB.hitsFieldUpdater) + counters.get(StripeB.missesFieldUpdater);
if (total == 0)
return 0;
return (counters.get(Stripe.hitTimesFieldUpdater) + counters.get(Stripe.missTimesFieldUpdater)) / total;
return (counters.get(StripeB.hitTimesFieldUpdater) + counters.get(StripeB.missTimesFieldUpdater)) / total;
}

@ManagedAttribute(
Expand All @@ -327,10 +327,10 @@ public long getAverageReadTime() {
)
@SuppressWarnings("unused")
public long getAverageWriteTime() {
long sum = counters.get(Stripe.storesFieldUpdater);
long sum = counters.get(StripeB.storesFieldUpdater);
if (sum == 0)
return 0;
return (counters.get(Stripe.storeTimesFieldUpdater)) / sum;
return (counters.get(StripeB.storeTimesFieldUpdater)) / sum;
}

@ManagedAttribute(
Expand All @@ -344,7 +344,7 @@ public long getAverageRemoveTime() {
long removes = getRemoveHits();
if (removes == 0)
return 0;
return (counters.get(Stripe.removeTimesFieldUpdater)) / removes;
return (counters.get(StripeB.removeTimesFieldUpdater)) / removes;
}

@ManagedAttribute(
Expand Down Expand Up @@ -403,16 +403,16 @@ public long getTimeSinceReset() {
displayName = "Reset Statistics (Statistics)"
)
public void resetStatistics() {
counters.reset(Stripe.hitsFieldUpdater);
counters.reset(Stripe.missesFieldUpdater);
counters.reset(Stripe.storesFieldUpdater);
counters.reset(Stripe.evictionsFieldUpdater);
counters.reset(Stripe.hitTimesFieldUpdater);
counters.reset(Stripe.missTimesFieldUpdater);
counters.reset(Stripe.storeTimesFieldUpdater);
counters.reset(Stripe.removeHitsFieldUpdater);
counters.reset(Stripe.removeTimesFieldUpdater);
counters.reset(Stripe.removeMissesFieldUpdater);
counters.reset(StripeB.hitsFieldUpdater);
counters.reset(StripeB.missesFieldUpdater);
counters.reset(StripeB.storesFieldUpdater);
counters.reset(StripeB.evictionsFieldUpdater);
counters.reset(StripeB.hitTimesFieldUpdater);
counters.reset(StripeB.missTimesFieldUpdater);
counters.reset(StripeB.storeTimesFieldUpdater);
counters.reset(StripeB.removeHitsFieldUpdater);
counters.reset(StripeB.removeTimesFieldUpdater);
counters.reset(StripeB.removeMissesFieldUpdater);
resetNanoseconds.set(timeService.time());
}

Expand All @@ -421,31 +421,36 @@ private boolean getStatisticsEnabled(FlagAffectedCommand cmd) {
}

public void addEvictions(long numEvictions) {
counters.add(Stripe.evictionsFieldUpdater, counters.stripeForCurrentThread(), numEvictions);
counters.add(StripeB.evictionsFieldUpdater, counters.stripeForCurrentThread(), numEvictions);
}

@SuppressWarnings("unused")
private static class Stripe {
static final AtomicLongFieldUpdater<Stripe> hitTimesFieldUpdater =
AtomicLongFieldUpdater.newUpdater(Stripe.class, "hitTimes");
static final AtomicLongFieldUpdater<Stripe> missTimesFieldUpdater =
AtomicLongFieldUpdater.newUpdater(Stripe.class, "missTimes");
static final AtomicLongFieldUpdater<Stripe> storeTimesFieldUpdater =
AtomicLongFieldUpdater.newUpdater(Stripe.class, "storeTimes");
static final AtomicLongFieldUpdater<Stripe> removeTimesFieldUpdater =
AtomicLongFieldUpdater.newUpdater(Stripe.class, "removeTimes");
static final AtomicLongFieldUpdater<Stripe> hitsFieldUpdater =
AtomicLongFieldUpdater.newUpdater(Stripe.class, "hits");
static final AtomicLongFieldUpdater<Stripe> missesFieldUpdater =
AtomicLongFieldUpdater.newUpdater(Stripe.class, "misses");
static final AtomicLongFieldUpdater<Stripe> storesFieldUpdater =
AtomicLongFieldUpdater.newUpdater(Stripe.class, "stores");
static final AtomicLongFieldUpdater<Stripe> evictionsFieldUpdater =
AtomicLongFieldUpdater.newUpdater(Stripe.class, "evictions");
static final AtomicLongFieldUpdater<Stripe> removeHitsFieldUpdater =
AtomicLongFieldUpdater.newUpdater(Stripe.class, "removeHits");
static final AtomicLongFieldUpdater<Stripe> removeMissesFieldUpdater =
AtomicLongFieldUpdater.newUpdater(Stripe.class, "removeMisses");
private static class StripeA {
private long slack1, slack2, slack3, slack4, slack5, slack6, slack7, slack8;
}

@SuppressWarnings({"unused", "VolatileLongOrDoubleField"})
private static class StripeB extends StripeA {
static final AtomicLongFieldUpdater<StripeB> hitTimesFieldUpdater =
AtomicLongFieldUpdater.newUpdater(StripeB.class, "hitTimes");
static final AtomicLongFieldUpdater<StripeB> missTimesFieldUpdater =
AtomicLongFieldUpdater.newUpdater(StripeB.class, "missTimes");
static final AtomicLongFieldUpdater<StripeB> storeTimesFieldUpdater =
AtomicLongFieldUpdater.newUpdater(StripeB.class, "storeTimes");
static final AtomicLongFieldUpdater<StripeB> removeHitsFieldUpdater =
AtomicLongFieldUpdater.newUpdater(StripeB.class, "removeHits");
static final AtomicLongFieldUpdater<StripeB> removeMissesFieldUpdater =
AtomicLongFieldUpdater.newUpdater(StripeB.class, "removeMisses");
static final AtomicLongFieldUpdater<StripeB> storesFieldUpdater =
AtomicLongFieldUpdater.newUpdater(StripeB.class, "stores");
static final AtomicLongFieldUpdater<StripeB> evictionsFieldUpdater =
AtomicLongFieldUpdater.newUpdater(StripeB.class, "evictions");
static final AtomicLongFieldUpdater<StripeB> missesFieldUpdater =
AtomicLongFieldUpdater.newUpdater(StripeB.class, "misses");
static final AtomicLongFieldUpdater<StripeB> hitsFieldUpdater =
AtomicLongFieldUpdater.newUpdater(StripeB.class, "hits");
static final AtomicLongFieldUpdater<StripeB> removeTimesFieldUpdater =
AtomicLongFieldUpdater.newUpdater(StripeB.class, "removeTimes");

private volatile long hits = 0;
private volatile long hitTimes = 0;
Expand All @@ -457,7 +462,10 @@ private static class Stripe {
private volatile long removeHits = 0;
private volatile long removeMisses = 0;
private volatile long removeTimes = 0;
}

private long slack1, slack2, slack3, slack4, slack5, slack6;
@SuppressWarnings("unused")
private static class StripeC extends StripeB {
private long slack1, slack2, slack3, slack4, slack5, slack6, slack7, slack8;
}
}

0 comments on commit 0b9ac9e

Please sign in to comment.