0306 ~ 0319


# 0306 ~ 0319

# 0309 - JIT(Just-In Time compiler) ์ปดํŒŒ์ผ๋Ÿฌ๋ž€?

์ž๋ฐ”๋Š” ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•ด์„œ ๋ฐ”์ดํŠธ์ฝ”๋“œ๋กœ ์ปดํŒŒ์ผํ•˜๋Š” ๊ณผ์ •๊ณผ ๋ฐ”์ดํŠธ์ฝ”๋“œ๋ฅผ ์ธํ„ฐํ”„๋ฆฌํŠธํ•˜๋Š” ๊ณผ์ •์„ ๊ฑฐ์ณ์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ปดํŒŒ์ผ ๊ณผ์ •๋งŒ ํ•„์š”ํ•œ ๋‹ค๋ฅธ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด๋ณด๋‹ค ๋Š๋ฆฌ๋‹ค. ๊ฑฐ๊ธฐ์— ๋”ํ•˜์—ฌ ์ธํ„ฐํ”„๋ฆฌํ„ฐ๋Š” ์ปดํŒŒ์ผ๋Ÿฌ๋ณด๋‹ค ๋Š๋ฆฌ๊ธฐ ๋•Œ๋ฌธ์— ์„ฑ๋Šฅ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ๋ฐ–์— ์—†๋‹ค.

์ธํ„ฐํ”„๋ฆฌํ„ฐ ๋ฐฉ์‹์˜ ๋‹จ์ ์„ ๋ณด์™„ํ•˜๊ธฐ ์œ„ํ•ด ๋„์ž…๋๋‹ค. JIT ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ์‹คํ–‰ ์‹œ์ ์— ์ธํ„ฐํ”„๋ฆฌํ„ฐ ๋ฐฉ์‹์œผ๋กœ ๊ธฐ๊ณ„์–ด ์ฝ”๋“œ๋ฅผ ์ƒ์„ฑํ•  ๋•Œ ์ž์ฃผ ์‚ฌ์šฉ๋˜๋Š” ๋ฉ”์†Œ๋“œ์˜ ๊ฒฝ์šฐ ์ปดํŒŒ์ผํ•˜๊ณ  ๊ธฐ๊ณ„์–ด๋ฅผ ์บ์‹ฑํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ํ•ด๋‹น ๋ฉ”์†Œ๋“œ๊ฐ€ ์—ฌ๋Ÿฌ ๋ฒˆ ํ˜ธ์ถœํ•  ๋•Œ ๋งค๋ฒˆ ํ•ด์„ํ•˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•œ๋‹ค.

# [ JIT ์ปดํŒŒ์ผ๋Ÿฌ ๋™์ž‘ ๋ฐฉ์‹ ]

