Skip to content
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

Improve usage of ByteArrayOutputStream/ByteArrayInputStream #24805

Closed
wants to merge 1 commit into from

Conversation

stsypanov
Copy link
Contributor

  • ByteArrayInputStream.flush() is no-op method along with ByteArrayInputStream.close(), ByteArrayOutputStream.flush() and ByteArrayOutputStream.close(). So we can drop try-with-resources statements as well as explicit calls to flush()/close()
  • new String(BAOS.toByteArray(), charset) replaced with call to StreamUtils.baosToString(baos, charset) to swallow UnsupportedEncodingException which is actually never thrown as charset is already available at invocation point

As of performance I've used more precise benchmark:

@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Fork(jvmArgsAppend = {"-Xms2g", "-Xmx2g", "-XX:+UseParallelGC"})
public class ByteArrayOutputStreamBenchmark {

  @Benchmark
  public String toString(Data data) throws UnsupportedEncodingException {
    return data.baos.toString(data.charset.name());
  }

  @Benchmark
  public String newString(Data data) {
    return new String(data.baos.toByteArray(), data.charset);
  }

  @Benchmark
  public String toString_noCS(Data data) {
    return data.baos.toString();
  }

  @Benchmark
  public String newString_noCS(Data data) {
    return new String(data.baos.toByteArray());
  }

  @State(Scope.Thread)
  public static class Data {

    @Param({"0", "10", "100", "1000"})
    private int length;

    private final Charset charset = Charset.defaultCharset();

    private ByteArrayOutputStream baos;

    @Setup
    public void setup() throws IOException {
      byte[] bytes = StringUtils.repeat('a', length).getBytes(charset);

      baos = new ByteArrayOutputStream(length);
      baos.write(bytes);
    }
  }

}

Which demonstrates improvement in both time and memory consumption

JDK 8
                                       (length)  Mode      Score     Error   Units

newString                                     0  avgt     66.084 ±   2.121   ns/op
toString                                      0  avgt     44.601 ±   0.656   ns/op
newString_noCS                                0  avgt     69.694 ±   1.949   ns/op
toString_noCS                                 0  avgt     43.758 ±   0.333   ns/op

newString                                    10  avgt     53.232 ±   1.569   ns/op
toString                                     10  avgt     45.151 ±   0.397   ns/op
newString_noCS                               10  avgt     52.005 ±   0.473   ns/op
toString_noCS                                10  avgt     45.657 ±   4.325   ns/op

newString                                   100  avgt     96.067 ±   1.466   ns/op
toString                                    100  avgt     77.924 ±   0.645   ns/op
newString_noCS                              100  avgt     94.716 ±   3.138   ns/op
toString_noCS                               100  avgt     80.460 ±   1.375   ns/op

newString                                  1000  avgt    667.188 ±  33.071   ns/op
toString                                   1000  avgt    511.302 ±   1.730   ns/op
newString_noCS                             1000  avgt    624.721 ±  20.786   ns/op
toString_noCS                              1000  avgt    530.833 ±  11.087   ns/op

newString:·gc.alloc.rate.norm                 0  avgt     96.000 ±   0.001    B/op
toString:·gc.alloc.rate.norm                  0  avgt     40.000 ±   0.001    B/op
newString_noCS:·gc.alloc.rate.norm            0  avgt     56.000 ±   0.001    B/op
toString_noCS:·gc.alloc.rate.norm             0  avgt     40.000 ±   0.001    B/op

newString:·gc.alloc.rate.norm                10  avgt    136.000 ±   0.001    B/op
toString:·gc.alloc.rate.norm                 10  avgt     64.000 ±   0.001    B/op
newString_noCS:·gc.alloc.rate.norm           10  avgt     96.000 ±   0.001    B/op
toString_noCS:·gc.alloc.rate.norm            10  avgt     64.000 ±   0.001    B/op

newString:·gc.alloc.rate.norm               100  avgt    400.000 ±   0.001    B/op
toString:·gc.alloc.rate.norm                100  avgt    240.000 ±   0.001    B/op
newString_noCS:·gc.alloc.rate.norm          100  avgt    360.000 ±   0.001    B/op
toString_noCS:·gc.alloc.rate.norm           100  avgt    240.000 ±   0.001    B/op

newString:·gc.alloc.rate.norm              1000  avgt   3096.001 ±   0.001    B/op
toString:·gc.alloc.rate.norm               1000  avgt   2040.001 ±   0.001    B/op
newString_noCS:·gc.alloc.rate.norm         1000  avgt   3056.001 ±   0.001    B/op
toString_noCS:·gc.alloc.rate.norm          1000  avgt   2040.001 ±   0.001    B/op

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Mar 28, 2020
@sbrannen sbrannen added type: enhancement A general enhancement and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Mar 30, 2020
@sbrannen sbrannen self-assigned this Mar 30, 2020
@sbrannen sbrannen added this to the 5.2.6 milestone Mar 30, 2020
@sbrannen
Copy link
Member

sbrannen commented Mar 30, 2020

For future reference, please make sure you execute ./gradlew check prior to submitting a PR in order to avoid errors such as the following.

> Task :spring-core:checkstyleMain FAILED
[ant:checkstyle] [ERROR] /source/spring-framework/spring-core/src/main/java/org/springframework/util/StreamUtils.java:249:20: Javadoc element descriptions should not start with an uppercase letter. [SpringJavadoc]
[ant:checkstyle] [ERROR] /source/spring-framework/spring-core/src/main/java/org/springframework/util/StreamUtils.java:256:17: '}' at column 3 should be alone on a line. [RightCurly]
[ant:checkstyle] [ERROR] /source/spring-framework/spring-core/src/main/java/org/springframework/util/StreamUtils.java:256:55: Single letter catch variable (use "ex" instead). [SpringCatch]

@stsypanov
Copy link
Contributor Author

@sbrannen let me push once again ))

@sbrannen
Copy link
Member

I've already begun a local merge process.

So no need to push again.

@stsypanov
Copy link
Contributor Author

Ok, I was unaware about ./gradlew check, thanks for pointing that out!

@sbrannen sbrannen closed this in e63d1cf Mar 30, 2020
sbrannen added a commit that referenced this pull request Mar 30, 2020

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
See gh-24805
@sbrannen
Copy link
Member

This has been merged into master in e63d1cf and further revised in 9e30620.

Thanks

@stsypanov stsypanov deleted the baos branch March 31, 2020 07:16
izeye added a commit to izeye/samples-jmh-gradle that referenced this pull request Apr 10, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: enhancement A general enhancement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants