提交 341be22e authored 作者: Thomas Mueller's avatar Thomas Mueller

Clob.getSubString and Blob.getBytes are now up to 3 times faster.

上级 3ee41492
...@@ -18,7 +18,8 @@ Change Log ...@@ -18,7 +18,8 @@ Change Log
<h1>Change Log</h1> <h1>Change Log</h1>
<h2>Next Version (unreleased)</h2> <h2>Next Version (unreleased)</h2>
<ul><li>New database setting DEFAULT_CONNECTION (disabled by default) <ul><li>Clob.getSubString and Blob.getBytes are now up to 3 times faster.
</li><li>New database setting DEFAULT_CONNECTION (disabled by default)
to support DriverManager.getConnection("jdbc:default:connection"). to support DriverManager.getConnection("jdbc:default:connection").
Please note the Oracle JDBC driver will try to resolve this database URL if it is loaded before the H2 driver. Please note the Oracle JDBC driver will try to resolve this database URL if it is loaded before the H2 driver.
</li><li>JaQu: the static map Db.TOKENS was not synchronized. </li><li>JaQu: the static map Db.TOKENS was not synchronized.
......
...@@ -58,21 +58,7 @@ public class JdbcBlob extends TraceObject implements Blob { ...@@ -58,21 +58,7 @@ public class JdbcBlob extends TraceObject implements Blob {
return precision; return precision;
} }
} }
long size = 0; return IOUtils.copyAndCloseInput(value.getInputStream(), null);
InputStream in = value.getInputStream();
try {
byte[] buff = new byte[Constants.IO_BUFFER_SIZE];
while (true) {
int len = in.read(buff, 0, Constants.IO_BUFFER_SIZE);
if (len <= 0) {
break;
}
size += len;
}
} finally {
in.close();
}
return size;
} catch (Exception e) { } catch (Exception e) {
throw logAndConvert(e); throw logAndConvert(e);
} }
...@@ -106,14 +92,7 @@ public class JdbcBlob extends TraceObject implements Blob { ...@@ -106,14 +92,7 @@ public class JdbcBlob extends TraceObject implements Blob {
InputStream in = value.getInputStream(); InputStream in = value.getInputStream();
try { try {
IOUtils.skipFully(in, pos - 1); IOUtils.skipFully(in, pos - 1);
while (length > 0) { IOUtils.copy(in, out, length);
int x = in.read();
if (x < 0) {
break;
}
out.write(x);
length--;
}
} finally { } finally {
in.close(); in.close();
} }
......
...@@ -13,6 +13,7 @@ import java.io.PipedInputStream; ...@@ -13,6 +13,7 @@ import java.io.PipedInputStream;
import java.io.PipedOutputStream; import java.io.PipedOutputStream;
import java.io.Reader; import java.io.Reader;
import java.io.StringReader; import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer; import java.io.Writer;
import java.sql.Clob; import java.sql.Clob;
//## Java 1.6 begin ## //## Java 1.6 begin ##
...@@ -63,21 +64,7 @@ public class JdbcClob extends TraceObject implements Clob ...@@ -63,21 +64,7 @@ public class JdbcClob extends TraceObject implements Clob
return precision; return precision;
} }
} }
Reader in = value.getReader(); return IOUtils.copyAndCloseInput(value.getReader(), null, Long.MAX_VALUE);
try {
long size = 0;
char[] buff = new char[Constants.IO_BUFFER_SIZE];
while (true) {
int len = in.read(buff, 0, Constants.IO_BUFFER_SIZE);
if (len <= 0) {
break;
}
size += len;
}
return size;
} finally {
in.close();
}
} catch (Exception e) { } catch (Exception e) {
throw logAndConvert(e); throw logAndConvert(e);
} }
...@@ -196,21 +183,15 @@ public class JdbcClob extends TraceObject implements Clob ...@@ -196,21 +183,15 @@ public class JdbcClob extends TraceObject implements Clob
if (length < 0) { if (length < 0) {
throw DbException.getInvalidValueException("length", length); throw DbException.getInvalidValueException("length", length);
} }
StringBuilder buff = new StringBuilder(Math.min(4096, length)); StringWriter writer = new StringWriter(Math.min(Constants.IO_BUFFER_SIZE, length));
Reader reader = value.getReader(); Reader reader = value.getReader();
try { try {
IOUtils.skipFully(reader, pos - 1); IOUtils.skipFully(reader, pos - 1);
for (int i = 0; i < length; i++) { IOUtils.copyAndCloseInput(reader, writer, length);
int ch = reader.read();
if (ch < 0) {
break;
}
buff.append((char) ch);
}
} finally { } finally {
reader.close(); reader.close();
} }
return buff.toString(); return writer.toString();
} catch (Exception e) { } catch (Exception e) {
throw logAndConvert(e); throw logAndConvert(e);
} }
......
...@@ -354,21 +354,13 @@ class WebThread extends WebApp implements Runnable { ...@@ -354,21 +354,13 @@ class WebThread extends WebApp implements Runnable {
len -= headerBytes; len -= headerBytes;
File file = new File(WebServer.TRANSFER, fileName); File file = new File(WebServer.TRANSFER, fileName);
OutputStream out = new FileOutputStream(file); OutputStream out = new FileOutputStream(file);
byte[] bytes = Utils.newBytes(Constants.IO_BUFFER_SIZE); IOUtils.copy(in, out, len);
while (len > 0) {
int l = Math.min(Constants.IO_BUFFER_SIZE, len);
l = in.read(bytes, 0, l);
if (l < 0) {
break;
}
out.write(bytes, 0, l);
len -= l;
}
out.close(); out.close();
// remove the boundary // remove the boundary
RandomAccessFile f = new RandomAccessFile(file, "rw"); RandomAccessFile f = new RandomAccessFile(file, "rw");
int testSize = (int) Math.min(f.length(), Constants.IO_BUFFER_SIZE); int testSize = (int) Math.min(f.length(), Constants.IO_BUFFER_SIZE);
f.seek(f.length() - testSize); f.seek(f.length() - testSize);
byte[] bytes = Utils.newBytes(Constants.IO_BUFFER_SIZE);
f.readFully(bytes, 0, testSize); f.readFully(bytes, 0, testSize);
String s = new String(bytes, "ASCII"); String s = new String(bytes, "ASCII");
int x = s.lastIndexOf(boundary); int x = s.lastIndexOf(boundary);
......
...@@ -18,7 +18,6 @@ import java.net.URL; ...@@ -18,7 +18,6 @@ import java.net.URL;
import org.h2.constant.ErrorCode; import org.h2.constant.ErrorCode;
import org.h2.constant.SysProperties; import org.h2.constant.SysProperties;
import org.h2.engine.Constants;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.util.IOUtils; import org.h2.util.IOUtils;
import org.h2.util.StringUtils; import org.h2.util.StringUtils;
...@@ -322,17 +321,9 @@ public class FileSystemDisk extends FileSystem { ...@@ -322,17 +321,9 @@ public class FileSystemDisk extends FileSystem {
OutputStream out = null; OutputStream out = null;
InputStream in = null; InputStream in = null;
try { try {
out = IOUtils.openFileOutputStream(target, false);
in = IOUtils.openFileInputStream(source); in = IOUtils.openFileInputStream(source);
byte[] buffer = new byte[Constants.IO_BUFFER_SIZE]; out = IOUtils.openFileOutputStream(target, false);
while (true) { IOUtils.copy(in, out);
int len = in.read(buffer);
if (len < 0) {
break;
}
out.write(buffer, 0, len);
}
out.close();
} catch (IOException e) { } catch (IOException e) {
throw DbException.convertIOException(e, "original: " + source + " copy: " + target); throw DbException.convertIOException(e, "original: " + source + " copy: " + target);
} finally { } finally {
......
...@@ -280,24 +280,15 @@ public class Recover extends Tool implements DataHandler { ...@@ -280,24 +280,15 @@ public class Recover extends Tool implements DataHandler {
private void dumpLob(String fileName, boolean lobCompression) { private void dumpLob(String fileName, boolean lobCompression) {
OutputStream fileOut = null; OutputStream fileOut = null;
FileStore fileStore = null; FileStore fileStore = null;
int size = 0; long size = 0;
String n = fileName + (lobCompression ? ".comp" : "") + ".txt"; String n = fileName + (lobCompression ? ".comp" : "") + ".txt";
InputStream in = null; InputStream in = null;
try { try {
fileOut = IOUtils.openFileOutputStream(n, false); fileOut = IOUtils.openFileOutputStream(n, false);
fileStore = FileStore.open(null, fileName, "r"); fileStore = FileStore.open(null, fileName, "r");
fileStore.init(); fileStore.init();
in = new BufferedInputStream(new FileStoreInputStream(fileStore, this, lobCompression, false)); in = new FileStoreInputStream(fileStore, this, lobCompression, false);
byte[] buffer = new byte[Constants.IO_BUFFER_SIZE]; size = IOUtils.copy(in, fileOut);
while (true) {
int l = in.read(buffer);
if (l < 0) {
break;
}
fileOut.write(buffer, 0, l);
size += l;
}
fileOut.close();
} catch (Throwable e) { } catch (Throwable e) {
// this is usually not a problem, because we try both compressed and // this is usually not a problem, because we try both compressed and
// uncompressed // uncompressed
......
...@@ -33,8 +33,6 @@ import org.h2.store.fs.FileSystem; ...@@ -33,8 +33,6 @@ import org.h2.store.fs.FileSystem;
*/ */
public class IOUtils { public class IOUtils {
private static final int BUFFER_BLOCK_SIZE = 4 * 1024;
private IOUtils() { private IOUtils() {
// utility class // utility class
} }
...@@ -126,7 +124,7 @@ public class IOUtils { ...@@ -126,7 +124,7 @@ public class IOUtils {
* input stream. Exceptions while closing are ignored. * input stream. Exceptions while closing are ignored.
* *
* @param in the input stream * @param in the input stream
* @param out the output stream * @param out the output stream (null if writing is not required)
* @return the number of bytes copied * @return the number of bytes copied
*/ */
public static long copyAndCloseInput(InputStream in, OutputStream out) throws IOException { public static long copyAndCloseInput(InputStream in, OutputStream out) throws IOException {
...@@ -144,22 +142,40 @@ public class IOUtils { ...@@ -144,22 +142,40 @@ public class IOUtils {
* are kept open. * are kept open.
* *
* @param in the input stream * @param in the input stream
* @param out the output stream * @param out the output stream (null if writing is not required)
* @return the number of bytes copied * @return the number of bytes copied
*/ */
public static long copy(InputStream in, OutputStream out) throws IOException { public static long copy(InputStream in, OutputStream out) throws IOException {
return copy(in, out, Long.MAX_VALUE);
}
/**
* Copy all data from the input stream to the output stream. Both streams
* are kept open.
*
* @param in the input stream
* @param out the output stream (null if writing is not required)
* @param length the maximum number of bytes to copy
* @return the number of bytes copied
*/
public static long copy(InputStream in, OutputStream out, long length) throws IOException {
try { try {
long written = 0; long copied = 0;
byte[] buffer = new byte[4 * 1024]; int len = (int) Math.min(length, Constants.IO_BUFFER_SIZE);
while (true) { byte[] buffer = new byte[len];
int len = in.read(buffer); while (length > 0) {
len = in.read(buffer, 0, len);
if (len < 0) { if (len < 0) {
break; break;
} }
out.write(buffer, 0, len); if (out != null) {
written += len; out.write(buffer, 0, len);
}
copied += len;
length -= len;
len = (int) Math.min(length, Constants.IO_BUFFER_SIZE);
} }
return written; return copied;
} catch (Exception e) { } catch (Exception e) {
throw DbException.convertToIOException(e); throw DbException.convertToIOException(e);
} }
...@@ -170,22 +186,28 @@ public class IOUtils { ...@@ -170,22 +186,28 @@ public class IOUtils {
* Exceptions while closing are ignored. * Exceptions while closing are ignored.
* *
* @param in the reader * @param in the reader
* @param out the writer * @param out the writer (null if writing is not required)
* @param length the maximum number of bytes to copy
* @return the number of characters copied * @return the number of characters copied
*/ */
public static long copyAndCloseInput(Reader in, Writer out) throws IOException { public static long copyAndCloseInput(Reader in, Writer out, long length) throws IOException {
try { try {
long written = 0; long copied = 0;
char[] buffer = new char[4 * 1024]; int len = (int) Math.min(length, Constants.IO_BUFFER_SIZE);
while (true) { char[] buffer = new char[len];
int len = in.read(buffer); while (length > 0) {
len = in.read(buffer, 0, len);
if (len < 0) { if (len < 0) {
break; break;
} }
out.write(buffer, 0, len); if (out != null) {
written += len; out.write(buffer, 0, len);
}
length -= len;
len = (int) Math.min(length, Constants.IO_BUFFER_SIZE);
copied += len;
} }
return written; return copied;
} catch (Exception e) { } catch (Exception e) {
throw DbException.convertToIOException(e); throw DbException.convertToIOException(e);
} finally { } finally {
...@@ -253,18 +275,9 @@ public class IOUtils { ...@@ -253,18 +275,9 @@ public class IOUtils {
if (length <= 0) { if (length <= 0) {
length = Integer.MAX_VALUE; length = Integer.MAX_VALUE;
} }
int block = Math.min(BUFFER_BLOCK_SIZE, length); int block = Math.min(Constants.IO_BUFFER_SIZE, length);
ByteArrayOutputStream out = new ByteArrayOutputStream(block); ByteArrayOutputStream out = new ByteArrayOutputStream(block);
byte[] buff = new byte[block]; copy(in, out, length);
while (length > 0) {
int len = Math.min(block, length);
len = in.read(buff, 0, len);
if (len < 0) {
break;
}
out.write(buff, 0, len);
length -= len;
}
return out.toByteArray(); return out.toByteArray();
} catch (Exception e) { } catch (Exception e) {
throw DbException.convertToIOException(e); throw DbException.convertToIOException(e);
...@@ -286,18 +299,9 @@ public class IOUtils { ...@@ -286,18 +299,9 @@ public class IOUtils {
if (length <= 0) { if (length <= 0) {
length = Integer.MAX_VALUE; length = Integer.MAX_VALUE;
} }
int block = Math.min(BUFFER_BLOCK_SIZE, length); int block = Math.min(Constants.IO_BUFFER_SIZE, length);
StringWriter out = new StringWriter(length == Integer.MAX_VALUE ? block : length); StringWriter out = new StringWriter(block);
char[] buff = new char[block]; copyAndCloseInput(in, out, length);
while (length > 0) {
int len = Math.min(block, length);
len = in.read(buff, 0, len);
if (len < 0) {
break;
}
out.write(buff, 0, len);
length -= len;
}
return out.toString(); return out.toString();
} finally { } finally {
in.close(); in.close();
......
...@@ -218,15 +218,7 @@ public class SourceCompiler { ...@@ -218,15 +218,7 @@ public class SourceCompiler {
private static void copyInThread(final InputStream in, final OutputStream out) { private static void copyInThread(final InputStream in, final OutputStream out) {
new Task() { new Task() {
public void call() throws IOException { public void call() throws IOException {
while (true) { IOUtils.copy(in, out);
int x = in.read();
if (x < 0) {
return;
}
if (out != null) {
out.write(x);
}
}
} }
}.execute(); }.execute();
} }
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论