JIT ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ์‹คํ–‰ ์‹œ์ ์—์„œ๋Š” ์ธํ„ฐํ”„๋ฆฌํ„ฐ์™€ ๊ฐ™์ด ๊ธฐ๊ณ„์–ด ์ฝ”๋“œ๋ฅผ ์ƒ์„ฑํ•˜๋ฉด์„œ ํ•ด๋‹น ์ฝ”๋“œ๊ฐ€ ์ปดํŒŒ์ผ ๋Œ€์ƒ์ด ๋˜๋ฉด ์ปดํŒŒ์ผํ•˜๊ณ  ๊ทธ ์ฝ”๋“œ๋ฅผ ์บ์‹ฑํ•œ๋‹ค. JIT ์ปดํŒŒ์ผ์€ ์ฝ”๋“œ๊ฐ€ ์‹คํ–‰๋˜๋Š” ๊ณผ์ •์— ์‹ค์‹œ๊ฐ„์œผ๋กœ ์ผ์–ด๋‚˜๋ฉฐ, ์ „์ฒด ์ฝ”๋“œ์˜ ํ•„์š”ํ•œ ๋ถ€๋ถ„๋งŒ ๋ณ€ํ™˜ํ•œ๋‹ค. ๊ธฐ๊ณ„์–ด๋กœ ๋ณ€ํ™˜๋œ ์ฝ”๋“œ๋Š” ์บ์‹œ์— ์ €์žฅ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์žฌ์‚ฌ์šฉ ์‹œ ์ปดํŒŒ์ผ์„ ๋‹ค์‹œ ํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค.

  • JIT ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์ปดํŒŒ์ผํ•˜๋Š” ์กฐ๊ฑด์€ ์–ผ๋งˆ๋‚˜ ์ž์ฃผ ์ฝ”๋“œ๊ฐ€ ์‹คํ–‰๋๋Š”๊ฐ€ ์ด๋‹ค. ์ผ์ •ํ•œ ํšŸ์ˆ˜๋งŒํผ ์‹คํ–‰๋˜๊ณ  ๋‚˜๋ฉด ์ปดํŒŒ์ผ ์ž„๊ณ„์น˜์— ๋„๋‹ฌํ•˜๊ณ  ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ์ปดํŒŒ์ผํ•˜๊ธฐ์— ์ถฉ๋ถ„ํ•œ ์ •๋ณด๊ฐ€ ์Œ“์˜€๋‹ค๊ณ  ์ƒ๊ฐํ•œ๋‹ค.
  • ์ž„๊ณ„์น˜๋Š” ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋œ ํšŸ์ˆ˜, ๋ฉ”์„œ๋“œ์˜ ๋ฃจํ”„๋ฅผ ๋น ์ ธ๋‚˜์˜ค๊ธฐ๊นŒ์ง€ ๋ˆ ํšŸ์ˆ˜ ๋‘ ๊ฐœ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•œ๋‹ค. ์ด ๋‘ ์ˆ˜์˜ ํ•ฉ๊ณ„๋ฅผ ํ™•์ธํ•˜๊ณ  ๋ฉ”์„œ๋“œ๊ฐ€ ์ปดํŒŒ์ผ๋  ์ž๊ฒฉ์ด ์žˆ๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •ํ•œ๋‹ค. ์ž๊ฒฉ์ด ์žˆ๋‹ค๋ฉด ๋ฉ”์„œ๋“œ๋Š” ์ปดํŒŒ์ผ๋˜๊ธฐ ์œ„ํ•ด ํ์—์„œ ๋Œ€๊ธฐํ•œ๋‹ค. ์ดํ›„ ๋ฉ”์„œ๋“œ๋“ค์€ ์ปดํŒŒ์ผ ์Šค๋ ˆ๋“œ์— ์˜ํ•ด ์ปดํŒŒ์ผ๋œ๋‹ค.
  • ์•„์ฃผ ์˜ค๋žซ๋™์•ˆ ๋Œ์•„๊ฐ€๋Š” ๋ฃจํ”„ ๋ฌธ์˜ ์นด์šดํ„ฐ๊ฐ€ ์ž„๊ณ„์น˜๋ฅผ ๋„˜์–ด๊ฐ€๋ฉด ํ•ด๋‹น ๋ฃจํ”„๋Š” ์ปดํŒŒ์ผ ๋Œ€์ƒ์ด ๋œ๋‹ค. JVM์€ ๋ฃจํ”„๋ฅผ ์œ„ํ•œ ์ฝ”๋“œ์˜ ์ปดํŒŒ์ผ์ด ๋๋‚˜๋ฉด ๋ฃจํ”„๊ฐ€ ๋‹ค์‹œ ๋ฐ˜๋ณต๋  ๋•Œ๋Š” ์ฝ”๋“œ๋ฅผ ์ปดํŒŒ์ผ๋œ ์ฝ”๋“œ๋กœ ๊ต์ฒดํ•˜๊ณ  ๋” ๋น ๋ฅด๊ฒŒ ์‹คํ–‰๋œ๋‹ค. ์ด ๊ต์ฒด ๊ณผ์ •์„ "์Šคํƒ ์ƒ์˜ ๊ต์ฒด(on-stack replacement, ORS)"๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.

์ปดํŒŒ์ผ ์ž„๊ณ„์น˜(Compile Threshold) : JIT ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ๋ฉ”์†Œ๋“œ๊ฐ€ ์ž์ฃผ ์‚ฌ์šฉ๋˜๋Š”์ง€ ์ฒดํฌํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์ปดํŒŒ์ผ ์ž„๊ณ„์น˜๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. JIT ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ๋‚ด๋ถ€์ ์œผ๋กœ ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋  ๋•Œ๋งˆ๋‹ค ํ˜ธ์ถœ ํšŸ์ˆ˜๋ฅผ ์นด์šดํŒ…ํ•˜๊ณ  ๊ทธ ํšŸ์ˆ˜๊ฐ€ ํŠน์ • ์ˆ˜์น˜๋ฅผ ์ดˆ๊ณผํ•  ๋•Œ ์บ์‹ฑํ—ค์„œ ์ดํ›„์—๋Š” JIT ์ปดํŒŒ์ผ์ด ํŠธ๊ธฐ๋Ÿฌ๋œ๋‹ค.

# [ ์ด์  ]

