Permalink
Browse files

perf: avoid BaseQueryKey.toString in CachedQuery.getSize (#1227)

LruCache uses .getSize to limit the size of the cache, so this method
should refrain from doing memory allocations.

closes #1226
  • Loading branch information...
benbenw authored and vlsi committed Jun 29, 2018
1 parent 191d84e commit 669fc31ec187b27d15ee24f84c389260c54ddf25
@@ -5,13 +5,15 @@
package org.postgresql.core;
import org.postgresql.util.CanEstimateSize;
/**
* This class is used as a cache key for simple statements that have no "returning columns".
* Prepared statements that have no returning columns use just {@code String sql} as a key.
* Simple and Prepared statements that have returning columns use {@link QueryWithReturningColumnsKey}
* as a cache key.
*/
class BaseQueryKey {
class BaseQueryKey implements CanEstimateSize {
public final String sql;
public final boolean isParameterized;
public final boolean escapeProcessing;
@@ -31,6 +33,14 @@ public String toString() {
+ '}';
}
@Override
public long getSize() {
if (sql == null) { // just in case
return 16;
}
return 16 + sql.length() * 2L; // 2 bytes per char, revise with Java 9's compact strings
}
@Override
public boolean equals(Object o) {
if (this == o) {
@@ -13,9 +13,7 @@
*/
public class CachedQuery implements CanEstimateSize {
/**
* Cache key. {@link String} or {@code org.postgresql.jdbc.CallableQueryKey}. It is assumed that
* {@code String.valueOf(key)*2} would give reasonable estimate of the number of retained bytes by
* given key (see {@link #getSize}).
* Cache key. {@link String} or {@code org.postgresql.util.CanEstimateSize}.
*/
public final Object key;
public final Query query;
@@ -25,6 +23,9 @@
private int executeCount;
public CachedQuery(Object key, Query query, boolean isFunction, boolean outParmBeforeFunc) {
assert key instanceof String || key instanceof CanEstimateSize
: "CachedQuery.key should either be String or implement CanEstimateSize."
+ " Actual class is " + key.getClass();
this.key = key;
this.query = query;
this.isFunction = isFunction;
@@ -55,7 +56,12 @@ public int getExecuteCount() {
@Override
public long getSize() {
int queryLength = String.valueOf(key).length() * 2 /* 2 bytes per char */;
long queryLength;
if (key instanceof String) {
queryLength = ((String) key).length() * 2L; // 2 bytes per char, revise with Java 9's compact strings
} else {
queryLength = ((CanEstimateSize) key).getSize();
}
return queryLength * 2 /* original query and native sql */
+ 100L /* entry in hash map, CachedQuery wrapper, etc */;
}
@@ -16,6 +16,7 @@
*/
class QueryWithReturningColumnsKey extends BaseQueryKey {
public final String[] columnNames;
private int size; // query length cannot exceed MAX_INT
QueryWithReturningColumnsKey(String sql, boolean isParameterized, boolean escapeProcessing,
String[] columnNames) {
@@ -27,6 +28,23 @@
this.columnNames = columnNames;
}
@Override
public long getSize() {
int size = this.size;
if (size != 0) {
return size;
}
size = (int) super.getSize();
if (columnNames != null) {
size += 16L; // array itself
for (String columnName: columnNames) {
size += columnName.length() * 2L; // 2 bytes per char, revise with Java 9's compact strings
}
}
this.size = size;
return size;
}
@Override
public String toString() {
return "QueryWithReturningColumnsKey{"

0 comments on commit 669fc31

Please sign in to comment.