Skip to content

Commit

Permalink
Re-add an mbean for monitoring cache invalidations.
Browse files Browse the repository at this point in the history
This is for #4384.

For this initial version, methods and constants only have a single
value indicating validation count globally. For constants, this
will aggregate all constant names (which are invalidated
separately). For methods, this will aggregate all class hierarchy
invalidations, which will frequently mean a single invalidation
event will increment this value many times, depending on the size
of the hierarchy below it. This latter point could be improved
but we don't really have a clear place to say "this is the top
invalidation" at the moment.
headius committed Dec 5, 2017
1 parent 307f557 commit 0e6efdd
Showing 10 changed files with 90 additions and 24 deletions.
21 changes: 19 additions & 2 deletions core/src/main/java/org/jruby/Ruby.java
Original file line number Diff line number Diff line change
@@ -59,9 +59,11 @@
import org.jruby.javasupport.JavaSupport;
import org.jruby.javasupport.JavaSupportImpl;
import org.jruby.lexer.yacc.ISourcePosition;
import org.jruby.management.Caches;
import org.jruby.parser.StaticScope;
import org.jruby.runtime.JavaSites;
import org.jruby.runtime.invokedynamic.InvokeDynamicSupport;
import org.jruby.runtime.opto.ConstantInvalidator;
import org.jruby.util.MRIRecursionGuard;
import org.jruby.util.io.EncodingUtils;
import org.objectweb.asm.util.TraceClassVisitor;
@@ -251,6 +253,7 @@ private Ruby(RubyInstanceConfig config) {
this.beanManager = BeanManagerFactory.create(this, config.isManagementEnabled());
this.jitCompiler = new JITCompiler(this);
this.parserStats = new ParserStats(this);
this.caches = new Caches();

Random myRandom;
try {
@@ -277,7 +280,7 @@ private Ruby(RubyInstanceConfig config) {
this.runtimeCache = new RuntimeCache();
runtimeCache.initMethodCache(ClassIndex.MAX_CLASSES.ordinal() * MethodNames.values().length - 1);

checkpointInvalidator = OptoFactory.newConstantInvalidator();
checkpointInvalidator = OptoFactory.newConstantInvalidator(this);

if (config.isObjectSpaceEnabled()) {
objectSpacer = ENABLED_OBJECTSPACE;
@@ -296,6 +299,7 @@ public void registerMBeans() {
this.beanManager.register(configBean);
this.beanManager.register(parserStats);
this.beanManager.register(runtimeBean);
this.beanManager.register(caches);
}

void reinitialize(boolean reinitCore) {
@@ -875,6 +879,15 @@ public JITCompiler getJITCompiler() {
return jitCompiler;
}

/**
* Get the Caches management object.
*
* @return the current runtime's Caches management object
*/
public Caches getCaches() {
return caches;
}

/**
* @deprecated use #newInstance()
*/
@@ -4343,7 +4356,7 @@ public Invalidator getConstantInvalidator(String constantName) {
}

private Invalidator addConstantInvalidator(String constantName) {
Invalidator invalidator = OptoFactory.newConstantInvalidator();
final Invalidator invalidator = OptoFactory.newConstantInvalidator(this);
constantNameInvalidators.putIfAbsent(constantName, invalidator);

// fetch the invalidator back from the ConcurrentHashMap to ensure that
@@ -4921,6 +4934,9 @@ private MRIRecursionGuard oldRecursionGuard() {
// Compilation
private final JITCompiler jitCompiler;

// Cache invalidation
private final Caches caches;

// Note: this field and the following static initializer
// must be located be in this order!
private volatile static boolean securityRestricted = false;
@@ -5148,4 +5164,5 @@ private void deprecatedNetworkStackProperty() {
+ "Use JAVA_OPTS=-Djava.net.preferIPv4Stack=true OR prepend -J as a JRuby option.");
}
}

}
2 changes: 2 additions & 0 deletions core/src/main/java/org/jruby/RubyModule.java
Original file line number Diff line number Diff line change
@@ -1507,6 +1507,8 @@ protected DynamicMethod searchMethodCommon(String name) {
public void invalidateCacheDescendants() {
LOG.debug("{} invalidating descendants", baseName);

getRuntime().getCaches().incrementMethodInvalidations();

if (includingHierarchies.isEmpty()) {
// it's only us; just invalidate directly
methodInvalidator.invalidate();
2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/management/BeanManager.java
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@ public interface BeanManager {

void register(ParserStatsMBean parserStats);

void register(MethodCacheMBean methodCache);
void register(CachesMBean methodCache);

void register(Runtime runtime);

Original file line number Diff line number Diff line change
@@ -36,7 +36,7 @@ private static class DummyBeanManager implements BeanManager {
public void register(JITCompilerMBean jitCompiler) {}
public void register(ConfigMBean config) {}
public void register(ParserStatsMBean parserStats) {}
public void register(MethodCacheMBean methodCache) {}
public void register(CachesMBean methodCache) {}
public void register(Runtime runtime) {}
public void unregisterCompiler() {}
public void unregisterConfig() {}
4 changes: 2 additions & 2 deletions core/src/main/java/org/jruby/management/BeanManagerImpl.java
Original file line number Diff line number Diff line change
@@ -46,8 +46,8 @@ public void register(ParserStatsMBean parserStats) {
if (managementEnabled) register(base + "service=ParserStats", parserStats);
}

public void register(MethodCacheMBean methodCache) {
if (managementEnabled) register(base + "service=MethodCache", methodCache);
public void register(CachesMBean caches) {
if (managementEnabled) register(base + "service=Caches", caches);
}

public void register(Runtime runtime) {
26 changes: 26 additions & 0 deletions core/src/main/java/org/jruby/management/Caches.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package org.jruby.management;

import java.util.concurrent.atomic.AtomicLong;

public class Caches implements CachesMBean {
private final AtomicLong methodInvalidations = new AtomicLong(0);
private final AtomicLong constantInvalidations = new AtomicLong(0);

@Override
public long getMethodInvalidationCount() {
return methodInvalidations.get();
}

@Override
public long getConstantInvalidationCount() {
return constantInvalidations.get();
}

public long incrementMethodInvalidations() {
return methodInvalidations.incrementAndGet();
}

public long incrementConstantInvalidations() {
return constantInvalidations.incrementAndGet();
}
}
6 changes: 6 additions & 0 deletions core/src/main/java/org/jruby/management/CachesMBean.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package org.jruby.management;

public interface CachesMBean {
public long getMethodInvalidationCount();
public long getConstantInvalidationCount();
}
12 changes: 0 additions & 12 deletions core/src/main/java/org/jruby/management/MethodCacheMBean.java

This file was deleted.

30 changes: 30 additions & 0 deletions core/src/main/java/org/jruby/runtime/opto/ConstantInvalidator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package org.jruby.runtime.opto;

import org.jruby.management.Caches;

import java.util.List;

/**
* A validator specific to how we manage Ruby constants.
*/
public class ConstantInvalidator extends SwitchPointInvalidator {
private final Caches caches;

public ConstantInvalidator(Caches caches) {
this.caches = caches;
}

@Override
public void invalidate() {
// order is important; invalidate before increment
super.invalidate();
caches.incrementConstantInvalidations();
}

@Override
public void invalidateAll(List<Invalidator> invalidators) {
// order is important; invalidate before increment
super.invalidateAll(invalidators);
caches.incrementConstantInvalidations();
}
}
9 changes: 3 additions & 6 deletions core/src/main/java/org/jruby/runtime/opto/OptoFactory.java
Original file line number Diff line number Diff line change
@@ -26,6 +26,7 @@
***** END LICENSE BLOCK *****/
package org.jruby.runtime.opto;

import org.jruby.Ruby;
import org.jruby.RubyModule;
import org.jruby.runtime.ThreadContext;
import org.jruby.util.cli.Options;
@@ -48,8 +49,8 @@ public static final Object newConstantWrapper(Class type, Object object) {
return OptoFactory.CONSTANT_FACTORY.create(type, object);
}

public static Invalidator newConstantInvalidator() {
return new SwitchPointInvalidator();
public static Invalidator newConstantInvalidator(Ruby runtime) {
return new ConstantInvalidator(runtime.getCaches());
}

private static Boolean indyEnabled() {
@@ -74,10 +75,6 @@ public static Invalidator newMethodInvalidator(RubyModule module) {
return new GenerationInvalidator(module);
}

private static Boolean indyConstants() {
return Options.INVOKEDYNAMIC_CACHE_CONSTANTS.load();
}

private static void disableIndy() {
Options.COMPILE_INVOKEDYNAMIC.force("false");
}

0 comments on commit 0e6efdd

Please sign in to comment.