์ผ๋ฐ˜์ ์ธ ์ธํ„ฐํ”„๋ฆฌํ„ฐ ์–ธ์–ด๋Š” ๋ฐ”์ดํŠธ์ฝ”๋“œ๋‚˜ ์†Œ์Šค์ฝ”๋“œ๋ฅผ ์ตœ์ ํ™” ๊ณผ์ •์ด ์—†์ด ๋ฒˆ์—ญํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์„ฑ๋Šฅ์ด ๋‚ฎ๋‹ค. ๋ฐ˜๋ฉด ์ •์ ์œผ๋กœ ์ปดํŒŒ์ผํ•˜๋Š” ์–ธ์–ด๋Š” ์‹คํ–‰ ์ „์— ๋ฌด์กฐ๊ฑด ์ปดํŒŒ์ผ์„ ํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋‹ค์–‘ํ•œ ํ”Œ๋žซํผ์— ๋งž๊ฒŒ ์ปดํŒŒ์ผ์„ ํ•˜๋ ค๋ฉด ์‹œ๊ฐ„์ด ์˜ค๋ž˜ ๊ฑธ๋ฆฐ๋‹ค. JIT ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ์‹คํ–‰ ๊ณผ์ •์—์„œ ์ปดํŒŒ์ผ์„ ํ•  ์ˆ˜ ์žˆ๊ธฐ ์œ„ํ•ด ๋งŒ๋“ค์–ด์กŒ๋‹ค. JIT ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ์ •์  ์ปดํŒŒ์ผ๋Ÿฌ๋งŒํผ ๋น ๋ฅด๋ฉด์„œ ์ธํ„ฐํ”„๋ฆฌํ„ฐ ์–ธ์–ด์˜ ๋น ๋ฅธ ์‘๋‹ต์†๋„๋ฅผ ์ถ”๊ตฌํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•œ๋‹ค. ๋˜ํ•œ ๋ฐ”์ดํŠธ์ฝ”๋“œ ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์‹œ๊ฐ„์ด ๋งŽ์ด ์†Œ์š”๋˜๋Š” ์ตœ์ ํ™”๋ฅผ ๋ฏธ๋ฆฌ ํ•ด์ฃผ๊ธฐ ๋•Œ๋ฌธ์— ๋ฐ”์ดํŠธ ์ฝ”๋“œ์—์„œ ๊ธฐ๊ณ„์–ด ๋ฒˆ์—ญ์€ ํ›จ์”ฌ ๋น ๋ฅด๊ฒŒ ์ง„ํ–‰๋  ์ˆ˜ ์žˆ์–ด ์„ฑ๋Šฅ์ƒ์˜ ์ด์ ์ด ์žˆ๋‹ค.


# 0310 - ์ž๋ฐ”์—์„œ ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ

Java 8์—์„œ๋Š” ์ปฌ๋ ‰์…˜ ๋ฐ์ดํ„ฐ ์ŠคํŠธ๋ฆผ์œผ๋กœ ์‰ฝ๊ฒŒ ๋ฐ˜๋ณตํ•  ์ˆ˜ ์žˆ๋Š” Stream API๋ฅผ ๋„์ž…ํ–ˆ๋‹ค.

# ์ˆœ์ฐจ ์ŠคํŠธ๋ฆผ

  • ๋‹จ์ผ ์Šค๋ ˆ๋“œ ์ฒ˜๋ฆฌ
List<Integer> listOfNumbers = Arrays.asList(1, 2, 3, 4);
listOfNumbers.stream().forEach(number ->
    System.out.println(number + " " + Thread.currentThread().getName())
);
1
2
3
4
์‹คํ–‰๊ฒฐ๊ณผ :
1 main
2 main
3 main
4 main
1
2
3
4
5

# ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ

List<Integer> listOfNumbers = Arrays.asList(1, 2, 3, 4);
listOfNumbers.parallelStream().forEach(number ->
        System.out.println(number + " " + Thread.currentThread().getName())
);
1
2
3
4
4 ForkJoinPool.commonPool-worker-3
2 ForkJoinPool.commonPool-worker-5
1 ForkJoinPool.commonPool-worker-7
3 main
1
2
3
4

# [ Fork-Join Framework ]

๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ์€ Fork-Join ํ”„๋ ˆ์ž„์›Œํฌ์™€ common pool of worker ์Šค๋ ˆ๋“œ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. fork-join ํ”„๋ ˆ์ž„์›Œํฌ๋Š” ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ๊ฐ„์˜ ์ž‘์—… ๊ด€๋ฆฌ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด Java7์˜ java.util.concurrent์— ์ถ”๊ฐ€๋˜์—ˆ๋‹ค.

# [ ์†Œ์Šค ๋ถ„ํ•  ]

fork-join ํ”„๋ ˆ์ž„์›Œํฌ๋Š” worker ์Šค๋ ˆ๋“œ๊ฐ„์— ์†Œ์Šค ๋ฐ์ดํ„ฐ๋ฅผ ๋ถ„ํ• ํ•˜๊ณ  ์ž‘์—… ์™„๋ฃŒ์‹œ ์ฝœ๋ฐฑ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.

List<Integer> listOfNumbers = Arrays.asList(1, 2, 3, 4);
int sum = listOfNumbers.parallelStream().reduce(5, Integer::sum);
assertThat(sum).isNotEqualTo(15);
1
2
3

์ˆœ์ฐจ์ŠคํŠธ๋ฆผ์—์„œ์˜ ์ž‘์—… ๊ฒฐ๊ณผ๋Š” 15์ด๋‚˜, ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ์‹œ ์‹ค์ œ ๋ชจ๋“  ์›Œ์ปค ์Šค๋ ˆ๋“œ์—์„œ ์ˆซ์ž 5๊ฐ€ ํ•ฉ์‚ฐ๋œ๋‹ค.

List<Integer> listOfNumbers = Arrays.asList(1, 2, 3, 4);
int sum = listOfNumbers.parallelStream().reduce(0, Integer::sum) + 5;
assertThat(sum).isEqualTo(15);
1
2
3

๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ ์™ธ๋ถ€์— ์ˆซ์ž 5๋ฅผ ๋”ํ•˜๋Š” ์ž‘์—…์„ ํ†ตํ•ด ๋ฌธ์ œ ํ•ด๊ฒฐ

