Skip to content

Commit 2382736

Browse files
authored
[java] less memory allocation (#12320)
1 parent 4468622 commit 2382736

3 files changed

Lines changed: 30 additions & 16 deletions

File tree

java/src/org/openqa/selenium/netty/server/ResponseConverter.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
public class ResponseConverter extends ChannelOutboundHandlerAdapter {
4141

4242
private static final int CHUNK_SIZE = 1024 * 1024;
43+
private static final ThreadLocal<byte[]> CHUNK_CACHE = ThreadLocal.withInitial(() -> new byte[CHUNK_SIZE]);
4344
private final boolean allowCors;
4445

4546
public ResponseConverter(boolean allowCors) {
@@ -57,7 +58,7 @@ public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise)
5758
HttpResponse seResponse = (HttpResponse) msg;
5859

5960
// We may not know how large the response is, but figure it out if we can.
60-
byte[] ary = new byte[CHUNK_SIZE];
61+
byte[] ary = CHUNK_CACHE.get();
6162
InputStream is = seResponse.getContent().get();
6263
int byteCount = ByteStreams.read(is, ary, 0, ary.length);
6364
// If there are no bytes left to read, then -1 is returned by read, and this is bad.
@@ -70,7 +71,7 @@ public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise)
7071
new DefaultFullHttpResponse(
7172
HTTP_1_1,
7273
HttpResponseStatus.valueOf(seResponse.getStatus()),
73-
Unpooled.wrappedBuffer(ary, 0, byteCount));
74+
Unpooled.copiedBuffer(ary, 0, byteCount));
7475
first.headers().addInt(CONTENT_LENGTH, byteCount);
7576
copyHeaders(seResponse, first);
7677
ctx.write(first);
@@ -81,7 +82,7 @@ public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise)
8182
ctx.write(first);
8283

8384
// We need to write the first response.
84-
ctx.write(new DefaultHttpContent(Unpooled.wrappedBuffer(ary)));
85+
ctx.write(new DefaultHttpContent(Unpooled.copiedBuffer(ary)));
8586

8687
HttpChunkedInput writer = new HttpChunkedInput(new ChunkedStream(is, CHUNK_SIZE));
8788
ChannelFuture future = ctx.write(writer);

java/src/org/openqa/selenium/remote/codec/w3c/W3CHttpCommandCodec.java

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -75,13 +75,15 @@
7575
import com.google.common.collect.ImmutableMap;
7676
import com.google.common.io.Resources;
7777
import java.io.IOException;
78+
import java.io.UncheckedIOException;
7879
import java.net.URL;
7980
import java.nio.charset.StandardCharsets;
8081
import java.util.ArrayList;
8182
import java.util.Collection;
8283
import java.util.HashMap;
8384
import java.util.List;
8485
import java.util.Map;
86+
import java.util.concurrent.ConcurrentHashMap;
8587
import java.util.stream.Collectors;
8688
import java.util.stream.Stream;
8789
import org.openqa.selenium.InvalidSelectorException;
@@ -96,6 +98,8 @@
9698
*/
9799
public class W3CHttpCommandCodec extends AbstractHttpCommandCodec {
98100

101+
private static final ConcurrentHashMap<String, String> ATOM_SCRIPTS = new ConcurrentHashMap<>();
102+
99103
public W3CHttpCommandCodec() {
100104
String sessionId = "/session/:sessionId";
101105

@@ -338,15 +342,22 @@ private List<String> stringToUtf8Array(String toConvert) {
338342

339343
private Map<String, ?> executeAtom(String atomFileName, Object... args) {
340344
try {
341-
String scriptName = "/org/openqa/selenium/remote/" + atomFileName;
342-
URL url = getClass().getResource(scriptName);
343-
344-
String rawFunction = Resources.toString(url, StandardCharsets.UTF_8);
345-
String atomName = atomFileName.replace(".js", "");
346-
String script =
347-
String.format("/* %s */return (%s).apply(null, arguments);", atomName, rawFunction);
345+
String script = ATOM_SCRIPTS.computeIfAbsent(atomFileName, (fileName) -> {
346+
String scriptName = "/org/openqa/selenium/remote/" + atomFileName;
347+
URL url = getClass().getResource(scriptName);
348+
String rawFunction;
349+
try {
350+
rawFunction = Resources.toString(url, StandardCharsets.UTF_8);
351+
} catch (IOException e) {
352+
throw new UncheckedIOException(e);
353+
}
354+
String atomName = fileName.replace(".js", "");
355+
return String.format("/* %s */return (%s).apply(null, arguments);", atomName, rawFunction);
356+
});
348357
return toScript(script, args);
349-
} catch (IOException | NullPointerException e) {
358+
} catch (UncheckedIOException e) {
359+
throw new WebDriverException(e.getCause());
360+
} catch (NullPointerException e) {
350361
throw new WebDriverException(e);
351362
}
352363
}

java/src/org/openqa/selenium/remote/tracing/HttpTracing.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
package org.openqa.selenium.remote.tracing;
1919

20+
import java.util.logging.Level;
2021
import java.util.logging.Logger;
2122
import org.openqa.selenium.internal.Require;
2223
import org.openqa.selenium.remote.http.HttpRequest;
@@ -56,11 +57,12 @@ public static void inject(Tracer tracer, TraceContext context, HttpRequest reque
5657
Require.nonNull("Tracer", tracer);
5758
Require.nonNull("Request", request);
5859

59-
StackTraceElement caller = Thread.currentThread().getStackTrace()[2];
60-
LOG.fine(
61-
String.format(
62-
"Injecting %s into %s at %s:%d",
63-
request, context, caller.getClassName(), caller.getLineNumber()));
60+
if (LOG.isLoggable(Level.FINE)) {
61+
StackTraceElement caller = Thread.currentThread().getStackTrace()[2];
62+
LOG.log(
63+
Level.FINE, "Injecting {0} into {1} at {2}:{3}",
64+
new Object[] {request, context, caller.getClassName(), caller.getLineNumber()});
65+
}
6466

6567
tracer.getPropagator().inject(context, request, (req, key, value) -> req.setHeader(key, value));
6668
}

0 commit comments

Comments
 (0)