finishJson优化

This commit is contained in:
redkale
2024-10-13 09:29:23 +08:00
parent 38ec269df2
commit 909b813573
9 changed files with 102 additions and 36 deletions

View File

@@ -49,7 +49,7 @@ public class JsonBytesWriter extends JsonWriter implements ByteTuple {
} }
public JsonBytesWriter(int size) { public JsonBytesWriter(int size) {
this.content = new byte[size > 1024 ? size : 1024]; this.content = new byte[size > DEFAULT_SIZE ? size : DEFAULT_SIZE];
} }
public JsonBytesWriter(ByteArray array) { public JsonBytesWriter(ByteArray array) {
@@ -425,10 +425,6 @@ public class JsonBytesWriter extends JsonWriter implements ByteTuple {
return copy; return copy;
} }
public int count() {
return this.count;
}
@Override @Override
public void writeString(String value) { public void writeString(String value) {
writeString(true, value); writeString(true, value);

View File

@@ -158,6 +158,9 @@ public abstract class JsonDynEncoder<T> extends ObjectEncoder<JsonWriter, T> {
if (onlyShotIntLongLatin1MoreFieldObjectFlag && membersSize < 2) { if (onlyShotIntLongLatin1MoreFieldObjectFlag && membersSize < 2) {
onlyShotIntLongLatin1MoreFieldObjectFlag = false; // 字段个数必须大于1 onlyShotIntLongLatin1MoreFieldObjectFlag = false; // 字段个数必须大于1
} }
onlyTwoIntFieldObjectFlag = false; // 废弃此特性
onlyOneLatin1FieldObjectFlag = false; // 废弃此特性
onlyShotIntLongLatin1MoreFieldObjectFlag = false; // 废弃此特性
{ // 构造函数 { // 构造函数
mv = (cw.visitMethod( mv = (cw.visitMethod(
ACC_PUBLIC, "<init>", "(" + jsonfactoryDesc + typeDesc + objEncoderDesc + ")V", null, null)); ACC_PUBLIC, "<init>", "(" + jsonfactoryDesc + typeDesc + objEncoderDesc + ")V", null, null));

View File

@@ -75,7 +75,7 @@ public class JsonReader extends Reader {
this.limit = -1; this.limit = -1;
this.text = null; this.text = null;
if (this.array != null) { if (this.array != null) {
if (this.array.content.length > CharArray.DEFAULT_SIZE * 200) { if (this.array.content.length > JsonWriter.DEFAULT_SIZE * 200) {
this.array = null; this.array = null;
} else { } else {
this.array.clear(); this.array.clear();
@@ -1096,11 +1096,9 @@ public class JsonReader extends Reader {
protected static class CharArray { protected static class CharArray {
private static final int DEFAULT_SIZE = 1024;
private int count; private int count;
private char[] content = new char[DEFAULT_SIZE]; private char[] content = new char[JsonWriter.DEFAULT_SIZE];
private char[] expand(int len) { private char[] expand(int len) {
int newcount = count + len; int newcount = count + len;

View File

@@ -96,24 +96,30 @@ public abstract class JsonWriter extends Writer {
public abstract void writeFieldLatin1Value(final byte[] fieldBytes, final char[] fieldChars, final String value); public abstract void writeFieldLatin1Value(final byte[] fieldBytes, final char[] fieldChars, final String value);
@ClassDepends @ClassDepends
@Deprecated(since = "2.8.0")
public abstract void writeLastFieldShortValue(final byte[] fieldBytes, final char[] fieldChars, final short value); public abstract void writeLastFieldShortValue(final byte[] fieldBytes, final char[] fieldChars, final short value);
@ClassDepends @ClassDepends
@Deprecated(since = "2.8.0")
public abstract void writeLastFieldIntValue(final byte[] fieldBytes, final char[] fieldChars, final int value); public abstract void writeLastFieldIntValue(final byte[] fieldBytes, final char[] fieldChars, final int value);
@ClassDepends @ClassDepends
@Deprecated(since = "2.8.0")
public abstract void writeLastFieldLongValue(final byte[] fieldBytes, final char[] fieldChars, final long value); public abstract void writeLastFieldLongValue(final byte[] fieldBytes, final char[] fieldChars, final long value);
@ClassDepends @ClassDepends
@Deprecated(since = "2.8.0")
public abstract void writeLastFieldLatin1Value(final byte[] fieldBytes, final char[] fieldChars, String value); public abstract void writeLastFieldLatin1Value(final byte[] fieldBytes, final char[] fieldChars, String value);
// firstFieldBytes 必须带{开头 // firstFieldBytes 必须带{开头
@ClassDepends @ClassDepends
@Deprecated(since = "2.8.0")
public abstract void writeObjectByOnlyOneLatin1FieldValue( public abstract void writeObjectByOnlyOneLatin1FieldValue(
final byte[] firstFieldBytes, final char[] firstFieldChars, final String value); final byte[] firstFieldBytes, final char[] firstFieldChars, final String value);
// firstFieldBytes 必须带{开头, lastFieldBytes必须,开头 // firstFieldBytes 必须带{开头, lastFieldBytes必须,开头
@ClassDepends @ClassDepends
@Deprecated(since = "2.8.0")
public abstract void writeObjectByOnlyTwoIntFieldValue( public abstract void writeObjectByOnlyTwoIntFieldValue(
final byte[] firstFieldBytes, final byte[] firstFieldBytes,
final char[] firstFieldChars, final char[] firstFieldChars,

View File

@@ -13,10 +13,11 @@ import org.redkale.util.ByteArray;
import org.redkale.util.ByteTuple; import org.redkale.util.ByteTuple;
/** /**
*
* *
* @author zhangjx * @author zhangjx
*/ */
public class ProtobufBytesWriter extends ProtobufWriter { public class ProtobufBytesWriter extends ProtobufWriter { // 存在child情况因此不能实现ByteTuple
private static final int RESET_MAX_SIZE = DEFAULT_SIZE << 4; private static final int RESET_MAX_SIZE = DEFAULT_SIZE << 4;

View File

@@ -6,6 +6,7 @@
package org.redkale.net; package org.redkale.net;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.charset.*; import java.nio.charset.*;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.logging.*; import java.util.logging.*;
@@ -184,6 +185,10 @@ public class Context {
this.serverAddress = addr; this.serverAddress = addr;
} }
public ByteBuffer createByteBuffer() {
return ByteBuffer.allocateDirect(getBufferCapacity());
}
public ResourceFactory getResourceFactory() { public ResourceFactory getResourceFactory() {
return resourceFactory; return resourceFactory;
} }

View File

@@ -103,7 +103,11 @@ public abstract class Response<C extends Context, R extends Request<C>> {
public void completed(final Integer result, final ByteBuffer[] attachments) { public void completed(final Integer result, final ByteBuffer[] attachments) {
if (attachments != null) { if (attachments != null) {
for (ByteBuffer attachment : attachments) { for (ByteBuffer attachment : attachments) {
if (attachment != writeBuffer) {
channel.offerWriteBuffer(attachment); channel.offerWriteBuffer(attachment);
} else {
attachment.clear();
}
} }
} }
completeInIOThread(false); completeInIOThread(false);
@@ -113,7 +117,11 @@ public abstract class Response<C extends Context, R extends Request<C>> {
public void failed(Throwable exc, final ByteBuffer[] attachments) { public void failed(Throwable exc, final ByteBuffer[] attachments) {
if (attachments != null) { if (attachments != null) {
for (ByteBuffer attachment : attachments) { for (ByteBuffer attachment : attachments) {
if (attachment != writeBuffer) {
channel.offerWriteBuffer(attachment); channel.offerWriteBuffer(attachment);
} else {
attachment.clear();
}
} }
} }
completeInIOThread(true); completeInIOThread(true);
@@ -124,9 +132,12 @@ public abstract class Response<C extends Context, R extends Request<C>> {
this.context = context; this.context = context;
this.request = request; this.request = request;
this.thread = WorkThread.currentWorkThread(); this.thread = WorkThread.currentWorkThread();
this.writeBuffer = context != null ? ByteBuffer.allocateDirect(context.getBufferCapacity()) : null; this.writeBuffer = context.createByteBuffer();
this.workExecutor = this.workExecutor = context.workExecutor == null ? ForkJoinPool.commonPool() : context.workExecutor;
context == null || context.workExecutor == null ? ForkJoinPool.commonPool() : context.workExecutor; }
protected ByteBuffer writeBuffer() {
return writeBuffer;
} }
protected AsyncConnection removeChannel() { protected AsyncConnection removeChannel() {
@@ -157,6 +168,7 @@ public abstract class Response<C extends Context, R extends Request<C>> {
} }
channel = null; channel = null;
} }
this.writeBuffer.clear();
this.responseSupplier = null; this.responseSupplier = null;
this.responseConsumer = null; this.responseConsumer = null;
this.recycleListener = null; this.recycleListener = null;
@@ -364,6 +376,10 @@ public abstract class Response<C extends Context, R extends Request<C>> {
} }
} }
protected void writeInIOThread(ByteBuffer buffer) {
this.channel.writeInIOThread(buffer, buffer, finishBufferIOThreadHandler);
}
public final void finish(final byte[] bs) { public final void finish(final byte[] bs) {
finish(false, bs, 0, bs.length); finish(false, bs, 0, bs.length);
} }

View File

@@ -291,6 +291,10 @@ public class HttpRequest extends Request<HttpContext> {
return req; return req;
} }
protected int pipelineIndex() {
return pipelineIndex;
}
protected boolean isWebSocket() { protected boolean isWebSocket() {
return maybews && getmethod && "Upgrade".equalsIgnoreCase(getHeader("Connection")); return maybews && getmethod && "Upgrade".equalsIgnoreCase(getHeader("Connection"));
} }

View File

@@ -201,6 +201,10 @@ public class HttpResponse extends Response<HttpContext, HttpRequest> {
private final JsonBytesWriter jsonWriter = new JsonBytesWriter(); private final JsonBytesWriter jsonWriter = new JsonBytesWriter();
private final Consumer<byte[]> headerArrayConsumer;
private final Consumer<byte[]> headerBufferConsumer;
@SuppressWarnings("Convert2Lambda") @SuppressWarnings("Convert2Lambda")
protected final ConvertBytesHandler convertHandler = new ConvertBytesHandler() { protected final ConvertBytesHandler convertHandler = new ConvertBytesHandler() {
@Override @Override
@@ -231,6 +235,8 @@ public class HttpResponse extends Response<HttpContext, HttpRequest> {
this.jsonLiveContentLengthArray = config == null ? null : config.jsonLiveContentLengthArray; this.jsonLiveContentLengthArray = config == null ? null : config.jsonLiveContentLengthArray;
this.jsonCloseContentLengthArray = config == null ? null : config.jsonCloseContentLengthArray; this.jsonCloseContentLengthArray = config == null ? null : config.jsonCloseContentLengthArray;
this.contentType = this.plainContentType; this.contentType = this.plainContentType;
this.headerArrayConsumer = headerArray::put;
this.headerBufferConsumer = writeBuffer()::put;
} }
@Override @Override
@@ -425,8 +431,34 @@ public class HttpResponse extends Response<HttpContext, HttpRequest> {
* @param obj 输出对象 * @param obj 输出对象
*/ */
public final void finishJson(final Type type, final Object obj) { public final void finishJson(final Type type, final Object obj) {
if (sendHandler == null
&& cacheHandler == null
&& headerBufferConsumer != null
&& request.pipelineIndex() <= 0
&& !this.channel.hasPipelineData()
&& request.getRespConvert() == jsonRootConvert
&& this.header.getStringEntrys().length == 0) {
this.contentType = this.jsonContentType;
if (this.recycleListener != null) {
this.output = obj;
}
JsonBytesWriter writer = jsonWriter;
jsonRootConvert.convertTo(writer.clear(), type, obj);
this.contentLength = writer.length();
createHeader(headerBufferConsumer); // 写进writeBuffer
ByteBuffer buffer = writeBuffer();
if (buffer.capacity() >= contentLength) {
buffer.put(writer.content(), 0, writer.length());
buffer.flip();
writeInIOThread(buffer);
} else {
finish(this.jsonContentType, writer);
}
} else {
finishJson((Convert) null, type, obj); finishJson((Convert) null, type, obj);
} }
}
/** /**
* 将对象以JSON格式输出 * 将对象以JSON格式输出
@@ -1069,6 +1101,12 @@ public class HttpResponse extends Response<HttpContext, HttpRequest> {
// Header大小 // Header大小
protected void createHeader() { protected void createHeader() {
createHeader(headerArrayConsumer);
this.headWritedSize = headerArray.length();
}
// Header大小
protected void createHeader(Consumer<byte[]> writer) {
if (this.status == 200 if (this.status == 200
&& !this.respHeadContainsConnection && !this.respHeadContainsConnection
&& !this.request.isWebSocket() && !this.request.isWebSocket()
@@ -1088,47 +1126,47 @@ public class HttpResponse extends Response<HttpContext, HttpRequest> {
lengthArray = this.plainCloseContentLengthArray; lengthArray = this.plainCloseContentLengthArray;
} }
} }
headerArray.put(lengthArray[(int) this.contentLength]); writer.accept(lengthArray[(int) this.contentLength]);
} else { } else {
if (this.status == 200 && !this.respHeadContainsConnection && !this.request.isWebSocket()) { if (this.status == 200 && !this.respHeadContainsConnection && !this.request.isWebSocket()) {
if (this.request.isKeepAlive()) { if (this.request.isKeepAlive()) {
headerArray.put(status200_server_live_Bytes); writer.accept(status200_server_live_Bytes);
} else { } else {
headerArray.put(status200_server_close_Bytes); writer.accept(status200_server_close_Bytes);
} }
} else { } else {
if (this.status == 200) { if (this.status == 200) {
headerArray.put(status200Bytes); writer.accept(status200Bytes);
} else { } else {
headerArray.put(("HTTP/1.1 " + this.status + " " + httpCodes.get(this.status) + "\r\n").getBytes()); writer.accept(("HTTP/1.1 " + this.status + " " + httpCodes.get(this.status) + "\r\n").getBytes());
} }
headerArray.put(serverNameBytes); writer.accept(serverNameBytes);
if (!this.respHeadContainsConnection) { if (!this.respHeadContainsConnection) {
byte[] bs = this.request.isKeepAlive() ? connectAliveBytes : connectCloseBytes; byte[] bs = this.request.isKeepAlive() ? connectAliveBytes : connectCloseBytes;
if (bs.length > 0) { if (bs.length > 0) {
headerArray.put(bs); writer.accept(bs);
} }
} }
} }
if (!this.request.isWebSocket()) { if (!this.request.isWebSocket()) {
if (this.contentType == this.jsonContentType) { if (this.contentType == this.jsonContentType) {
headerArray.put(this.jsonContentTypeBytes); writer.accept(this.jsonContentTypeBytes);
} else if (this.contentType == null || this.contentType == this.plainContentType) { } else if (this.contentType == null || this.contentType == this.plainContentType) {
headerArray.put(this.plainContentTypeBytes); writer.accept(this.plainContentTypeBytes);
} else { } else {
headerArray.put(("Content-Type: " + this.contentType + "\r\n").getBytes()); writer.accept(("Content-Type: " + this.contentType + "\r\n").getBytes());
} }
} }
if (this.contentLength >= 0) { if (this.contentLength >= 0) {
if (this.contentLength < contentLengthArray.length) { if (this.contentLength < contentLengthArray.length) {
headerArray.put(contentLengthArray[(int) this.contentLength]); writer.accept(contentLengthArray[(int) this.contentLength]);
} else { } else {
headerArray.put(("Content-Length: " + this.contentLength + "\r\n").getBytes()); writer.accept(("Content-Length: " + this.contentLength + "\r\n").getBytes());
} }
} }
} }
if (dateSupplier != null) { if (dateSupplier != null) {
headerArray.put(dateSupplier.get()); writer.accept(dateSupplier.get());
} }
if (this.defaultAddHeaders != null) { if (this.defaultAddHeaders != null) {
@@ -1166,7 +1204,7 @@ public class HttpResponse extends Response<HttpContext, HttpRequest> {
} }
} }
for (Entry<String> en : this.header.getStringEntrys()) { for (Entry<String> en : this.header.getStringEntrys()) {
headerArray.put((en.name + ": " + en.getValue() + "\r\n").getBytes()); writer.accept((en.name + ": " + en.getValue() + "\r\n").getBytes());
} }
if (request.newSessionid != null) { if (request.newSessionid != null) {
String domain = defaultCookie == null ? null : defaultCookie.getDomain(); String domain = defaultCookie == null ? null : defaultCookie.getDomain();
@@ -1180,12 +1218,12 @@ public class HttpResponse extends Response<HttpContext, HttpRequest> {
// path = "/"; // path = "/";
// } // }
if (request.newSessionid.isEmpty()) { if (request.newSessionid.isEmpty()) {
headerArray.put(("Set-Cookie: " + HttpRequest.SESSIONID_NAME + "=; " + domain writer.accept(("Set-Cookie: " + HttpRequest.SESSIONID_NAME + "=; " + domain
+ "Path=/; Max-Age=0; HttpOnly\r\n") + "Path=/; Max-Age=0; HttpOnly\r\n")
.getBytes()); .getBytes());
} else { } else {
headerArray.put(("Set-Cookie: " + HttpRequest.SESSIONID_NAME + "=" + request.newSessionid + "; " writer.accept(("Set-Cookie: " + HttpRequest.SESSIONID_NAME + "=" + request.newSessionid + "; " + domain
+ domain + "Path=/; HttpOnly\r\n") + "Path=/; HttpOnly\r\n")
.getBytes()); .getBytes());
} }
} }
@@ -1202,11 +1240,10 @@ public class HttpResponse extends Response<HttpContext, HttpRequest> {
cookie.setPath(defaultCookie.getPath()); cookie.setPath(defaultCookie.getPath());
} }
} }
headerArray.put(("Set-Cookie: " + cookieString(cookie) + "\r\n").getBytes()); writer.accept(("Set-Cookie: " + cookieString(cookie) + "\r\n").getBytes());
} }
} }
headerArray.put(LINE); writer.accept(LINE);
this.headWritedSize = headerArray.length();
} }
private CharSequence cookieString(HttpCookie cookie) { private CharSequence cookieString(HttpCookie cookie) {