# [ common thread pool ]

common ์Šค๋ ˆ๋“œํ’€์˜ ์Šค๋ ˆ๋“œ ์ˆ˜๋Š” ํ”„๋กœ์„ธ์„œ ์ฝ”์–ด ์ˆ˜์™€ ๊ฐ™๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ API๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด JVM ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ „๋‹ฌํ•˜์—ฌ ์‚ฌ์šฉํ•  ์Šค๋ ˆ๋“œ์ˆ˜๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

-D java.util.concurrent.ForkJoinPool.common.parallelism=4
1

์ด๊ฒƒ์€ ์ „์—ญ์œผ๋กœ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์ด๋ฉฐ, common thread pool์„ ์‚ฌ์šฉํ•˜๋Š” ๋ชจ๋“  ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ ๋ฐ ๊ธฐํƒ€ ๋ชจ๋“  fork-join ์ž‘์—…์— ์˜ํ–ฅ์„ ๋ฏธ์นœ๋‹ค. ์‚ฌ์šฉ์‹œ ์ฃผ์˜

# [ custom thread pool ]

List<Integer> listOfNumbers = Arrays.asList(1, 2, 3, 4);
ForkJoinPool customThreadPool = new ForkJoinPool(4);
int sum = customThreadPool.submit(
    () -> listOfNumbers.parallelStream().reduce(0, Integer::sum)).get();
customThreadPool.shutdown();
assertThat(sum).isEqualTo(10);
1
2
3
4
5
6

# [ ์„ฑ๋Šฅ์ƒ์˜ ์˜ํ–ฅ ]

๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ๋Š” ๋‹ค์ค‘ ์ฝ”์–ด๋ฅผ ์˜จ์ „ํžˆ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋‹ค์ค‘ ์Šค๋ ˆ๋“œ ๊ด€๋ฆฌ, ๋ฉ”๋ชจ๋ฆฌ ์ง€์—ญ์„ฑ, ์†Œ์Šค ๋ถ„ํ•  ๋ฐ ๊ฒฐ๊ณผ ๋ณ‘ํ•ฉ์— ๋Œ€ํ•œ ์˜ค๋ฒ„ํ—ค๋“œ๋„ ๊ณ ๋ คํ•ด์•ผ ํ•œ๋‹ค.

# [ ์˜ค๋ฒ„ํ—ค๋“œ(Overhead) ]

IntStream.rangeClosed(1, 100).reduce(0, Integer::sum);
IntStream.rangeClosed(1, 100).parallel().reduce(0, Integer::sum);
1
2

์ด๋Ÿฐ ๊ฐ„๋‹จํ•œ ํ•ฉ๊ณ„์—์„œ ์ˆœ์ฐจ ์ŠคํŠธ๋ฆผ์„ ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ์œผ๋กœ ๋ณ€ํ™˜ํ•˜๋ฉด ์„ฑ๋Šฅ์ด ์ €ํ•˜๋œ๋‹ค. image

๊ทธ ์ด์œ ๋Š” ๋•Œ๋•Œ๋กœ ์Šค๋ ˆ๋“œ, ์†Œ์Šค ๋ฐ ๊ฒฐ๊ณผ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ์˜ค๋ฒ„ํ—ค๋“œ๊ฐ€ ์‹ค์ œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค cost๊ฐ€ ๋งŽ์ด ๋“œ๋Š” ์ž‘์—…์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

# [ ๋ถ„ํ•  ๋น„์šฉ(Splitting Costs) ]

๋ฐ์ดํ„ฐ ์†Œ์Šค(๊ฐ๊ฐ์˜ ์ŠคํŠธ๋ฆผ ๋‹จ์œ„)๋ฅผ ๊ท ๋“ฑํ•˜๊ฒŒ ๋ถ„ํ• ํ•˜๋Š” ๊ฒƒ์€ ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๋Š”๋ฐ ํ•„์š”ํ•œ cost์ด์ง€๋งŒ ์ผ๋ถ€ ๋ฐ์ดํ„ฐ ์†Œ์Šค๋Š” ๋‹ค๋ฅธ ๋ฐ์ดํ„ฐ ์†Œ์Šค๋ณด๋‹ค ๋” ์ž˜๋ถ„ํ•  ๋œ๋‹ค.

private static final List<Integer> arrayListOfNumbers = new ArrayList<>();
private static final List<Integer> linkedListOfNumbers = new LinkedList<>();

// ํ•ด๋‹น ์ฝ”๋“œ๋กœ 100๋งŒ์˜ ์ •์ˆ˜ ๋ชฉ๋ก์„ ์ดˆ๊ธฐํ™”ํ•ฉ๋‹ˆ๋‹ค.
static {
    IntStream.rangeClosed(1, 1_000_000).forEach(i -> {
        arrayListOfNumbers.add(i);
        linkedListOfNumbers.add(i);
    });
}
1
2
3
4
5
6
7
8
9
10
arrayListOfNumbers.stream().reduce(0, Integer::sum)
arrayListOfNumbers.parallelStream().reduce(0, Integer::sum);
linkedListOfNumbers.stream().reduce(0, Integer::sum);
linkedListOfNumbers.parallelStream().reduce(0, Integer::sum);
1
2
3
4

