Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit f764fb6

Browse files
committed
[improvement] improve encode decode performance
1 parent 8865e28 commit f764fb6

File tree

4 files changed

+148
-105
lines changed

4 files changed

+148
-105
lines changed

core/src/main/java/com/qq/tars/client/rpc/TarsDecoder.java

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -100,9 +100,7 @@ public Request decodeRequest(ByteBuf buffer) throws ProtocolException {
100100
if (buffer.readableBytes() < length) {
101101
return null;
102102
}
103-
byte[] byteArray = new byte[buffer.readableBytes()];
104-
buffer.readBytes(byteArray);
105-
TarsInputStream jis = new TarsInputStream(byteArray);
103+
TarsInputStream jis = new TarsInputStream(buffer);
106104
TarsServantRequest request = new TarsServantRequest();
107105
try {
108106
short version = jis.read(TarsHelper.STAMP_SHORT.shortValue(), 1, true);
@@ -233,10 +231,8 @@ public Response decodeResponse(ByteBuf channelBuffer) throws ProtocolException {
233231
if (channelBuffer.readableBytes() < length) {
234232
return null;
235233
}
236-
237234
byte[] bytes = new byte[length];
238235
channelBuffer.readBytes(bytes);
239-
240236
TarsServantResponse response = new TarsServantResponse();
241237
response.setCharsetName(charsetName);
242238
TarsInputStream is = new TarsInputStream(bytes);

core/src/main/java/com/qq/tars/client/rpc/TarsEncoder.java

Lines changed: 134 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,11 @@
2929
import com.qq.tars.rpc.protocol.tars.support.AnalystManager;
3030
import com.qq.tars.rpc.protocol.tup.UniAttribute;
3131
import io.netty.buffer.ByteBuf;
32-
import io.netty.buffer.Unpooled;
32+
import io.netty.buffer.ByteBufAllocator;
33+
import io.netty.buffer.CompositeByteBuf;
3334
import io.netty.channel.ChannelHandlerContext;
3435
import io.netty.handler.codec.MessageToByteEncoder;
36+
import io.netty.util.ReferenceCountUtil;
3537
import org.slf4j.Logger;
3638
import org.slf4j.LoggerFactory;
3739

@@ -49,60 +51,85 @@ public TarsEncoder(Charset charset) {
4951

5052
@Override
5153
protected void encode(ChannelHandlerContext channelHandlerContext, Object o, ByteBuf out) throws Exception {
52-
if (o instanceof Request) {
53-
try {
54-
final ByteBuf ioBuffer = encodeRequest((TarsServantRequest) o);
54+
ByteBuf ioBuffer = null;
55+
try {
56+
if (o instanceof Request) {
57+
try {
58+
ioBuffer = encodeRequest(channelHandlerContext.alloc(), (TarsServantRequest) o);
59+
if (logger.isDebugEnabled())
60+
logger.debug("[tars] write data size is " + ioBuffer.duplicate().getInt(0));
61+
62+
int length = ioBuffer.getInt(0);
63+
if (length > ioBuffer.readableBytes()) {
64+
throw new IndexOutOfBoundsException();
65+
}
66+
out.ensureWritable(ioBuffer.readableBytes());
67+
out.writeBytes(ioBuffer);
68+
} catch (Exception e) {
69+
logger.warn(e.getMessage(), e);
70+
}
71+
} else if (o instanceof Response) {
72+
ioBuffer = encodeResponse(channelHandlerContext.alloc(), (Response) o);
5573
if (logger.isDebugEnabled())
5674
logger.debug("[tars] write data size is " + ioBuffer.duplicate().getInt(0));
5775
int length = ioBuffer.getInt(0);
5876
if (length > ioBuffer.readableBytes()) {
5977
throw new IndexOutOfBoundsException();
6078
}
6179
out.writeBytes(ioBuffer);
62-
} catch (Exception e) {
63-
e.printStackTrace();
80+
} else {
81+
throw new ProtocolException("[tars] cannot support type");
6482
}
65-
} else if (o instanceof Response) {
66-
final ByteBuf ioBuffer = encodeResponse((Response) o);
67-
if (logger.isDebugEnabled())
68-
logger.debug("[tars] write data size is " + ioBuffer.duplicate().getInt(0));
69-
int length = ioBuffer.getInt(0);
70-
if (length > ioBuffer.readableBytes()) {
71-
throw new IndexOutOfBoundsException();
83+
} finally {
84+
if (ioBuffer != null) {
85+
ReferenceCountUtil.release(ioBuffer);
7286
}
73-
out.writeBytes(ioBuffer);
74-
} else {
75-
throw new ProtocolException("[tars] cannot support type");
7687
}
7788
}
7889

7990

80-
public ByteBuf encodeRequest(Request req) throws ProtocolException {
91+
public ByteBuf encodeRequest(ByteBufAllocator allocator, Request req) throws ProtocolException {
8192
final TarsServantRequest request = (TarsServantRequest) req;
82-
request.setCharsetName(this.charset.name());
83-
TarsOutputStream os = new TarsOutputStream();
84-
os.setServerEncoding(this.charset);
85-
os.getByteBuffer().writeInt(0);
86-
os.write(request.getVersion(), 1);
87-
os.write(request.getPacketType(), 2);
88-
os.write(request.getMessageType(), 3);
89-
os.write(request.getRequestId(), 4);
90-
os.write(request.getServantName(), 5);
91-
os.write(request.getFunctionName(), 6);
92-
os.write(encodeRequestParams(request), 7);//
93-
os.write(request.getTimeout(), 8);
94-
os.write(request.getContext(), 9);
95-
os.write(request.getStatus(), 10);
96-
int length = os.getByteBuffer().readableBytes();
97-
os.getByteBuffer().setInt(0, length);
98-
if (length > TarsHelper.PACKAGE_MAX_LENGTH || length <= 0) {
99-
throw new ProtocolException("the length header of the package must be between 0~10M bytes. data length:" + Integer.toHexString(length));
93+
CompositeByteBuf compositeByteBuf = allocator.compositeBuffer();
94+
ByteBuf headBuffer = allocator.buffer();
95+
ByteBuf bodyBuffer = allocator.buffer();
96+
ByteBuf endBuffer = allocator.buffer();
97+
int length = 0;
98+
try {
99+
request.setCharsetName(this.charset.name());
100+
TarsOutputStream os = new TarsOutputStream(headBuffer);
101+
os.setServerEncoding(this.charset);
102+
os.getByteBuffer().writeInt(0);
103+
os.write(request.getVersion(), 1);
104+
os.write(request.getPacketType(), 2);
105+
os.write(request.getMessageType(), 3);
106+
os.write(request.getRequestId(), 4);
107+
os.write(request.getServantName(), 5);
108+
os.write(request.getFunctionName(), 6);
109+
encodeRequestParams(bodyBuffer, request);
110+
os.writBodyeHead(bodyBuffer, 7);//
111+
TarsOutputStream endStream = new TarsOutputStream(endBuffer);
112+
endStream.write(request.getTimeout(), 8);
113+
endStream.write(request.getContext(), 9);
114+
endStream.write(request.getStatus(), 10);
115+
length = os.getByteBuffer().readableBytes() + bodyBuffer.readableBytes() + endStream.getByteBuffer().readableBytes();
116+
os.getByteBuffer().setInt(0, length);
117+
compositeByteBuf.addComponents(true, headBuffer, bodyBuffer, endBuffer);
118+
119+
} catch (Exception e) {
120+
//when encode exception
121+
ReferenceCountUtil.release(headBuffer);
122+
ReferenceCountUtil.release(bodyBuffer);
123+
ReferenceCountUtil.release(endBuffer);
124+
if (length > TarsHelper.PACKAGE_MAX_LENGTH || length <= 0) {
125+
throw new ProtocolException("the length header of the package must be between 0~10M bytes. data length:" + Integer.toHexString(length));
126+
}
100127
}
101-
return os.getByteBuffer();
128+
return compositeByteBuf;
102129
}
103130

104-
protected ByteBuf encodeRequestParams(TarsServantRequest request) throws ProtocolException {
105-
TarsOutputStream os = new TarsOutputStream();
131+
protected void encodeRequestParams(ByteBuf byteBuf, TarsServantRequest request) throws ProtocolException {
132+
TarsOutputStream os = new TarsOutputStream(byteBuf);
106133
os.setServerEncoding(this.charset);
107134
TarsMethodInfo methodInfo = request.getMethodInfo();
108135
List<TarsMethodParameterInfo> parameterInfoList = methodInfo.getParametersList();
@@ -127,79 +154,92 @@ protected ByteBuf encodeRequestParams(TarsServantRequest request) throws Protoco
127154
}
128155

129156
}
130-
return os.getByteBuffer();
131157
}
132158

133159

134-
public ByteBuf encodeResponse(Response resp) throws ProtocolException {
160+
public ByteBuf encodeResponse(ByteBufAllocator allocator, Response resp) throws ProtocolException {
135161
TarsServantResponse response = (TarsServantResponse) resp;
136162
if (response.getPacketType() == TarsHelper.ONEWAY) {
137163
return null;
138164
}
139-
TarsOutputStream jos = new TarsOutputStream();
140-
jos.setServerEncoding(charset);
165+
CompositeByteBuf compositeByteBuf = allocator.compositeBuffer();
166+
ByteBuf headBuffer = allocator.buffer();
167+
ByteBuf bodyBuffer = allocator.buffer();
168+
ByteBuf endBuffer = allocator.buffer();
141169
try {
142-
jos.getByteBuffer().writeInt(0);
143-
jos.write(response.getVersion(), 1);
144-
jos.write(response.getPacketType(), 2);
170+
TarsOutputStream jos = new TarsOutputStream(headBuffer);
171+
jos.setServerEncoding(charset);
172+
try {
173+
jos.getByteBuffer().writeInt(0);
174+
jos.write(response.getVersion(), 1);
175+
jos.write(response.getPacketType(), 2);
145176

146-
if (response.getVersion() == TarsHelper.VERSION) {
147-
jos.write(response.getRequestId(), 3);
148-
jos.write(response.getMessageType(), 4);
149-
jos.write(response.getRet(), 5);
150-
jos.write(encodeResult(response), 6);
151-
if (response.getStatus() != null) {
152-
jos.write(response.getStatus(), 7);
153-
}
154-
if (response.getRet() != TarsHelper.SERVERSUCCESS) {
155-
jos.write(StringUtils.isEmpty(response.getRemark()) ? "" : response.getRemark(), 8);
156-
}
157-
} else if (TarsHelper.VERSION2 == response.getVersion() || TarsHelper.VERSION3 == response.getVersion()) {
158-
jos.write(response.getMessageType(), 3);
159-
jos.write(response.getRequestId(), 4);
160-
String servantName = response.getRequest().getServantName();
161-
jos.write(servantName, 5);
162-
jos.write(response.getRequest().getFunctionName(), 6);
163-
jos.write(encodeWupResult(response), 7);
164-
jos.write(response.getTimeout(), 8);
165-
if (response.getContext() != null) {
166-
jos.write(response.getContext(), 9);
167-
}
168-
if (response.getStatus() != null) {
169-
jos.write(response.getStatus(), 10);
170-
}
171-
} else if (response.getVersion() == TarsHelper.VERSIONJSON) {
172-
jos.write(response.getRequestId(), 3);
173-
jos.write(response.getMessageType(), 4);
174-
jos.write(response.getRet(), 5);
175-
jos.write(encodeJsonResult(response), 6);
176-
if (response.getStatus() != null) {
177-
jos.write(response.getStatus(), 7);
177+
if (response.getVersion() == TarsHelper.VERSION) {
178+
jos.write(response.getRequestId(), 3);
179+
jos.write(response.getMessageType(), 4);
180+
jos.write(response.getRet(), 5);
181+
encodeResult(bodyBuffer, response);
182+
jos.writBodyeHead(bodyBuffer, 6);
183+
TarsOutputStream tarsOutputStream = new TarsOutputStream(endBuffer);
184+
if (response.getStatus() != null) {
185+
tarsOutputStream.write(response.getStatus(), 7);
186+
}
187+
if (response.getRet() != TarsHelper.SERVERSUCCESS) {
188+
tarsOutputStream.write(StringUtils.isEmpty(response.getRemark()) ? "" : response.getRemark(), 8);
189+
}
190+
} else if (TarsHelper.VERSION2 == response.getVersion() || TarsHelper.VERSION3 == response.getVersion()) {
191+
jos.write(response.getMessageType(), 3);
192+
jos.write(response.getRequestId(), 4);
193+
String servantName = response.getRequest().getServantName();
194+
jos.write(servantName, 5);
195+
jos.write(response.getRequest().getFunctionName(), 6);
196+
jos.write(encodeWupResult(response), 7);
197+
jos.write(response.getTimeout(), 8);
198+
if (response.getContext() != null) {
199+
jos.write(response.getContext(), 9);
200+
}
201+
if (response.getStatus() != null) {
202+
jos.write(response.getStatus(), 10);
203+
}
204+
} else if (response.getVersion() == TarsHelper.VERSIONJSON) {
205+
jos.write(response.getRequestId(), 3);
206+
jos.write(response.getMessageType(), 4);
207+
jos.write(response.getRet(), 5);
208+
jos.write(encodeJsonResult(response), 6);
209+
if (response.getStatus() != null) {
210+
jos.write(response.getStatus(), 7);
211+
}
212+
if (response.getRet() != TarsHelper.SERVERSUCCESS) {
213+
jos.write(StringUtils.isEmpty(response.getRemark()) ? "" : response.getRemark(), 8);
214+
}
215+
} else {
216+
response.setRet(TarsHelper.SERVERENCODEERR);
217+
System.err.println("un supported protocol, ver=" + response.getVersion());
178218
}
179-
if (response.getRet() != TarsHelper.SERVERSUCCESS) {
180-
jos.write(StringUtils.isEmpty(response.getRemark()) ? "" : response.getRemark(), 8);
219+
} catch (Exception ex) {
220+
if (response.getRet() == TarsHelper.SERVERSUCCESS) {
221+
response.setRet(TarsHelper.SERVERENCODEERR);
181222
}
182-
} else {
183-
response.setRet(TarsHelper.SERVERENCODEERR);
184-
System.err.println("un supported protocol, ver=" + response.getVersion());
185-
}
186-
} catch (Exception ex) {
187-
if (response.getRet() == TarsHelper.SERVERSUCCESS) {
188-
response.setRet(TarsHelper.SERVERENCODEERR);
189223
}
224+
final int dataLength = headBuffer.readableBytes() + bodyBuffer.readableBytes() + endBuffer.readableBytes();
225+
headBuffer.setInt(0, dataLength);//write real data length
226+
compositeByteBuf.addComponents(true, headBuffer, bodyBuffer, endBuffer);
227+
} catch (Exception e) {
228+
//when encode exception
229+
ReferenceCountUtil.release(headBuffer);
230+
ReferenceCountUtil.release(bodyBuffer);
231+
ReferenceCountUtil.release(endBuffer);
232+
System.err.println("un supported protocol, ver=" + response.getVersion());
190233
}
191-
final ByteBuf buffer = jos.getByteBuffer();
192-
final int dataLength = buffer.readableBytes();
193-
jos.getByteBuffer().setInt(0, dataLength);//write real data length
194-
return buffer;
234+
return compositeByteBuf;
195235
}
196236

197-
protected ByteBuf encodeResult(TarsServantResponse response) {
237+
protected void encodeResult(ByteBuf bytebuf, TarsServantResponse response) {
198238
TarsServantRequest request = (TarsServantRequest) response.getRequest();
199239
if (TarsHelper.isPing(request.getFunctionName())) {
200-
return Unpooled.buffer();
240+
return;
201241
}
202-
TarsOutputStream ajos = new TarsOutputStream();
242+
TarsOutputStream ajos = new TarsOutputStream(bytebuf);
203243
ajos.setServerEncoding(charset);
204244
int ret = response.getRet();
205245
Map<String, TarsMethodInfo> methodInfoMap = AnalystManager.getInstance().getMethodMapByName(request.getServantName());
@@ -229,7 +269,6 @@ protected ByteBuf encodeResult(TarsServantResponse response) {
229269
}
230270
}
231271
}
232-
return ajos.getByteBuffer();
233272
}
234273

235274
protected byte[] encodeWupResult(TarsServantResponse response) {
@@ -311,6 +350,7 @@ protected byte[] encodeJsonResult(TarsServantResponse response) {
311350
String result = object.toString();
312351
return result.getBytes(charset);
313352
}
353+
314354
}
315355

316356

core/src/main/java/com/qq/tars/protocol/tars/TarsOutputStream.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,11 @@ public void write(ByteBuf l, int tag) {
206206
write(l.readableBytes(), 0);
207207
bs.writeBytes(l);
208208
}
209+
public void writBodyeHead(ByteBuf l, int tag) {
210+
writeHead(TarsStructBase.SIMPLE_LIST, tag);
211+
writeHead(TarsStructBase.BYTE, 0);
212+
write(l.readableBytes(), 0);
213+
}
209214

210215

211216
public void write(short[] l, int tag) {

core/src/test/java/com/qq/tars/TransportTest.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ public void destroy() {
7575
long startTime = System.nanoTime();
7676
NettyServantClient client = NettyTransporter.connect(url, servantProxyConfig, channelHandler);
7777
System.out.println("init channel time " + ((System.nanoTime() - startTime) / 1000));
78-
for (int i = 0; i < 2; i++) {
78+
for (int i = 0; i < 100; i++) {
7979
MonitorQueryReq monitorQueryReq = new MonitorQueryReq();
8080
monitorQueryReq.dateType = DateType.MINIUES.value();
8181
monitorQueryReq.method = "query";
@@ -117,7 +117,7 @@ public void destroy() {
117117
System.out.println("client connection is " + client.getChannel().isWritable());
118118

119119

120-
Thread.sleep(50000);
120+
Thread.sleep(10000);
121121
}
122122

123123

@@ -174,11 +174,13 @@ public void testForQuery() {
174174
request.startTime = 1606060800L;
175175
request.endTime = 1606147199L;
176176
System.out.println(request);
177-
Holder<MonitorQueryRsp> holder = new Holder<>();
178-
queryPrx.query(request, holder);
179-
System.out.println(holder);
180-
177+
long startTime = System.currentTimeMillis();
178+
for (int i = 0; i < 10000; i++) {
179+
Holder<MonitorQueryRsp> holder = new Holder<>();
180+
queryPrx.query(request, holder);
181+
}
181182

183+
System.out.println(System.currentTimeMillis() - startTime);
182184
}
183185

184186
}

0 commit comments

Comments
 (0)