-
Notifications
You must be signed in to change notification settings - Fork 819
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
perf: replace BufferedOutputStream with unsynchronized PgBufferedOutputStream, allow configuring different Java and SO_SNDBUF buffer sizes #3248
base: master
Are you sure you want to change the base?
Conversation
6f86dfb
to
557ce20
Compare
Just wondering: do you have |
@plokhotnyuk , could you please try commenting this line
Would it alleviate |
I'm using |
8e7b129
to
91388c3
Compare
7c02456
to
5a76511
Compare
I noticed there's It looks like we could add |
Do we have any chance to re-use byte array buffers of But before that need to find an ability to avoid boxing when checking type of serialisation for oids using generic hash maps. |
This PR already fixes it for
That is on my list. Try using @@ -62,6 +62,7 @@ import java.sql.SQLException;
import java.sql.SQLWarning;
import java.util.ArrayDeque;
import java.util.ArrayList;
+import java.util.BitSet;
import java.util.Collections;
import java.util.Deque;
import java.util.HashMap;
@@ -128,6 +129,7 @@ public class QueryExecutorImpl extends QueryExecutorBase {
* Bit set that has a bit set for each oid which should be sent using binary format.
*/
private final Set<Integer> useBinarySendForOids = new HashSet<>();
+ private final BitSet useBinarySendForOidsBs = new BitSet();
/**
* This is a fake query object so processResults can distinguish "ReadyForQuery" messages
@@ -3005,6 +3007,7 @@ public class QueryExecutorImpl extends QueryExecutorBase {
public void addBinarySendOid(int oid) {
synchronized (useBinarySendForOids) {
useBinarySendForOids.add(oid);
+ useBinarySendForOidsBs.set(oid);
}
}
@@ -3012,6 +3015,7 @@ public class QueryExecutorImpl extends QueryExecutorBase {
public void removeBinarySendOid(int oid) {
synchronized (useBinarySendForOids) {
useBinarySendForOids.remove(oid);
+ useBinarySendForOidsBs.set(oid, false);
}
}
@@ -3027,7 +3031,8 @@ public class QueryExecutorImpl extends QueryExecutorBase {
@Override
public boolean useBinaryForSend(int oid) {
synchronized (useBinarySendForOids) {
- return useBinarySendForOids.contains(oid);
+ return useBinarySendForOidsBs.get(oid);
}
}
@@ -3036,6 +3041,9 @@ public class QueryExecutorImpl extends QueryExecutorBase {
synchronized (useBinarySendForOids) {
useBinarySendForOids.clear();
useBinarySendForOids.addAll(oids);
+ for (Integer oid : oids) {
+ useBinarySendForOidsBs.set(oid);
+ }
}
} |
3c6412a
to
61a6b1c
Compare
The changes look good to me. It is still unclear if |
…utStream, increase the send buffer size This fixes the following issues: 1) Java 21 uses ReentrantLock for BufferedOutputStream, however, we do not need synchronization as we synchronize at the level of QueryExecutor.execute 2) The default buffer size of 8192 was small for the modern connections 3) The previous implementation of GSSOutputStream could produce oversize packets that would be rejected by the backend. Fixes pgjdbc#3245 See https://github.com/postgres/postgres/blob/acecd6746cdc2df5ba8dcc2c2307c6560c7c2492/src/backend/libpq/be-secure-gssapi.c#L348
… buffer when sending data from InputStream
@plokhotnyuk , do you think you could benchmark 32KiB, 64KiB, 128KiB heap buffer sizes? I am leaning towards adding |
I think that having those options configurable even with setting them to |
// Cancel signal is 16 bytes only, so we use 16 as the max send buffer size | ||
cancelStream = | ||
new PGStream(pgStream.getSocketFactory(), pgStream.getHostSpec(), cancelSignalTimeout); | ||
new PGStream(pgStream.getSocketFactory(), pgStream.getHostSpec(), cancelSignalTimeout, 16); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess this is the only place where we can justify the buffer size :)
@bokken Could you please review this PR to be merged and released in the next version? |
This fixes two issues:
Java 21 uses ReentrantLock for BufferedOutputStream, however, we do not need synchronization as we synchronize at the level of QueryExecutor.execute
The default buffer size of 8192 was small for the modern connections
Fixes #3245
TODO:
PgBufferedOutputStream
maxSendBufferSize
PGStream.sendInteger4
andPGStream.sendInteger2
toPgBufferedOutputStream
so we do not need intermediateint[4]
arrays for sending integersPGStream.sendStream
toPgBufferedOutputStream
so we can reusePgBufferedOutputStream's
buffer when reading data from theInputStream
GSSOutputStream
so it limits the produced messages (backend limits message size with 16KiB)GSSOutputStream
so it avoids intermediate copies of the data when writing large array to GSS streamCancelled:
send buffer size
/cc @plokhotnyuk