์•„๋ž˜์˜ ๊ฒฐ๊ณผ๋Š” ์ˆœ์ฐจ ์ŠคํŠธ๋ฆผ์„ ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ์œผ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๊ฒƒ์ด ArrayList์— ๋Œ€ํ•ด์„œ๋งŒ ์„ฑ๋Šฅ ์ด์ ์„ ๊ฐ€์ ธ์˜จ๋‹ค๋Š” ๊ฒƒ์„ ๋ณด์—ฌ์ค€๋‹ค. image

LinkedList๋Š” ๋ณ‘๋ ฌ์ฒ˜๋ฆฌ๋ฅผ ํ–ˆ์ง€๋งŒ Scoredhk Error ๊ฐ’์ด ์ฆ๊ฐ€, ๋ฐ˜๋ฉด ArrayList๋Š” Score์™€ Error ๊ฐ’์ด ๊ฐ์†Œ

๊ทธ ์ด์œ ๋Š” Array๋ผ๋Š” ํŠน์ง•์ด ์ €๋ ดํ•˜๊ฒŒ ์†Œ์Šค๋ฅผ ๋ถ„ํ• ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ LinkedList์—๋Š” ์ด๋Ÿฌํ•œ ์†์„ฑ์ด ์—†๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. TreeMap๊ณผ HashSet์€ LinkedList๋ณด๋‹ค ์ž˜ ๋ถ„ํ• ๋˜์ง€๋งŒ Array๋งŒํผ์€ ๋ถ„ํ• ๋˜์ง€ ์•ˆํ”๋‹ค.

# [ ๋ณ‘ํ•ฉ ๋น„์šฉ(Merging Costs) ]

๋ณ‘๋ ฌ ๊ณ„์‚ฐ์„ ํ•˜๊ธฐ ์œ„ํ•ด ์†Œ์Šค๋ฅผ ๋ถ„ํ• ํ•  ๋•Œ๋งˆ๋‹ค ๊ฒฐ๊ตญ ๊ฒฐ๊ณผ๋ฅผ ๋ณ‘ํ•ฉํ•ด์•ผ ํ•œ๋‹ค. ์„œ๋กœ ๋‹ค๋ฅธ ๋ณ‘ํ•ฉ ์ž‘์—…์œผ๋กœ sum ๋ฐ grouping์„ ์‚ฌ์šฉํ•˜์—ฌ ์ˆœ์ฐจ ๋ฐ ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ์—์„œ์˜ ์„ฑ๋Šฅ ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰

arrayListOfNumbers.stream().reduce(0, Integer::sum);
arrayListOfNumbers.stream().parallel().reduce(0, Integer::sum);
arrayListOfNumbers.stream().collect(Collectors.toSet());
arrayListOfNumbers.stream().parallel().collect(Collectors.toSet());
1
2
3
4

์•„๋ž˜์˜ ๊ฒฐ๊ณผ๋Š” ์ˆœ์ฐจ ์ŠคํŠธ๋ฆผ์„ ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ์œผ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๊ฒƒ์ด sum ์—ฐ์‚ฐ์— ๋Œ€ํ•ด์„œ๋งŒ ์„ฑ๋Šฅ์ƒ์˜ ์ด์ ์„ ๊ฐ€์ ธ์˜จ๋‹ค๋Š” ๊ฒƒ์„ ๋ณด์—ฌ์ค€๋‹ค. image

๋ณ‘ํ•ฉ ์ž‘์—…์€ reduce์™€ sum๊ณผ ๊ฐ™์€ ์ผ๋ถ€ ์ž‘์—…์˜ ๊ฒฝ์šฐ ์ •๋ง ๊ฐ€๋ณ๊ฒŒ ๋™์ž‘ํ•˜์ง€๋งŒ set๊ณผ map๊ณผ ๊ฐ™์€ ํ˜•ํƒœ๋กœ ๊ทธ๋ฃนํ™”ํ•˜๋Š” ๊ฒƒ์€ ๋ณ‘ํ•ฉ ์ž‘์—…์ด ์ƒ๋‹นํžˆ ๋ฌด๊ฒ๊ฒŒ ๋™์ž‘ํ•  ์ˆ˜ ์žˆ๋‹ค.

# [ Memory Locality ]

