提交 5831e75e authored 作者: Noel Grandin's avatar Noel Grandin 提交者: GitHub

Merge pull request #553 from andreitokar/mem_optimization

eliminate memory estimations for "mem:" case
......@@ -72,7 +72,6 @@ public class MVMap<K, V> extends AbstractMap<K, V>
protected MVMap(DataType keyType, DataType valueType) {
this.keyType = keyType;
this.valueType = valueType;
this.root = Page.createEmpty(this, -1);
}
/**
......@@ -106,6 +105,7 @@ public class MVMap<K, V> extends AbstractMap<K, V>
this.id = DataUtils.readHexInt(config, "id", 0);
this.createVersion = DataUtils.readHexLong(config, "createVersion", 0);
this.writeVersion = store.getCurrentVersion();
this.root = Page.createEmpty(this, -1);
}
/**
......
......@@ -120,7 +120,7 @@ MVStore:
/**
* A persistent storage for maps.
*/
public class MVStore {
public final class MVStore {
/**
* Whether assertions are enabled.
......@@ -292,12 +292,21 @@ public class MVStore {
Object o = config.get("compress");
this.compressionLevel = o == null ? 0 : (Integer) o;
String fileName = (String) config.get("fileName");
fileStore = (FileStore) config.get("fileStore");
fileStoreIsProvided = fileStore != null;
if(fileStore == null && fileName != null) {
fileStore = new FileStore();
}
o = config.get("pageSplitSize");
if (o == null) {
pageSplitSize = fileName == null ? 4 * 1024 : 16 * 1024;
int pgSplitSize;
if (o != null) {
pgSplitSize = (Integer) o;
} else if(fileStore != null) {
pgSplitSize = 16 * 1024;
} else {
pageSplitSize = (Integer) o;
pgSplitSize = 48; // number of keys per page in that case
}
pageSplitSize = pgSplitSize;
o = config.get("backgroundExceptionHandler");
this.backgroundExceptionHandler = (UncaughtExceptionHandler) o;
meta = new MVMap<String, String>(StringDataType.INSTANCE,
......@@ -306,18 +315,11 @@ public class MVStore {
c.put("id", 0);
c.put("createVersion", currentVersion);
meta.init(this, c);
fileStore = (FileStore) config.get("fileStore");
if (fileName == null && fileStore == null) {
if (fileStore == null) {
cache = null;
cacheChunkRef = null;
return;
}
if (fileStore == null) {
fileStoreIsProvided = false;
fileStore = new FileStore();
} else {
fileStoreIsProvided = true;
}
retentionTime = fileStore.getDefaultRetentionTime();
boolean readOnly = config.containsKey("readOnly");
o = config.get("cacheSize");
......@@ -995,7 +997,7 @@ public class MVStore {
*
* @return the new version
*/
public long commit() {
public synchronized long commit() {
if (fileStore != null) {
return commitAndSave();
}
......
......@@ -36,6 +36,7 @@ public class Page {
* An empty object array.
*/
public static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
private static final int IN_MEMORY = Integer.MIN_VALUE;
private final MVMap<?, ?> map;
private long version;
......@@ -52,7 +53,7 @@ public class Page {
private int cachedCompare;
/**
* The estimated memory used.
* The estimated memory used in persistent case, IN_MEMORY marker value otherwise.
*/
private int memory;
......@@ -125,13 +126,15 @@ public class Page {
p.values = values;
p.children = children;
p.totalCount = totalCount;
if (memory == 0) {
MVStore store = map.store;
if(store.getFileStore() == null) {
p.memory = IN_MEMORY;
} else if (memory == 0) {
p.recalculateMemory();
} else {
p.addMemory(memory);
}
MVStore store = map.store;
if (store != null) {
if(store.getFileStore() != null) {
store.registerUnsavedPage(p.memory);
}
return p;
......@@ -146,18 +149,8 @@ public class Page {
* @return the page
*/
public static Page create(MVMap<?, ?> map, long version, Page source) {
Page p = new Page(map, version);
// the position is 0
p.keys = source.keys;
p.values = source.values;
p.children = source.children;
p.totalCount = source.totalCount;
p.memory = source.memory;
MVStore store = map.store;
if (store != null) {
store.registerUnsavedPage(p.memory);
}
return p;
return create(map, version, source.keys, source.values, source.children,
source.totalCount, source.memory);
}
/**
......@@ -302,7 +295,7 @@ public class Page {
Page newPage = create(map, version,
keys, values,
children, totalCount,
getMemory());
memory);
// mark the old as deleted
removePage();
newPage.cachedCompare = cachedCompare;
......@@ -368,7 +361,11 @@ public class Page {
* @return the page with the entries after the split index
*/
Page split(int at) {
return isLeaf() ? splitLeaf(at) : splitNode(at);
Page page = isLeaf() ? splitLeaf(at) : splitNode(at);
if(isPersistent()) {
recalculateMemory();
}
return page;
}
private Page splitLeaf(int at) {
......@@ -388,9 +385,7 @@ public class Page {
Page newPage = create(map, version,
bKeys, bValues,
null,
bKeys.length, 0);
recalculateMemory();
newPage.recalculateMemory();
b, 0);
return newPage;
}
......@@ -422,8 +417,6 @@ public class Page {
bKeys, null,
bChildren,
t, 0);
recalculateMemory();
newPage.recalculateMemory();
return newPage;
}
......@@ -498,13 +491,15 @@ public class Page {
// this is slightly slower:
// keys = Arrays.copyOf(keys, keys.length);
keys = keys.clone();
Object old = keys[index];
DataType keyType = map.getKeyType();
int mem = keyType.getMemory(key);
if (old != null) {
mem -= keyType.getMemory(old);
if(isPersistent()) {
Object old = keys[index];
DataType keyType = map.getKeyType();
int mem = keyType.getMemory(key);
if (old != null) {
mem -= keyType.getMemory(old);
}
addMemory(mem);
}
addMemory(mem);
keys[index] = key;
}
......@@ -521,8 +516,10 @@ public class Page {
// values = Arrays.copyOf(values, values.length);
values = values.clone();
DataType valueType = map.getValueType();
addMemory(valueType.getMemory(value) -
valueType.getMemory(old));
if(isPersistent()) {
addMemory(valueType.getMemory(value) -
valueType.getMemory(old));
}
values[index] = value;
return old;
}
......@@ -569,8 +566,10 @@ public class Page {
keys[index] = key;
values[index] = value;
totalCount++;
addMemory(map.getKeyType().getMemory(key) +
map.getValueType().getMemory(value));
if(isPersistent()) {
addMemory(map.getKeyType().getMemory(key) +
map.getValueType().getMemory(value));
}
}
/**
......@@ -595,8 +594,10 @@ public class Page {
children = newChildren;
totalCount += childPage.totalCount;
addMemory(map.getKeyType().getMemory(key) +
DataUtils.PAGE_MEMORY_CHILD);
if(isPersistent()) {
addMemory(map.getKeyType().getMemory(key) +
DataUtils.PAGE_MEMORY_CHILD);
}
}
/**
......@@ -607,22 +608,28 @@ public class Page {
public void remove(int index) {
int keyLength = keys.length;
int keyIndex = index >= keyLength ? index - 1 : index;
Object old = keys[keyIndex];
addMemory(-map.getKeyType().getMemory(old));
if(isPersistent()) {
Object old = keys[keyIndex];
addMemory(-map.getKeyType().getMemory(old));
}
Object[] newKeys = new Object[keyLength - 1];
DataUtils.copyExcept(keys, newKeys, keyLength, keyIndex);
keys = newKeys;
if (values != null) {
old = values[index];
addMemory(-map.getValueType().getMemory(old));
if(isPersistent()) {
Object old = values[index];
addMemory(-map.getValueType().getMemory(old));
}
Object[] newValues = new Object[keyLength - 1];
DataUtils.copyExcept(values, newValues, keyLength, index);
values = newValues;
totalCount--;
}
if (children != null) {
addMemory(-DataUtils.PAGE_MEMORY_CHILD);
if(isPersistent()) {
addMemory(-DataUtils.PAGE_MEMORY_CHILD);
}
long countOffset = children[index].count;
int childCount = children.length;
......@@ -887,16 +894,23 @@ public class Page {
return pos != 0 ? (int) (pos | (pos >>> 32)) : super.hashCode();
}
private boolean isPersistent() {
return memory != IN_MEMORY;
}
public int getMemory() {
if (MVStore.ASSERT) {
int mem = memory;
recalculateMemory();
if (mem != memory) {
throw DataUtils.newIllegalStateException(
DataUtils.ERROR_INTERNAL, "Memory calculation error");
if (isPersistent()) {
if (MVStore.ASSERT) {
int mem = memory;
recalculateMemory();
if (mem != memory) {
throw DataUtils.newIllegalStateException(
DataUtils.ERROR_INTERNAL, "Memory calculation error");
}
}
return memory;
}
return memory;
return getKeyCount();
}
private void addMemory(int mem) {
......@@ -928,11 +942,13 @@ public class Page {
* Remove the page.
*/
public void removePage() {
long p = pos;
if (p == 0) {
removedInMemory = true;
if(isPersistent()) {
long p = pos;
if (p == 0) {
removedInMemory = true;
}
map.removePage(p, memory);
}
map.removePage(p, memory);
}
/**
......
......@@ -1416,7 +1416,9 @@ public class TestMVStore extends TestBase {
assertEquals(i + 1, m.size());
}
assertEquals(1000, m.size());
assertEquals(131896, s.getUnsavedMemory());
// previously (131896) we fail to account for initial root page for every map
// there are two of them here (meta and "data"), hence lack of 256 bytes
assertEquals(132152, s.getUnsavedMemory());
s.commit();
assertEquals(2, s.getFileStore().getWriteCount());
s.close();
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论