Skip to content

Commit d6f8cc2

Browse files
authored
Merge pull request #1001 from dr-itz/50-dev
[perf] set a fetch size to reduce peak memory usage
2 parents 4a3a605 + eb6780f commit d6f8cc2

File tree

5 files changed

+26
-7
lines changed

5 files changed

+26
-7
lines changed

src/java/arjdbc/jdbc/RubyJdbcConnection.java

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ public class RubyJdbcConnection extends RubyObject {
128128
private boolean lazy = false; // final once set on initialize
129129
private boolean jndi; // final once set on initialize
130130
private boolean configureConnection = true; // final once initialized
131+
private int fetchSize = 0; // 0 = JDBC default
131132

132133
protected RubyJdbcConnection(Ruby runtime, RubyClass metaClass) {
133134
super(runtime, metaClass);
@@ -571,6 +572,11 @@ protected void doInitialize(final ThreadContext context, final IRubyObject confi
571572
else {
572573
this.configureConnection = value != context.runtime.getFalse();
573574
}
575+
576+
IRubyObject jdbcFetchSize = getConfigValue(context, "jdbc_fetch_size");
577+
if (jdbcFetchSize != context.nil) {
578+
this.fetchSize = RubyNumeric.fix2int(jdbcFetchSize);
579+
}
574580
}
575581

576582
@JRubyMethod(name = "adapter")
@@ -818,6 +824,7 @@ public IRubyObject call(final Connection connection) throws SQLException {
818824
// is called, so we have to process the result sets as we get them
819825
// this shouldn't be an issue in most cases since we're only getting 1 result set anyways
820826
result = mapExecuteResult(context, connection, resultSet);
827+
resultSet.close();
821828
} else {
822829
result = context.runtime.newFixnum(updateCount);
823830
}
@@ -851,6 +858,7 @@ protected Statement createStatement(final ThreadContext context, final Connectio
851858
else {
852859
statement.setEscapeProcessing(escapeProcessing.isTrue());
853860
}
861+
if (fetchSize != 0) statement.setFetchSize(fetchSize);
854862
return statement;
855863
}
856864

@@ -1045,6 +1053,7 @@ public IRubyObject call(final Connection connection) throws SQLException {
10451053
else {
10461054
final PreparedStatement prepStatement;
10471055
statement = prepStatement = connection.prepareStatement(query);
1056+
if (fetchSize != 0) statement.setFetchSize(fetchSize);
10481057
statement.setMaxRows(maxRows); // zero means there is no limit
10491058
setStatementParameters(context, connection, prepStatement, binds);
10501059
hasResult = prepStatement.execute();
@@ -1123,7 +1132,9 @@ public IRubyObject prepare_statement(final ThreadContext context, final IRubyObj
11231132
return withConnection(context, new Callable<IRubyObject>() {
11241133
public IRubyObject call(Connection connection) throws SQLException {
11251134
final String query = sql.convertToString().getUnicodeValue();
1126-
return JavaUtil.convertJavaToRuby(context.runtime, connection.prepareStatement(query));
1135+
PreparedStatement statement = connection.prepareStatement(query);
1136+
if (fetchSize != 0) statement.setFetchSize(fetchSize);
1137+
return JavaUtil.convertJavaToRuby(context.runtime, statement);
11271138
}
11281139
});
11291140
}
@@ -1158,19 +1169,15 @@ public IRubyObject call(final Connection connection) throws SQLException {
11581169
statement = (PreparedStatement) JavaEmbedUtils.rubyToJava(cachedStatement);
11591170
} else {
11601171
statement = connection.prepareStatement(query);
1172+
if (fetchSize != 0) statement.setFetchSize(fetchSize);
11611173
}
11621174

11631175
setStatementParameters(context, connection, statement, (RubyArray) binds);
11641176

11651177
if (statement.execute()) {
11661178
ResultSet resultSet = statement.getResultSet();
11671179
IRubyObject results = mapQueryResult(context, connection, resultSet);
1168-
1169-
if (cached) {
1170-
// Make sure we free the result set if we are caching the statement
1171-
// It gets closed automatically when the statement is closed if we aren't caching
1172-
resultSet.close();
1173-
}
1180+
resultSet.close();
11741181

11751182
return results;
11761183
} else {
@@ -2501,6 +2508,8 @@ protected IRubyObject arrayToRuby(final ThreadContext context,
25012508
while ( arrayResult.next() ) {
25022509
array.append( jdbcToRuby(context, runtime, 2, baseType, arrayResult) );
25032510
}
2511+
arrayResult.close();
2512+
25042513
return array;
25052514
}
25062515
finally { if ( value != null ) value.free(); }

test/rails/config.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ connections:
6262
driver: <%= 'org.mariadb.jdbc.Driver' %>
6363
<% end %>
6464
<% if defined? JRUBY_VERSION %>
65+
jdbc_fetch_size: 100
6566
properties:
6667
serverTimezone: <%= java.util.TimeZone.getDefault.getID %>
6768
<% end %>
@@ -80,6 +81,7 @@ connections:
8081
prepared_statements: <%= ENV['PREPARED_STATEMENTS'] || ENV['PS'] %> # should leave it off to its default if not set
8182
<% end %>
8283
username: <%= ENV['PGUSER'] || ENV['user'] || 'rails' %>
84+
jdbc_fetch_size: 100
8385
properties:
8486
# Postgres' JDBC driver does not prepare statements until executed 5 times by default, let's lower:
8587
prepareThreshold: <%= ENV['PREPARE_THRESHOLD'] || 1 %>
@@ -96,9 +98,11 @@ connections:
9698
arunit:
9799
database: <%= FIXTURES_ROOT %>/fixture_database.sqlite3
98100
timeout: 5000
101+
jdbc_fetch_size: 100
99102
arunit2:
100103
database: <%= FIXTURES_ROOT %>/fixture_database_2.sqlite3
101104
timeout: 5000
105+
jdbc_fetch_size: 100
102106

103107
sqlite3_mem:
104108
arunit:
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
exclude :test_some_time, 'intermittent failures, leaks thread, fires at high frequency'
2+
exclude :test_connection_pool_starts_reaper, 'intermittent failures, leaks thread, fires at high frequency'
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
exclude :test_some_time, 'intermittent failures, leaks thread, fires at high frequency'
2+
exclude :test_connection_pool_starts_reaper, 'intermittent failures, leaks thread, fires at high frequency'
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
exclude :test_some_time, 'intermittent failures, leaks thread, fires at high frequency'
2+
exclude :test_connection_pool_starts_reaper, 'intermittent failures, leaks thread, fires at high frequency'

0 commit comments

Comments
 (0)