์ตœ์‹  ์ปดํ“จํ„ฐ๋Š” ์ •๊ตํ•œ ๋ฉ€ํ‹ฐ ๋ ˆ๋ฒจ ์บ์‹œ๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์ž์ฃผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ํ”„๋กœ์„ธ์„œ ๊ฐ€๊นŒ์ด์— ์ €์žฅํ•œ๋‹ค. ์„ ํ˜• ๋ฉ”๋ชจ๋ฆฌ ์—‘์„ธ์Šค ํŒจํ„ด์ด ๊ฐ์ง€๋˜๋ฉด ํ•˜๋“œ์›จ์–ด๋Š” ๊ณง ํ•„์š”ํ•  ๊ฒƒ์ด๋ผ๋Š” ๊ฐ€์ • ํ•˜์— ๋‹ค์Œ ๋ฐ์ดํ„ฐ ๋ผ์ธ์„ ๋ฏธ๋ฆฌ ๊ฐ€์ ธ์˜จ๋‹ค.(prefetch)
๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ๋Š” ํ”„๋กœ์„ธ์„œ ์ฝ”์–ด๊ฐ€ ์œ ์šฉํ•œ ์ž‘์—…์„ ์ง€์†์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์„ ๋•Œ ์„ฑ๋Šฅ ์ด์ ์„ ๊ฐ€์ ธ์˜จ๋‹ค. cache miss๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๋Š” ๊ฒƒ์€ ์œ ์šฉํ•œ ์ž‘์—…์ด ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ฉ”๋ชจ๋ฆฌ ๋Œ€์—ญํญ์„ ์ œํ•œ ์š”์†Œ๋กœ ๊ณ ๋ คํ•ด์•ผ ํ•œ๋‹ค.
ํ•˜๋‚˜๋Š” primitive ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜๊ณ  ๋‹ค๋ฅธ ํ•˜๋‚˜๋Š” wrapper ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜๋Š” ๋‘๊ฐœ์˜ ๋ฐฐ์—ด์„ ์‚ฌ์šฉํ•˜์—ฌ ์ด๋ฅผ ์ฆ๋ช…ํ•˜๋Š” ์˜ˆ์ด๋‹ค.

private static final int[] intArray = new int[1_000_000];
private static final Integer[] integerArray = new Integer[1_000_000];

static {
    IntStream.rangeClosed(1, 1_000_000).forEach(i -> {
        intArray[i-1] = i;
        integerArray[i-1] = i;
    });
}
1
2
3
4
5
6
7
8
9

๋‘ ๋ฐฐ์—ด์—์„œ ์ˆœ์ฐจ ๋ฐ ๋ณ‘๋ ฌ reduce ์ž‘์—…์— ๋Œ€ํ•œ ์„ฑ๋Šฅ ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•ด๋ณด์ž

Arrays.stream(intArray).reduce(0, Integer::sum);
Arrays.stream(intArray).parallel().reduce(0, Integer::sum);
Arrays.stream(integerArray).reduce(0, Integer::sum);
Arrays.stream(integerArray).parallel().reduce(0, Integer::sum);
1
2
3
4

์•„๋ž˜์˜ ๊ฒฐ๊ณผ ์ˆœ์ฐจ ์ŠคํŠธ๋ฆผ์„ ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ์œผ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๊ฒƒ์ด primitive ๋ฐฐ์—ด์„ ์‚ฌ์šฉํ•  ๋•Œ ์•ฝ๊ฐ„ ๋” ๋งŽ์€ ์„ฑ๋Šฅ ์ด์ ์„ ๊ฐ€์ ธ์˜จ๋‹ค.

# [ NQ๋ชจ๋ธ ]

NQ๋ชจ๋ธ์—์„œ๋Š” N์€ ์†Œ์Šค ๋ฐ์ดํ„ฐ์˜ ์š”์†Œ ์ˆ˜๋ฅผ ๋‚˜ํƒ€๋‚ด๊ณ  Qs๋Š” ๋ฐ์ดํ„ฐ ์š”์†Œ๋‹น ์ˆ˜ํ–‰๋œ ๊ณ„์‚ฐ์˜ ์–‘์„ ๋‚˜ํƒ€๋‚ธ๋‹ค.
N * Q์˜ ๊ณฑ์ด ํด์ˆ˜๋ก ๋ณ‘๋ ฌํ™”๋กœ ์ธํ•ด ์„ฑ๋Šฅ ํ–ฅ์ƒ์˜ ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์•„์ง„๋‹ค. ์ˆซ์ž ํ•ฉ์‚ฐ๊ณผ ๊ฐ™์ด ์‚ฌ์†Œํ•œ Q๊ฐ€ ์žˆ๋Š” ๋ฌธ์ œ์˜ ๊ฒฝ์šฐ ๊ฒฝํ—˜์ƒ N์€ 10,000 ๋ณด๋‹ค ์ปค์•ผ ํ•œ๋‹ค.


# 0317 - JMH(Java Microbenchmark Harness)

