Optimize StringBuilder.append for String with range

by using String.charsAt to avoid performing 1-by-1 copying.

Also adds a benchmark testing append for substring.

Before:
    Trial Report (1 of 3):
      Experiment {instrument=runtime, benchmarkMethod=timeAppendSubCharSequence, vm=default, parameters={length=1}}
      Results:
        runtime(ns): min=231.16, 1st qu.=233.24, median=244.20, mean=241.41, 3rd qu.=247.49, max=252.71
    Trial Report (2 of 3):
      Experiment {instrument=runtime, benchmarkMethod=timeAppendSubCharSequence, vm=default, parameters={length=10}}
      Results:
        runtime(ns): min=1639.48, 1st qu.=1646.44, median=1658.96, mean=1669.49, 3rd qu.=1694.87, max=1726.36
    Trial Report (3 of 3):
      Experiment {instrument=runtime, benchmarkMethod=timeAppendSubCharSequence, vm=default, parameters={length=100}}
      Results:
        runtime(ns): min=14867.68, 1st qu.=14914.04, median=14965.08, mean=15050.44, 3rd qu.=15189.02, max=15423.22

After:
    Trial Report (1 of 3):
      Experiment {instrument=runtime, benchmarkMethod=timeAppendSubCharSequence, vm=default, parameters={length=1}}
      Results:
        runtime(ns): min=139.58, 1st qu.=141.36, median=143.44, mean=146.17, 3rd qu.=148.57, max=164.15
    Trial Report (2 of 3):
      Experiment {instrument=runtime, benchmarkMethod=timeAppendSubCharSequence, vm=default, parameters={length=10}}
      Results:
        runtime(ns): min=503.95, 1st qu.=507.65, median=520.78, mean=541.48, 3rd qu.=580.13, max=596.60
    Trial Report (3 of 3):
      Experiment {instrument=runtime, benchmarkMethod=timeAppendSubCharSequence, vm=default, parameters={length=100}}
      Results:
        runtime(ns): min=4797.27, 1st qu.=4832.23, median=4861.71, mean=4936.96, 3rd qu.=5049.35, max=5140.17

Bug: 28327317
Change-Id: I81a4b83cf4b3d854dbb635cd49669ba0bec96009
2 files changed