[
https://issues.apache.org/jira/browse/CALCITE-3878?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17068270#comment-17068270
]
neoremind edited comment on CALCITE-3878 at 3/27/20, 5:08 AM:
--------------------------------------------------------------
To verify, I made a benchmark.
{code:java}
@State(Scope.Thread)
@Threads(1)
public class ArrayListTest {
@Param({ "256" })
int size;
List<String> strs;
public static void main(String[] args) throws RunnerException {
Options opt = new OptionsBuilder()
.include(ArrayListTest.class.getName())
.addProfiler(GCProfiler.class)
.warmupIterations(1)
.warmupTime(TimeValue.valueOf("10"))
.measurementIterations(2)
.measurementTime(TimeValue.valueOf("6"))
.forks(2)
.build();
new Runner(opt).run();
}
@Setup
public void setup() {
strs = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
strs.add(String.valueOf(i));
}
}
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public void testWithoutInitialCapacity() {
List<String> list = new ArrayList<>();
for (String s : strs) {
list.add(s);
}
}
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public void testWithInitialCapacity() {
List<String> list = new ArrayList<>(size);
for (String s : strs) {
list.add(s);
}
}
}
{code}
The results shows with initial capacity, the average time and gc is better. For
average time, it performs 22% better. For memory allocation, without initial
size, it consumes up to 1616.472 MB/sec, while with initial size only 480.301
MB/sec used.
{code:java}
Benchmark
(size) Mode Cnt Score Error Units
ArrayListTest.testWithInitialCapacity
256 avgt 4 1914.580 ± 1050.407 ns/op
ArrayListTest.testWithInitialCapacity:·gc.alloc.rate
256 avgt 4 480.301 ± 243.528 MB/sec
ArrayListTest.testWithInitialCapacity:·gc.alloc.rate.norm
256 avgt 4 1040.000 ± 0.001 B/op
ArrayListTest.testWithInitialCapacity:·gc.churn.PS_Eden_Space
256 avgt 4 482.151 ± 239.883 MB/sec
ArrayListTest.testWithInitialCapacity:·gc.churn.PS_Eden_Space.norm
256 avgt 4 1044.103 ± 18.772 B/op
ArrayListTest.testWithInitialCapacity:·gc.churn.PS_Survivor_Space
256 avgt 4 0.050 ± 0.093 MB/sec
ArrayListTest.testWithInitialCapacity:·gc.churn.PS_Survivor_Space.norm
256 avgt 4 0.108 ± 0.168 B/op
ArrayListTest.testWithInitialCapacity:·gc.count
256 avgt 4 410.000 counts
ArrayListTest.testWithInitialCapacity:·gc.time
256 avgt 4 213.000 ms
ArrayListTest.testWithoutInitialCapacity
256 avgt 4 2462.095 ± 469.356 ns/op
ArrayListTest.testWithoutInitialCapacity:·gc.alloc.rate
256 avgt 4 1616.472 ± 305.481 MB/sec
ArrayListTest.testWithoutInitialCapacity:·gc.alloc.rate.norm
256 avgt 4 4520.000 ± 0.001 B/op
ArrayListTest.testWithoutInitialCapacity:·gc.churn.PS_Eden_Space
256 avgt 4 1619.863 ± 259.328 MB/sec
ArrayListTest.testWithoutInitialCapacity:·gc.churn.PS_Eden_Space.norm
256 avgt 4 4529.933 ± 138.807 B/op
ArrayListTest.testWithoutInitialCapacity:·gc.churn.PS_Survivor_Space
256 avgt 4 0.155 ± 0.167 MB/sec
ArrayListTest.testWithoutInitialCapacity:·gc.churn.PS_Survivor_Space.norm
256 avgt 4 0.432 ± 0.418 B/op
ArrayListTest.testWithoutInitialCapacity:·gc.count
256 avgt 4 427.000 counts
ArrayListTest.testWithoutInitialCapacity:·gc.time
256 avgt 4 226.000 ms
{code}
was (Author: neoremind):
To verify, I made a benchmark.
{code:java}
@State(Scope.Thread)
@Threads(1)
public class ArrayListTest {
@Param({ "256" })
int size;
List<String> strs;
public static void main(String[] args) throws RunnerException {
Options opt = new OptionsBuilder()
.include(ArrayListTest.class.getName())
.addProfiler(GCProfiler.class)
.warmupIterations(1)
.warmupTime(TimeValue.valueOf("10"))
.measurementIterations(2)
.measurementTime(TimeValue.valueOf("6"))
.forks(2)
.build();
new Runner(opt).run();
}
@Setup
public void setup() {
strs = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
strs.add(String.valueOf(i));
}
}
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public void testWithoutInitialCapacity() {
List<String> list = new ArrayList<>();
for (String s : strs) {
list.add(s);
}
}
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public void testWithInitialCapacity() {
List<String> list = new ArrayList<>(size);
for (String s : strs) {
list.add(s);
}
}
}
{code}
The results shows with initial capacity, the average time and gc is better. For
average time, it performs 22% better.
{code:java}
Benchmark
(size) Mode Cnt Score Error Units
ArrayListTest.testWithInitialCapacity
256 avgt 4 1914.580 ± 1050.407 ns/op
ArrayListTest.testWithInitialCapacity:·gc.alloc.rate
256 avgt 4 480.301 ± 243.528 MB/sec
ArrayListTest.testWithInitialCapacity:·gc.alloc.rate.norm
256 avgt 4 1040.000 ± 0.001 B/op
ArrayListTest.testWithInitialCapacity:·gc.churn.PS_Eden_Space
256 avgt 4 482.151 ± 239.883 MB/sec
ArrayListTest.testWithInitialCapacity:·gc.churn.PS_Eden_Space.norm
256 avgt 4 1044.103 ± 18.772 B/op
ArrayListTest.testWithInitialCapacity:·gc.churn.PS_Survivor_Space
256 avgt 4 0.050 ± 0.093 MB/sec
ArrayListTest.testWithInitialCapacity:·gc.churn.PS_Survivor_Space.norm
256 avgt 4 0.108 ± 0.168 B/op
ArrayListTest.testWithInitialCapacity:·gc.count
256 avgt 4 410.000 counts
ArrayListTest.testWithInitialCapacity:·gc.time
256 avgt 4 213.000 ms
ArrayListTest.testWithoutInitialCapacity
256 avgt 4 2462.095 ± 469.356 ns/op
ArrayListTest.testWithoutInitialCapacity:·gc.alloc.rate
256 avgt 4 1616.472 ± 305.481 MB/sec
ArrayListTest.testWithoutInitialCapacity:·gc.alloc.rate.norm
256 avgt 4 4520.000 ± 0.001 B/op
ArrayListTest.testWithoutInitialCapacity:·gc.churn.PS_Eden_Space
256 avgt 4 1619.863 ± 259.328 MB/sec
ArrayListTest.testWithoutInitialCapacity:·gc.churn.PS_Eden_Space.norm
256 avgt 4 4529.933 ± 138.807 B/op
ArrayListTest.testWithoutInitialCapacity:·gc.churn.PS_Survivor_Space
256 avgt 4 0.155 ± 0.167 MB/sec
ArrayListTest.testWithoutInitialCapacity:·gc.churn.PS_Survivor_Space.norm
256 avgt 4 0.432 ± 0.418 B/op
ArrayListTest.testWithoutInitialCapacity:·gc.count
256 avgt 4 427.000 counts
ArrayListTest.testWithoutInitialCapacity:·gc.time
256 avgt 4 226.000 ms
{code}
> Make ArrayList creation with initial capacity when size is fixed
> ----------------------------------------------------------------
>
> Key: CALCITE-3878
> URL: https://issues.apache.org/jira/browse/CALCITE-3878
> Project: Calcite
> Issue Type: Improvement
> Components: core
> Affects Versions: 1.22.0
> Reporter: neoremind
> Priority: Minor
> Labels: pull-request-available
> Time Spent: 40m
> Remaining Estimate: 0h
>
> I find many places in Calcite where _new ArrayList<>()_ is used, if the list
> is expected to be immutable or not resizing, it is always a good manner to
> create with initial capacity, better for memory usage and performance.
> I search all occurrences, focus on the core module, to make it safe, I only
> update local variables with fixed size and not working in recursive method.
> If the local variable reference goes out of scope, if resizing is needed,
> things will work normally as well, so no side effect, but for the "escaping"
> case, I am very conservative and do not change them.
>
>
>
--
This message was sent by Atlassian Jira
(v8.3.4#803005)