Rewrite my menu preferences to avoid ProjectState caching

Storing individual user menus inside of the All-Users project state
object leads to unconstrained server memory growth. As users load
preferences the ProjctState object retains all of their preferences.
The cache is only cleared when refs/meta/config within All-Users is
modified, which is very infrequent.

Instead of abusing the ProjectLevelConfig for user preferences,
build a new type VersionedAccountPreferences from the base helper
VersionedMetaData. Load and store all preferences dynamically from
Git. This is similar to the model change metadata will use in the
future, so flushing out any performance problems now with simpler
models like the user preference store is valuable.

User preferences are not accessed very frequently; only at initial
tab load and if the user modifies their settings. If there are any
current performance problems with this storage model the current
impact will be slight while the issue is worked on.

Change-Id: I74c1aed4119b48557e954cc602eb1cf178d201bb
This commit is contained in:
Shawn Pearce
2014-04-14 12:30:03 -07:00
parent 2758c69115
commit 3f621ca0c2
8 changed files with 195 additions and 110 deletions

View File

@@ -87,7 +87,7 @@ public class ProjectState {
private final List<CommentLinkInfo> commentLinks;
private final ProjectConfig config;
private final Map<ConfigKey, ProjectLevelConfig> configs;
private final Map<String, ProjectLevelConfig> configs;
private final Set<AccountGroup.UUID> localOwners;
/** Prolog rule state. */
@@ -223,16 +223,11 @@ public class ProjectState {
}
public ProjectLevelConfig getConfig(String fileName) {
return getConfig(fileName, RefNames.REFS_CONFIG);
}
public ProjectLevelConfig getConfig(String fileName, String ref) {
ConfigKey cfgKey = new ConfigKey(fileName, ref);
if (configs.containsKey(cfgKey)) {
return configs.get(cfgKey);
if (configs.containsKey(fileName)) {
return configs.get(fileName);
}
ProjectLevelConfig cfg = new ProjectLevelConfig(fileName, ref, this);
ProjectLevelConfig cfg = new ProjectLevelConfig(fileName, this);
try {
Repository git = gitMgr.openRepository(getProject().getNameKey());
try {
@@ -246,7 +241,7 @@ public class ProjectState {
log.warn("Failed to load " + fileName + " for " + getProject().getName(), e);
}
configs.put(cfgKey, cfg);
configs.put(fileName, cfg);
return cfg;
}
@@ -505,26 +500,4 @@ public class ProjectState {
}
return false;
}
private static class ConfigKey {
final String file;
final String ref;
ConfigKey(String file, String ref) {
this.file = file;
this.ref = ref;
}
@Override
public boolean equals(Object other) {
return other instanceof ConfigKey
&& file.equals(((ConfigKey) other).file)
&& ref.equals(((ConfigKey) other).ref);
}
@Override
public int hashCode() {
return file.hashCode() * 31 + ref.hashCode();
}
}
}