Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit874756c

Browse files
committed
Reduce Base64::encode allocations,closeAsyncHttpClient#1344
Motivation:`Base64::encode` allocates a StringBuilder on every call.Modifications:* Extract `StringBuilderPool` from `SringUtils`* Use such pool for `Base64::encode`Result:Less allocations
1 parent403e8ff commit874756c

File tree

10 files changed

+107
-95
lines changed

10 files changed

+107
-95
lines changed

‎client/src/main/java/org/asynchttpclient/Realm.java‎

Lines changed: 4 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@
1616
*/
1717
packageorg.asynchttpclient;
1818

19-
importstaticorg.asynchttpclient.util.Assertions.*;
20-
2119
importstaticjava.nio.charset.StandardCharsets.*;
20+
importstaticorg.asynchttpclient.util.Assertions.assertNotNull;
2221
importstaticorg.asynchttpclient.util.MiscUtils.isNonEmpty;
22+
importstaticorg.asynchttpclient.util.StringUtils.*;
2323

2424
importjava.nio.charset.Charset;
2525
importjava.security.MessageDigest;
@@ -28,6 +28,7 @@
2828

2929
importorg.asynchttpclient.uri.Uri;
3030
importorg.asynchttpclient.util.AuthenticatorUtils;
31+
importorg.asynchttpclient.util.StringBuilderPool;
3132
importorg.asynchttpclient.util.StringUtils;
3233

