提交 e8c85730 authored 作者: Thomas Mueller's avatar Thomas Mueller

MVStore: the store is now auto-compacted automatically up to some point, to…

MVStore: the store is now auto-compacted automatically up to some point, to avoid very large file sizes. This area is still work in progress.
上级 d7c685df
...@@ -17,7 +17,8 @@ Change Log ...@@ -17,7 +17,8 @@ Change Log
<h1>Change Log</h1> <h1>Change Log</h1>
<h2>Next Version (unreleased)</h2> <h2>Next Version (unreleased)</h2>
<ul><li>MVStore: new utility to compress a store. <ul><li>MVStore: the store is now auto-compacted automatically up to some point,
to avoid very large file sizes. This area is still work in progress.
</li><li>Sequences of temporary tables (auto-increment or identity columns) </li><li>Sequences of temporary tables (auto-increment or identity columns)
were persisted unnecessarily in the database file, and were not removed were persisted unnecessarily in the database file, and were not removed
when re-opening the database. when re-opening the database.
......
...@@ -184,8 +184,18 @@ public class Chunk { ...@@ -184,8 +184,18 @@ public class Chunk {
return c; return c;
} }
/**
* Calculate the fill rate in %. 0 means empty, 100 means full.
*
* @return the fill rate
*/
public int getFillRate() { public int getFillRate() {
return (int) (maxLen == 0 ? 0 : 100 * maxLenLive / maxLen); if (maxLenLive == 0) {
return 0;
} else if (maxLenLive == maxLen) {
return 100;
}
return 1 + (int) (98 * maxLenLive / maxLen);
} }
@Override @Override
......
...@@ -238,6 +238,9 @@ public class MVStore { ...@@ -238,6 +238,9 @@ public class MVStore {
*/ */
private int autoCommitDelay; private int autoCommitDelay;
private int autoCompactFillRate = 10;
private int autoCompactSize = 2 * 1024 * 1024;
/** /**
* Create and open the store. * Create and open the store.
* *
...@@ -1531,10 +1534,10 @@ public class MVStore { ...@@ -1531,10 +1534,10 @@ public class MVStore {
* before calling this method. * before calling this method.
* *
* @param targetFillRate the minimum percentage of live entries * @param targetFillRate the minimum percentage of live entries
* @param saving the amount of saved space * @param write the number of bytes to write
* @return if a chunk was re-written * @return if a chunk was re-written
*/ */
public synchronized boolean compact(int targetFillRate, int saving) { public synchronized boolean compact(int targetFillRate, int write) {
checkOpen(); checkOpen();
if (lastChunk == null) { if (lastChunk == null) {
// nothing to do // nothing to do
...@@ -1588,21 +1591,20 @@ public class MVStore { ...@@ -1588,21 +1591,20 @@ public class MVStore {
} }
}); });
// find out up to were in the old list we need to move // find out up to were in the old list we need to move
long saved = 0; long written = 0;
int chunkCount = 0; int chunkCount = 0;
Chunk move = null; Chunk move = null;
for (Chunk c : old) { for (Chunk c : old) {
long size = c.maxLen - c.maxLenLive;
if (move != null) { if (move != null) {
if (c.collectPriority > 0 && saved > saving) { if (c.collectPriority > 0 && written > write) {
break; break;
} }
} }
saved += size; written += c.maxLenLive;
chunkCount++; chunkCount++;
move = c; move = c;
} }
if (chunkCount <= 1) { if (chunkCount < 1) {
return false; return false;
} }
// remove the chunks we want to keep from this list // remove the chunks we want to keep from this list
...@@ -2367,17 +2369,26 @@ public class MVStore { ...@@ -2367,17 +2369,26 @@ public class MVStore {
if (time <= lastCommitTime + autoCommitDelay) { if (time <= lastCommitTime + autoCommitDelay) {
return; return;
} }
if (!hasUnsavedChanges()) { if (hasUnsavedChanges()) {
try {
commitAndSave();
} catch (Exception e) {
if (backgroundExceptionHandler != null) {
backgroundExceptionHandler.uncaughtException(null, e);
return; return;
} }
}
}
if (autoCompactSize > 0) {
try { try {
commitAndSave(); compact(autoCompactFillRate, autoCompactSize);
} catch (Exception e) { } catch (Exception e) {
if (backgroundExceptionHandler != null) { if (backgroundExceptionHandler != null) {
backgroundExceptionHandler.uncaughtException(null, e); backgroundExceptionHandler.uncaughtException(null, e);
} }
} }
} }
}
/** /**
* Set the read cache size in MB. * Set the read cache size in MB.
......
...@@ -1299,7 +1299,6 @@ public class TestMVStore extends TestBase { ...@@ -1299,7 +1299,6 @@ public class TestMVStore extends TestBase {
} }
s.commit(); s.commit();
assertTrue(s.compact(100, 50 * 1024)); assertTrue(s.compact(100, 50 * 1024));
assertTrue(s.compact(100, 1024));
s.close(); s.close();
long len2 = FileUtils.size(fileName); long len2 = FileUtils.size(fileName);
assertTrue("len2: " + len2 + " len: " + len, len2 < len); assertTrue("len2: " + len2 + " len: " + len, len2 < len);
......
...@@ -6,9 +6,14 @@ ...@@ -6,9 +6,14 @@
package org.h2.dev.util; package org.h2.dev.util;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader; import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.io.InputStreamReader;
import java.io.LineNumberReader; import java.io.LineNumberReader;
import java.io.PrintWriter;
import java.io.Reader;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.regex.Pattern; import java.util.regex.Pattern;
...@@ -29,6 +34,10 @@ public class ThreadDumpCleaner { ...@@ -29,6 +34,10 @@ public class ThreadDumpCleaner {
"at java.io.FileInputStream.readBytes(?s).*?\n\n", "at java.io.FileInputStream.readBytes(?s).*?\n\n",
"\".*?\".*?\n java.lang.Thread.State:.*\n\t" + "\".*?\".*?\n java.lang.Thread.State:.*\n\t" +
"at sun.nio.ch.ServerSocketChannelImpl.accept(?s).*?\n\n", "at sun.nio.ch.ServerSocketChannelImpl.accept(?s).*?\n\n",
"\".*?\".*?\n java.lang.Thread.State:.*\n\t" +
"at sun.nio.ch.EPollArrayWrapper.epollWait(?s).*?\n\n",
"\".*?\".*?\n java.lang.Thread.State:.*\n\t" +
"at java.lang.Object.wait(?s).*?\n\n",
"JNI global references:.*\n\n", "JNI global references:.*\n\n",
}; };
...@@ -46,25 +55,45 @@ public class ThreadDumpCleaner { ...@@ -46,25 +55,45 @@ public class ThreadDumpCleaner {
* @param args the command line arguments * @param args the command line arguments
*/ */
public static void main(String... args) throws IOException { public static void main(String... args) throws IOException {
FileReader r = new FileReader(args[0]); String inFile = null, outFile = null;
LineNumberReader in = new LineNumberReader(new BufferedReader(r)); for (int i = 0; i < args.length; i++) {
new ThreadDumpCleaner().run(in); if (args[i].equals("-in")) {
inFile = args[++i];
} else if (args[i].equals("-out")) {
outFile = args[++i];
}
}
PrintWriter writer;
if (outFile != null) {
writer = new PrintWriter(new BufferedWriter(new FileWriter(outFile)));
} else {
writer = new PrintWriter(System.out);
}
Reader r;
if (inFile != null) {
r = new FileReader(inFile);
} else {
r = new InputStreamReader(System.in);
}
new ThreadDumpCleaner().run(
new LineNumberReader(new BufferedReader(r)),
writer);
} }
private void run(LineNumberReader in) throws IOException { private void run(LineNumberReader reader, PrintWriter writer) throws IOException {
StringBuilder buff = new StringBuilder(); StringBuilder buff = new StringBuilder();
while (true) { while (true) {
String line = in.readLine(); String line = reader.readLine();
if (line == null) { if (line == null) {
break; break;
} }
buff.append(line).append('\n'); buff.append(line).append('\n');
if (line.length() == 0) { if (line.length() == 0) {
System.out.print(filter(buff.toString())); writer.print(filter(buff.toString()));
buff = new StringBuilder(); buff = new StringBuilder();
} }
} }
System.out.print(filter(buff.toString())); writer.println(filter(buff.toString()));
} }
private String filter(String s) { private String filter(String s) {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论