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