Uploaded image for project: 'PUBLIC - Liferay Portal Community Edition'
  1. PUBLIC - Liferay Portal Community Edition
  2. LPS-6072

Fix the wrong use of SB(StringBuilder and StringBuffer)

    Details

    • Type: Story
    • Status: Closed
    • Priority: Minor
    • Resolution: Completed
    • Affects Version/s: 5.1.2, 5.2.3
    • Fix Version/s: --Sprint 12/11
    • Component/s: None
    • Labels:
      None
    • Branch Version/s:
      5.2.x, 5.1.x
    • Backported to Branch:
      Committed

      Description

      People always say StringBuilder/StringBuffer is better than "+", but it is not always true. Wrong use of SB(StringBuilder/StringBuffer) can cause a lot of short life objects which are garbages. These garbage objects will waste a lot of your cpu times to clean up.

      This ticket is supposed to fix the exist wrong use of SB, and explain how to use them correctly, so people won't make the same mistake again.

      From now on when i say waste object, i only mean the internal byte[] of String and SB, not String and Sb themselves, since String and Sb do not have too many fields except the byte[].

      If you want to connect two string together, in which way should you do it?

      String a = "abcdefghijklmnopq"; //length=17
      String b = "abcdefghijklmnopqr"; //length=18

      By "", javac will compile "" to String.concat(String str), see the jdk source code if you like, this mothed create a new byte[] to contain the content of a and b.
      So in this process, a and b are parameters(not created by you), the connected result is what you need, you have not create any waste object and even not wasting a single byte!

      Waste object number 0! waste bytes number 0!

      By SB, let's use StringBuilder as demo, the first version of code is:

      String result = new StringBuilder().append(a).append(b).toString();

      In this process, new StringBuilder() creates an internal byte[] whose size is 16, when you append a to it, because a.length == 17 > 16, so it has to increase, see the jdk source code of AbstractStringBuilder.expandCapacity(), it creates a new byte[] whose size is (16+1)*2 = 34, and use the first 17 bytes to contain a(you have 17 bytes freespace). At point your old 16 byte[] in SB becomes garbage, plus 1 waste object! Let's move on, when you append b to it, same thing happens, b.length == 18 > 17, it has to increase again, now the internal byte[] size is (34+1)*2=70. One more old 34 byte[] waste object created. Thing have not finish yet! When you call SB.toString(), see the source code!

      StringBuilder:

      public String toString() {
      // Create a copy, don't share the array
      return new String(value, 0, count);
      }

      String:

      public String(char value[], int offset, int count) {
      if (offset < 0)

      { throw new StringIndexOutOfBoundsException(offset); }

      if (count < 0)

      { throw new StringIndexOutOfBoundsException(count); }

      // Note: offset or count might be near -1>>>1.
      if (offset > value.length - count)

      { throw new StringIndexOutOfBoundsException(offset + count); }

      this.offset = 0;
      this.count = count;
      this.value = Arrays.copyOfRange(value, offset, offset+count);
      }

      Do you see the Arrays.copyOfRange(originalValue, off, off+size)! one more waste object, size 70!

      So finally with SB, you created 3 waste objects, total size is 16 + 34 + 70 =120 bytes, i do feel sorry for you

      One thing can makes this better, change the code to:

      String result = new StringBuilder(a.length() + b.length()).append(a).append(b).toString();

      Calc it yourself, you create only one waste object whose size is 17 + 18 = 35, it is still bad, isn't it?

      And don't forget the stack calls, they are not free, with SB you are doing more methods calling.

      Wants to see more?! Do it yourself to see what happens with 3 strings adding, you will be even more surprised!

      I don't want to make this explain any longer, here is the advice about when and how to use SB:

      1)Only use them whe you are trying to connect more than 3 string(not including 3)
      2)Ensure the capability of the SB at constructor, in most usual case you can precisely predict it, so please do it!

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              support-lep@liferay.com SE Support
              Reporter:
              shuyang.zhou Shuyang Zhou
              Recent user:
              Kiyoshi Lee
              Participants of an Issue:
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved:

                  Packages

                  Version Package
                  --Sprint 12/11