JMH๋Š” JVM ์œ„์—์„œ ๋™์ž‘ํ•˜๋Š” ์ฝ”๋“œ์˜ ์„ฑ๋Šฅ์„ ์ธก์ •ํ•ด์ฃผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋‹ค. ์‚ฌ์‹ค ์ •ํ™•ํ•œ ์„ฑ๋Šฅ์„ ์ธก์ •ํ•˜๊ธฐ ์œ„ํ•ด์„  ์‚ฌ์šฉํ•˜๋Š” ๊ฐ€์ƒ๋จธ์‹ ์˜ ์ œํ’ˆ์— ๋”ฐ๋ผ Hot-Spot VM ์˜ค๋ฒ„ํ—ค๋“œ๋‚˜ GC ์˜ค๋ฒ„ํ—ค๋“œ์™€ ๊ฐ™์€ ์ฝ”๋“œ๊ฐ€ ๋™์ž‘ํ•จ์— ์žˆ์–ด์„œ ์‹œ์Šคํ…œ์˜ ์˜ค๋ฒ„ํ—ค๋“œ๊นŒ์ง€ ๊ณ ๋ คํ•ด์„œ ์ธก์ •ํ•ด์•ผ ํ•˜์ง€๋งŒ ๊ฐ„๋‹จํ•œ ์ฝ”๋“œ์ด๊ฑฐ๋‚˜ ์—ฌ๋Ÿฌ ์ฝ”๋“œ์˜ ์ƒ๋Œ€์  ์„ฑ๋Šฅ์„ ์ธก์ •ํ•  ๋•Œ์—๋Š” ๊ฐ„๋‹จํžˆ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” JMH๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

์ฐธ๊ณ ๋กœ, JMH๋Š” Oracle์˜ JIT Compiler ๊ฐœ๋ฐœ์ž๊ฐ€ ๋งŒ๋“  ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— ํƒ€ ๋ฒค์น˜๋งˆํฌ ํ”„๋ ˆ์ž„์›Œํฌ๋ณด๋‹ค ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋‹ค.

# [ ์‚ฌ์šฉ๋ฐฉ๋ฒ• ]

plugins {
  id "me.champeau.jmh" version "0.7.0"
}

dependencies {
    jmh 'org.openjdk.jmh:jmh-core:0.9'
    jmh 'org.openjdk.jmh:jmh-generator-annprocess:0.9'
}
1
2
3
4
5
6
7
8
@State(Scope.Thread)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
public class LoopTest {

    final LIMIT_COUNT = 10000;
    final List<Integer> array = new ArrayList<>();

	@Setup
	public void init() {
        // ์„ฑ๋Šฅ ์ธก์ • ์ „ ์‚ฌ์ „์— ํ•„์š”ํ•œ ์ž‘์—…
        for(int i = 0; i < LIMIT_COUNT; i++) {
            array.add(i);
        }
	}

	@Benchmark
	public void originLoopWithGetSize() {
        // ์„ฑ๋Šฅ์„ ์ธก์ •ํ•  ์ฝ”๋“œ ์ž‘์„ฑ
        int size = array.size();
        for(int i = 0; i < size; i++) {
            processor(i);
        }
	}

    Integer temp = 0;
    public void processor(Integer i) {
        temp = i;
    }