3334
/**
@@ -459,7 +460,7 @@ private void newResponse(MessageDigest md) {
459460
// BEWARE: compute first as it used the cached StringBuilder
460461
StringdigestUri =AuthenticatorUtils.computeRealmURI(uri,useAbsoluteURI,omitQuery);
461462

462-
StringBuildersb =StringUtils.stringBuilder();
463+
StringBuildersb =StringBuilderPool.DEFAULT.stringBuilder();
463464

464465
// WARNING: DON'T MOVE, BUFFER IS RECYCLED!!!!
465466
byte[]secretDigest =secretDigest(sb,md);
@@ -473,30 +474,6 @@ private void newResponse(MessageDigest md) {
473474
response =toHexString(responseDigest);
474475
}
475476

476-
privatestaticStringtoHexString(byte[]data) {
477-
StringBuilderbuffer =StringUtils.stringBuilder();
478-
for (byteaData :data) {
479-
buffer.append(Integer.toHexString((aData &0xf0) >>>4));
480-
buffer.append(Integer.toHexString(aData &0x0f));
481-
}
482-
returnbuffer.toString();
483-
}
484-
485-
privatestaticvoidappendBase16(StringBuilderbuf,byte[]bytes) {
486-
intbase =16;
487-
for (byteb :bytes) {
488-
intbi =0xff &b;
489-
intc ='0' + (bi /base) %base;
490-
if (c >'9')
491-
c ='a' + (c -'0' -10);
492-
buf.append((char)c);
493-
c ='0' +bi %base;
494-
if (c >'9')
495-
c ='a' + (c -'0' -10);
496-
buf.append((char)c);
497-
}
498-
}
499-
500477
/**
501478
* Build a {@link Realm}
502479
*

‎client/src/main/java/org/asynchttpclient/oauth/OAuthSignatureCalculatorInstance.java‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
importorg.asynchttpclient.RequestBuilderBase;
3232
importorg.asynchttpclient.SignatureCalculator;
3333
importorg.asynchttpclient.util.Base64;
34+
importorg.asynchttpclient.util.StringBuilderPool;
3435
importorg.asynchttpclient.util.StringUtils;
3536
importorg.asynchttpclient.util.Utf8UrlEncoder;
3637

@@ -103,7 +104,7 @@ StringBuilder signatureBaseString(ConsumerKey consumerAuth, RequestToken userAut
103104
StringbaseUrl =request.getUri().toBaseUrl();
104105
StringencodedParams =encodedParams(consumerAuth,userAuth,oauthTimestamp,nonce,request.getFormParams(),request.getQueryParams());
105106

106-
StringBuildersb =StringUtils.stringBuilder();
107+
StringBuildersb =StringBuilderPool.DEFAULT.stringBuilder();
107108
sb.append(request.getMethod());// POST / GET etc (nothing to URL encode)
108109
sb.append('&');
109110
Utf8UrlEncoder.encodeAndAppendPercentEncoded(sb,baseUrl);
@@ -154,7 +155,7 @@ private String percentEncodeAlreadyFormUrlEncoded(String s) {
154155
}
155156

156157
privatebyte[]digest(ConsumerKeyconsumerAuth,RequestTokenuserAuth,ByteBuffermessage)throwsInvalidKeyException {
157-
StringBuildersb =StringUtils.stringBuilder();
158+
StringBuildersb =StringBuilderPool.DEFAULT.stringBuilder();
158159
Utf8UrlEncoder.encodeAndAppendQueryElement(sb,consumerAuth.getSecret());
159160
sb.append('&');
160161
if (userAuth !=null &&userAuth.getSecret() !=null) {
@@ -170,7 +171,7 @@ private byte[] digest(ConsumerKey consumerAuth, RequestToken userAuth, ByteBuffe
170171
}
171172

172173
StringconstructAuthHeader(ConsumerKeyconsumerAuth,RequestTokenuserAuth,Stringsignature,Stringnonce,longoauthTimestamp) {
173-
StringBuildersb =StringUtils.stringBuilder();
174+
StringBuildersb =StringBuilderPool.DEFAULT.stringBuilder();
174175
sb.append("OAuth ");
175176
sb.append(KEY_OAUTH_CONSUMER_KEY).append("=\"").append(consumerAuth.getKey()).append("\", ");
176177
if (userAuth.getKey() !=null) {

‎client/src/main/java/org/asynchttpclient/oauth/Parameters.java‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
importjava.util.Collections;
1818
importjava.util.List;
1919

20-
importorg.asynchttpclient.util.StringUtils;
20+
importorg.asynchttpclient.util.StringBuilderPool;
2121

2222
classParameters {
2323

@@ -37,7 +37,7 @@ String sortAndConcat() {
3737
Collections.sort(parameters);
3838

3939
// and build parameter section using pre-encoded pieces:
40-
StringBuilderencodedParams =StringUtils.stringBuilder();
40+
StringBuilderencodedParams =StringBuilderPool.DEFAULT.stringBuilder();
4141
for (inti =0;i <parameters.size();i++) {
4242
Parameterparam =parameters.get(i);
4343
encodedParams.append(param.key).append('=').append(param.value).append('&');

‎client/src/main/java/org/asynchttpclient/request/body/multipart/MultipartUtils.java‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
importorg.asynchttpclient.request.body.multipart.part.MessageEndMultipartPart;
3030
importorg.asynchttpclient.request.body.multipart.part.MultipartPart;
3131
importorg.asynchttpclient.request.body.multipart.part.StringMultipartPart;
32-
importorg.asynchttpclient.util.StringUtils;
32+
importorg.asynchttpclient.util.StringBuilderPool;
3333

3434
publicclassMultipartUtils {
3535

@@ -106,7 +106,7 @@ private static byte[] generateBoundary() {
106106
}
107107

108108
privatestaticStringcomputeContentType(CharSequencebase,byte[]boundary) {
109-
StringBuilderbuffer =StringUtils.stringBuilder().append(base);
109+
StringBuilderbuffer =StringBuilderPool.DEFAULT.stringBuilder().append(base);
110110
if (base.length() !=0 &&base.charAt(base.length() -1) !=';')
111111
buffer.append(';');
112112
returnbuffer.append(" boundary=").append(newString(boundary,US_ASCII)).toString();

‎client/src/main/java/org/asynchttpclient/uri/Uri.java‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,14 @@
1212
*/
1313
packageorg.asynchttpclient.uri;
1414

15-
importstaticorg.asynchttpclient.util.Assertions.*;
15+
importstaticorg.asynchttpclient.util.Assertions.assertNotNull;
1616
importstaticorg.asynchttpclient.util.MiscUtils.isNonEmpty;
1717

