Permalink
Browse files

Also cache negative uri cache lookups.

Serving views or resources which do not have a controller is pretty slow due to uri lookups on every request.
This fixes it by also caching uri looks which do not have a controller.

To avoid DOS attacks, the cache is also limited in size, and the size can
be controlled via the grails.urlmapping.cache.maxsize config property.
  • Loading branch information...
1 parent ba77c1b commit 08d543b74810debda7a8adb5efed41057597ad5e @recht recht committed with lhotari May 14, 2012
@@ -25,6 +25,10 @@ dependencies {
}
}
+ compile( "com.googlecode.concurrentlinkedhashmap:concurrentlinkedhashmap-lru:${concurrentlinkedhashmapVersion}" ) {
+ exclude group: 'commons-logging', module:'commons-logging'
+ }
+
// These 3 are required by UAA but not Grails (non OSGI version of excludes above)
compile 'com.google.protobuf:protobuf-java:2.3.0',
'com.googlecode.json-simple:json-simple:1.1',
@@ -17,26 +17,48 @@
import grails.util.Environment;
-import java.util.concurrent.ConcurrentHashMap;
+import org.codehaus.groovy.grails.plugins.support.aware.GrailsApplicationAware;
+
+import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap;
/**
+ * Lookup controllers for uris.
+ *
+ * <p>This class is responsible for looking up controller classes for uris.</p>
+ *
+ * <p>Lookups are cached in non-development mode, and the cache size can be controlled using the grails.urlmapping.cache.maxsize config property.</p>
+ *
* @author Marc Palmer (marc@anyware.co.uk)
*/
-public class ControllerArtefactHandler extends ArtefactHandlerAdapter {
+public class ControllerArtefactHandler extends ArtefactHandlerAdapter implements GrailsApplicationAware {
+ private static final String URL_MAPPING_CACHE_MAX_SIZE = "grails.urlmapping.cache.maxsize";
+ private static final GrailsClass NO_CONTROLLER = new AbstractGrailsClass(Object.class, "Controller") {};
+
public static final String TYPE = "Controller";
public static final String PLUGIN_NAME = "controllers";
- private ConcurrentHashMap<String, GrailsClass> uriToControllerClassCache;
+ private ConcurrentLinkedHashMap<String, GrailsClass> uriToControllerClassCache;
private ArtefactInfo artefactInfo;
+ private GrailsApplication grailsApplication;
+
public ControllerArtefactHandler() {
super(TYPE, GrailsControllerClass.class, DefaultGrailsControllerClass.class,
DefaultGrailsControllerClass.CONTROLLER, false);
}
@Override
public void initialize(ArtefactInfo artefacts) {
- uriToControllerClassCache = new ConcurrentHashMap<String, GrailsClass>();
+ Object cacheSize = grailsApplication.getFlatConfig().get(URL_MAPPING_CACHE_MAX_SIZE);
+ if (cacheSize == null) {
+ cacheSize = 10000;
+ }
+
+ uriToControllerClassCache = new ConcurrentLinkedHashMap.Builder<String, GrailsClass>()
+ .initialCapacity(500)
+ .maximumWeightedCapacity(new Integer(cacheSize.toString()))
+ .build();
+
artefactInfo = artefacts;
}
@@ -63,13 +85,23 @@ public GrailsClass getArtefactForFeature(Object feature) {
break;
}
}
- if (controllerClass != null) {
- // don't cache for dev environment
- if (Environment.getCurrent() != Environment.DEVELOPMENT) {
- uriToControllerClassCache.putIfAbsent(uri, controllerClass);
- }
+ if (controllerClass == null) {
+ controllerClass = NO_CONTROLLER;
}
+
+ // don't cache for dev environment
+ if (Environment.getCurrent() != Environment.DEVELOPMENT) {
+ uriToControllerClassCache.put(uri, controllerClass);
+ }
+ }
+
+ if (controllerClass == NO_CONTROLLER) {
+ controllerClass = null;
}
return controllerClass;
}
+
+ public void setGrailsApplication(GrailsApplication grailsApplication) {
+ this.grailsApplication = grailsApplication;
+ }
}
View
@@ -18,9 +18,6 @@ dependencies {
compile "commons-io:commons-io:${commonsIOVersion}"
compile "commons-lang:commons-lang:$commonsLangVersion"
- compile( "com.googlecode.concurrentlinkedhashmap:concurrentlinkedhashmap-lru:${concurrentlinkedhashmapVersion}" ) {
- exclude group: 'commons-logging', module:'commons-logging'
- }
compile 'opensymphony:sitemesh:2.4'
compile "org.springframework:spring-webmvc:${springVersion}"

0 comments on commit 08d543b

Please sign in to comment.