    public static void main(String[] args) throws IOException, RunnerException {
        Options opt = new OptionsBuilder()
                .include(LoopTest.class.getSimpleName())
                .warmupIterations(10)           // ์‚ฌ์ „ ํ…Œ์ŠคํŠธ ํšŸ์ˆ˜
                .measurementIterations(10)      // ์‹ค์ œ ์ธก์ • ํšŸ์ˆ˜
                .forks(1)                       // 
                .build();
        new Runner(opt).run();                  // ๋ฒค์น˜๋งˆํ‚น ์‹œ์ž‘
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# Run complete. Total time: 00:01:43

Benchmark                       Mode  Cnt  Score   Error  Units
LoopTest.forEach                avgt   10  0.990 ยฑ 0.096  ms/op
LoopTest.forEachByJdk8          avgt   10  0.703 ยฑ 0.160  ms/op
LoopTest.forEachByStream        avgt   10  0.561 ยฑ 0.057  ms/op
LoopTest.originLoop             avgt   10  0.634 ยฑ 0.117  ms/op
LoopTest.originLoopWithGetSize  avgt   10  0.876 ยฑ 0.093  ms/op
1
2
3
4
5
6
7
8

# 0319 - KPI/SLI/SLO/SLA

# 1. KPI(Key Performance Indicator)

KPI(Key Performance Indicator)๋Š” ์„ฑ๊ณต์„ ์ธก์ •ํ•˜๋Š”๋ฐ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ๋Š” ๋ฉ”ํŠธ๋ฆญ์ด๋‹ค.

  • KPI๋Š” ๋ชฉํ‘œ๋‚˜ ๋ชฉ์ ๊ณผ๋Š” ๋‹ค๋ฅธ, ๋ชฉํ‘œ๋ฅด๋ฅด ๋‹ฌ์„ฑํ•˜๋Š” ๊ณผ์ • ์ค‘์— ์žˆ๋Š”์ง€ ์ธก์ •ํ•˜๋Š” ๋ฉ”ํŠธ๋ฆญ์ด๋‹ค. ๋”ฐ๋ผ์„œ ์ˆ˜๋ฐ˜ํ•˜๋Š” ๋ชฉํ‘œ๊ฐ€ ํ•„์š”ํ•˜๋‹ค. ๋˜ํ•œ, KPI๋ฅผ ๋ชจ๋‹ˆํ„ฐ๋งํ•˜๋Š” ๊ฒƒ์€ ๋ชฉํ‘œ๋ฅผ ๋‹ฌ์„ฑํ•˜๊ธฐ ์œ„ํ•ด ํ•„์ˆ˜์ ์ด๋‹ค.
  • SMART ๋ฒ•์น™
    • Specific : KPI๋Š” ๊ตฌ์ฒด์ ์ด์–ด์•ผ ํ•œ๋‹ค.
    • Measurable : ๋ชจ๋‹ˆํ„ฐ๋งํ•˜๊ธฐ ์œ„ํ•ด์„œ KPI๋Š” ์ธก์ • ๊ฐ€๋Šฅํ•ด์•ผ ํ•œ๋‹ค.
    • Acheivable : 100%๋Š” ์„ฑ์ทจํ•˜๊ธฐ ์–ด๋ ต๋‹ค.
    • Relevant : ๊ด€๋ จ์žˆ์ง€ ์•Š์€ KPI๋Š” ๋ชฉํ‘œ ๋‹ฌ์„ฑ์„ ์ด๋Œ์–ด ๋‚ผ ์ˆ˜ ์—†๋‹ค.
    • Time-bound : 99% availble- Per year? Per month? Per day?

# 2. Service Level

Indicators -> Objectives -> Agreement

# [ SLI(Service Level Indicators) ]

: ์„œ๋น„์Šค์˜ ์ธก์ • ๊ฐ€๋Šฅํ•œ ํŠน์„ฑ, A KPI
ex. Availability

SLI๋Š” ์‹œ๊ฐ„์ด ์ •ํ•ด์ง€๊ณ  ์ธก์ • ๊ฐ€๋Šฅํ•ด์•ผ ํ•œ๋‹ค.

# [ SLO(Service Level Objectives) ]

: ์ฃผ์–ด์ง„ SLI๋กœ ์„ฑ์ทจํ•˜๊ณ  ์‹ถ์€ ๋ชฉํ‘œ๋‚˜ ์ˆซ์ž ์ง€ํ‘œ
ex. 95%, 99% or 99.99% availability

SLO๋Š” ์„ฑ์ทจ ๊ฐ€๋Šฅํ•˜๊ณ  ๊ด€๋ จ ์žˆ์–ด์•ผ ํ•œ๋‹ค.
๊ฐ€๋Šฅํ•œ ๋†’์€ ๋ชฉํ‘œ๋ฅผ ์„ธ์šฐ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ, ์‚ฌ์šฉ์ž๋ฅผ ๋งŒ์กฑ์‹œํ‚ฌ ๋งŒํผ์—์„œ ๊ฐ€๊ฒฉ ํšจ์œจ์ ์ธ SLO๋ฅผ ์„ ํƒํ•ด์•ผํ•œ๋‹ค. SLO๊ฐ€ ๋†’์„์ˆ˜๋ก ๋†’์€ ๋น„์šฉ๊ณผ ๋…ธ๋ ฅ์„ ์ดˆ๋ž˜ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
SLO๋ฅผ ์ตœ์†Œํ™” ํ•ด์•ผํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์ด SLO๋ฅผ ํฌ๊ฒŒ ๋Šฅ๊ฐ€ํ•ด์„œ๋Š” ์•ˆ๋œ๋‹ค.

# [ SLA(Service Level Agreements) ]

: ๋งŒ์•ฝ ์„œ๋น„์Šค๊ฐ€ ํŠน์ • ๊ธฐ๋Œ€๋ฅผ ๋ชป ๋ฏธ์ณค์„ ๋•Œ, ๊ณ ๊ฐ ๋ณด์ƒ์„ ์ œ๊ณตํ•ด์ฃผ๋Š” ๊ตฌ์†๋ ฅ์žˆ๋Š” ๊ณ„์•ฝ
= more restrictive version of SLO

SLA์—๋Š” ๋งŒ์•ฝ ์„œ๋น„์Šค๊ฐ€ ํŠน์ • ๊ฐ€์šฉ์„ฑ์„ ๋˜๋Š” ํผํฌ๋จผ์Šค ๊ธฐ์ค€์„ ์œ ์ง€ํ•˜์ง€ ๋ชปํ–ˆ์„๋•Œ ์ œ๊ณต์ž์— ๊ฐ€ํ•ด์ง€๋Š” penalty์— ๋Œ€ํ•˜์—ฌ ์ ๋Š”๋‹ค. ๊ทธ๋ฆฌ๊ณ  SLA๊ฐ€ ๊นจ์ง€๋ฉด, ๊ณ ๊ฐ์€ ์ œ๊ณต์ž๋กœ๋ถ€ํ„ฐ ๋ณด์ƒ์„ ๋ฐ›๋Š”๋‹ค.

๋ชจ๋“  ์„œ๋น„์Šค์— SLA๊ฐ€ ์žˆ์–ด์•ผ ํ•˜๋Š” ๊ฒƒ์€ ์•„๋‹ˆ์ง€๋งŒ, SLO๋Š” ์žˆ์–ด์•ผ ํ•œ๋‹ค. SLO์˜ ๊ธฐ์ค€์€ SLA๋ณด๋‹ค ๋†’์•„์•ผํ•œ๋‹ค.

image

Last update: March 20, 2023 00:17
Contributors: jaesungahn91