1818
importjava.net.URI;
1919
importjava.net.URISyntaxException;
2020

2121
importorg.asynchttpclient.util.MiscUtils;
22-
importorg.asynchttpclient.util.StringUtils;
22+
importorg.asynchttpclient.util.StringBuilderPool;
2323

2424
publicclassUri {
2525

@@ -117,7 +117,7 @@ public int getSchemeDefaultPort() {
117117

118118
publicStringtoUrl() {
119119
if (url ==null) {
120-
StringBuildersb =StringUtils.stringBuilder();
120+
StringBuildersb =StringBuilderPool.DEFAULT.stringBuilder();
121121
sb.append(scheme).append("://");
122122
if (userInfo !=null)
123123
sb.append(userInfo).append('@');
@@ -138,7 +138,7 @@ public String toUrl() {
138138
* @return <scheme>://<hostname>(:<port>). Port is ommitted if it matches the scheme's default one.
139139
*/
140140
publicStringtoBaseUrl() {
141-
StringBuildersb =StringUtils.stringBuilder();
141+
StringBuildersb =StringBuilderPool.DEFAULT.stringBuilder();
142142
sb.append(scheme).append("://").append(host);
143143
if (port != -1 &&port !=getSchemeDefaultPort()) {
144144
sb.append(':').append(port);
@@ -150,7 +150,7 @@ public String toBaseUrl() {
150150
}
151151

152152
publicStringtoRelativeUrl() {
153-
StringBuildersb =StringUtils.stringBuilder();
153+
StringBuildersb =StringBuilderPool.DEFAULT.stringBuilder();
154154
if (MiscUtils.isNonEmpty(path))
155155
sb.append(path);
156156
else

‎client/src/main/java/org/asynchttpclient/util/Base64.java‎

Lines changed: 29 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -13,59 +13,55 @@
1313
packageorg.asynchttpclient.util;
1414

1515
/**
16-
* Implements the "base64" binary encoding scheme as defined by
17-
* <a href="http://tools.ietf.org/html/rfc2045">RFC 2045</a>.
18-
* <br>
16+
* Implements the "base64" binary encoding scheme as defined by <a href="http://tools.ietf.org/html/rfc2045">RFC 2045</a>. <br>
1917
* Portions of code here are taken from Apache Pivot
2018
*/
2119
publicfinalclassBase64 {
22-
privatestaticfinalchar[]lookup =newchar[64];
23-
privatestaticfinalbyte[]reverseLookup =newbyte[256];
20+
privatestaticfinalStringBuilderPoolSB_POOL =newStringBuilderPool();
21+
privatestaticfinalchar[]LOOKUP =newchar[64];
22+
privatestaticfinalbyte[]REVERSE_LOOKUP =newbyte[256];
2423

2524
static {
2625
// Populate the lookup array
2726

2827
for (inti =0;i <26;i++) {
29-
lookup[i] = (char) ('A' +i);
28+
LOOKUP[i] = (char) ('A' +i);
3029
}
3130

3231
for (inti =26,j =0;i <52;i++,j++) {
33-
lookup[i] = (char) ('a' +j);
32+
LOOKUP[i] = (char) ('a' +j);
3433
}
3534

3635
for (inti =52,j =0;i <62;i++,j++) {
37-
lookup[i] = (char) ('0' +j);
36+
LOOKUP[i] = (char) ('0' +j);
3837
}
3938

40-
lookup[62] ='+';
41-
lookup[63] ='/';
39+
LOOKUP[62] ='+';
40+
LOOKUP[63] ='/';
4241

4342
// Populate the reverse lookup array
4443

4544
for (inti =0;i <256;i++) {
46-
reverseLookup[i] = -1;
45+
REVERSE_LOOKUP[i] = -1;
4746
}
4847

4948
for (inti ='Z';i >='A';i--) {
50-
reverseLookup[i] = (byte) (i -'A');
49+
REVERSE_LOOKUP[i] = (byte) (i -'A');
5150
}
5251

5352
for (inti ='z';i >='a';i--) {
54-
reverseLookup[i] = (byte) (i -'a' +26);
53+
REVERSE_LOOKUP[i] = (byte) (i -'a' +26);
5554
}
5655

5756
for (inti ='9';i >='0';i--) {
58-
reverseLookup[i] = (byte) (i -'0' +52);
57+
REVERSE_LOOKUP[i] = (byte) (i -'0' +52);
5958
}
6059

61-
reverseLookup['+'] =62;
62-
reverseLookup['/'] =63;
63-
reverseLookup['='] =0;
60+
REVERSE_LOOKUP['+'] =62;
61+
REVERSE_LOOKUP['/'] =63;
62+
REVERSE_LOOKUP['='] =0;
6463
}
6564

66-
/**
67-
* This class is not instantiable.
68-
*/
6965
privateBase64() {
7066
}
7167

@@ -76,30 +72,29 @@ private Base64() {
7672
* @return the encoded data
7773
*/
7874
publicstaticStringencode(byte[]bytes) {
79-
// always sequence of 4 characters for each 3 bytes; padded with '='s as necessary:
80-
StringBuilderbuf =newStringBuilder(((bytes.length +2) /3) *4);
75+
StringBuilderbuf =SB_POOL.stringBuilder();
8176

8277
// first, handle complete chunks (fast loop)
8378
inti =0;
8479
for (intend =bytes.length -2;i <end;) {
8580
intchunk = ((bytes[i++] &0xFF) <<16) | ((bytes[i++] &0xFF) <<8) | (bytes[i++] &0xFF);
86-
buf.append(lookup[chunk >>18]);
87-
buf.append(lookup[(chunk >>12) &0x3F]);
88-
buf.append(lookup[(chunk >>6) &0x3F]);
89-
buf.append(lookup[chunk &0x3F]);
81+
buf.append(LOOKUP[chunk >>18]);
82+
buf.append(LOOKUP[(chunk >>12) &0x3F]);
83+
buf.append(LOOKUP[(chunk >>6) &0x3F]);
84+
buf.append(LOOKUP[chunk &0x3F]);
9085
}
9186

9287
// then leftovers, if any
9388
intlen =bytes.length;
9489
if (i <len) {// 1 or 2 extra bytes?
9590
intchunk = ((bytes[i++] &0xFF) <<16);
96-
buf.append(lookup[chunk >>18]);
91+
buf.append(LOOKUP[chunk >>18]);
9792
if (i <len) {// 2 bytes
9893
chunk |= ((bytes[i] &0xFF) <<8);
99-
buf.append(lookup[(chunk >>12) &0x3F]);
100-
buf.append(lookup[(chunk >>6) &0x3F]);
94+
buf.append(LOOKUP[(chunk >>12) &0x3F]);
95+
buf.append(LOOKUP[(chunk >>6) &0x3F]);
10196
}else {// 1 byte
102-
buf.append(lookup[(chunk >>12) &0x3F]);
97+
buf.append(LOOKUP[(chunk >>12) &0x3F]);
10398
buf.append('=');
10499
}
105100
buf.append('=');
@@ -124,10 +119,10 @@ public static byte[] decode(String encoded) {
124119
byte[]bytes =newbyte[length];
125120

126121
for (inti =0,index =0,n =encoded.length();i <n;i +=4) {
127-
intword =reverseLookup[encoded.charAt(i)] <<18;
128-
word +=reverseLookup[encoded.charAt(i +1)] <<12;
129-
word +=reverseLookup[encoded.charAt(i +2)] <<6;
130-
word +=reverseLookup[encoded.charAt(i +3)];
122+
intword =REVERSE_LOOKUP[encoded.charAt(i)] <<18;
123+
word +=REVERSE_LOOKUP[encoded.charAt(i +1)] <<12;
124+
word +=REVERSE_LOOKUP[encoded.charAt(i +2)] <<6;
125+
word +=REVERSE_LOOKUP[encoded.charAt(i +3)];
131126

132127
for (intj =0;j <3 &&index +j <length;j++) {
133128
bytes[index +j] = (byte) (word >> (8 * (2 -j)));

‎client/src/main/java/org/asynchttpclient/util/HttpUtils.java‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ public static boolean followRedirect(AsyncHttpClientConfig config, Request reque
8383
}
8484

8585
privatestaticStringBuilderurlEncodeFormParams0(List<Param>params) {
86-
StringBuildersb =StringUtils.stringBuilder();
86+
StringBuildersb =StringBuilderPool.DEFAULT.stringBuilder();
8787
for (Paramparam :params) {
8888
encodeAndAppendFormParam(sb,param.getName(),param.getValue());
8989
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* Copyright (c) 2017 AsyncHttpClient Project. All rights reserved.
3+
*
4+
* This program is licensed to you under the Apache License Version 2.0,
5+
* and you may not use this file except in compliance with the Apache License Version 2.0.
6+
* You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0.
7+
*
8+
* Unless required by applicable law or agreed to in writing,
9+
* software distributed under the Apache License Version 2.0 is distributed on an
10+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
* See the Apache License Version 2.0 for the specific language governing permissions and limitations there under.
12+
*/
13+
packageorg.asynchttpclient.util;
14+
15+
publicclassStringBuilderPool {
16+
17+
publicstaticfinalStringBuilderPoolDEFAULT =newStringBuilderPool();
18+
19+
privatefinalThreadLocal<StringBuilder>pool =ThreadLocal.withInitial(() ->newStringBuilder(512));
20+
21+
/**
22+
* BEWARE: MUSN'T APPEND TO ITSELF!
23+
*
24+
* @return a pooled StringBuilder
25+
*/
26+
publicStringBuilderstringBuilder() {
27+
StringBuildersb =pool.get();
28+
sb.setLength(0);
29+
returnsb;
30+
}
31+
}

‎client/src/main/java/org/asynchttpclient/util/StringUtils.java‎

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,22 +18,6 @@
1818

1919
publicfinalclassStringUtils {
2020

21-
privatestaticfinalThreadLocal<StringBuilder>STRING_BUILDER_POOL =newThreadLocal<StringBuilder>() {
22-
protectedStringBuilderinitialValue() {
23-
returnnewStringBuilder(512);
24-
}
25-
};
26-
27-
/**
28-
* BEWARE: MUSN'T APPEND TO ITSELF!
29-
* @return a pooled StringBuilder
30-
*/
31-
publicstaticStringBuilderstringBuilder() {
32-
StringBuildersb =STRING_BUILDER_POOL.get();
33-
sb.setLength(0);
34-
returnsb;
35-
}
36-
3721
privateStringUtils() {
3822
}
3923

@@ -51,4 +35,28 @@ public static byte[] charSequence2Bytes(CharSequence sb, Charset charset) {
5135
ByteBufferbb =charSequence2ByteBuffer(sb,charset);
5236
returnbyteBuffer2ByteArray(bb);
5337
}
38+
39+
publicstaticStringtoHexString(byte[]data) {
40+
StringBuilderbuffer =StringBuilderPool.DEFAULT.stringBuilder();
41+
for (byteaData :data) {
42+
buffer.append(Integer.toHexString((aData &0xf0) >>>4));
43+
buffer.append(Integer.toHexString(aData &0x0f));
44+
}
45+
returnbuffer.toString();
46+
}
47+
48+
publicstaticvoidappendBase16(StringBuilderbuf,byte[]bytes) {
49+
intbase =16;
50+
for (byteb :bytes) {
51+
intbi =0xff &b;
52+
intc ='0' + (bi /base) %base;
53+
if (c >'9')
54+
c ='a' + (c -'0' -10);
55+
buf.append((char)c);
56+
c ='0' +bi %base;
57+
if (c >'9')
58+
c ='a' + (c -'0' -10);
59+
buf.append((char)c);
60+
}
61+
}
5462
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp