Skip to content

dvktdr78/scheduler_benchmark

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

37 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

์Šค์ผ€์ค„๋Ÿฌ ๋ฒค์น˜๋งˆํฌ ์‹œ์Šคํ…œ

์‹ค์ œ OS ์Šค์ผ€์ค„๋Ÿฌ 3์ข…(Basic Priority, MLFQS, CFS)์„ ๋ชฉํ‘œ ๊ธฐ๋ฐ˜ ํ…Œ์ŠคํŠธ๋กœ ๋น„๊ตํ•˜๋Š” Streamlit ๋ฒค์น˜๋งˆํฌ์ž…๋‹ˆ๋‹ค. (๋ผ์ด๋ธŒ ๋ฐ๋ชจ: http://34.47.105.226:8501)

๋น ๋ฅธ ์š”์•ฝ

  • ์ฐจ๋ณ„์ : ๋ชจ๋“  ์กฐํ•ฉ ๋น„๊ต๊ฐ€ ์•„๋‹Œ ํ…Œ์ŠคํŠธ ๋ชฉํ‘œ๋ณ„๋กœ ์Šค์ผ€์ค„๋Ÿฌ๋ฅผ ์„ ํƒํ•ด ๊ณต์ •์„ฑยท์ •ํ™•์„ฑ์„ ํ™•๋ณด.
  • ๊ตฌ์„ฑ: 18๊ฐœ ํ…Œ์ŠคํŠธ, 6๊ฐœ ์นดํ…Œ๊ณ ๋ฆฌ, 9๊ฐœ ์›Œํฌ๋กœ๋“œ, ์‹ค์‹œ๊ฐ„ ๊ทธ๋ž˜ํ”„/๋ฆฌํฌํŠธ ์ œ๊ณต.
  • ์ƒํƒœ: GCP์—์„œ 24/7 ๊ตฌ๋™, run.sh๋กœ ๋ฐ”๋กœ ์‹คํ–‰ ๊ฐ€๋Šฅ.
  • ํ•ต์‹ฌ ์Šคํ† ๋ฆฌ: time slice ๋ฏธ๊ตฌํ˜„, CFS ์ •๋ฐ€๋„, Basic FIFO ๋“ฑ 6๊ฐœ ํฌ๋ฆฌํ‹ฐ์ปฌ ๋ฒ„๊ทธ๋ฅผ ์žก์œผ๋ฉฐ ์•Œ๊ณ ๋ฆฌ์ฆ˜-์ธก์ •-์„ค๊ณ„ ์ธ์‚ฌ์ดํŠธ๋ฅผ ์ •๋ฆฌ.

๋น ๋ฅธ ์‹คํ–‰

git clone https://github.com/dvktdr78/scheduler_benchmark.git
cd scheduler_benchmark/python_webapp
python3 -m venv venv && source venv/bin/activate
pip install -r requirements.txt
streamlit run app.py   # ๋˜๋Š” ํ”„๋กœ์ ํŠธ ๋ฃจํŠธ์—์„œ ./run.sh

๊ฒฐ๊ณผ ํ•œ๋ˆˆ์— ๋ณด๊ธฐ

๋ชฉํ‘œ/์‹œ๋‚˜๋ฆฌ์˜ค ์Šน์ž/ํŠน์ง• ์ด์œ 
CPU-boundยท์ˆœ์ˆ˜ ์ฒ˜๋ฆฌ๋Ÿ‰ Basic (๊ฐ„๋‹จ) ์˜ค๋ฒ„ํ—ค๋“œ ์ตœ์†Œ, ์˜ˆ์ธก ๊ฐ€๋Šฅํ•œ ์‹คํ–‰ ์ˆœ์„œ
I/O/๋Œ€ํ™”ํ˜• ์‘๋‹ต์„ฑ MLFQS recent_cpu ๊ธฐ๋ฐ˜ ๋™์  ์šฐ์„ ์ˆœ์œ„๋กœ I/O ์šฐ๋Œ€
๊ณต์ •์„ฑยท์ผ๊ด€์„ฑ(P99/CV) CFS vruntime ๊ฐ€์ค‘์น˜ ๊ธฐ๋ฐ˜ ๊ณต์ • ๋ถ„๋ฐฐ, starvation ์—†์Œ
Nice ๊ทน๋‹จ ํ…Œ์ŠคํŠธ MLFQS: ๊ทน๋‹จ์  ํšจ๊ณผ / CFS: ๊ฐ€์ค‘์น˜ ๋น„๋ก€ MLFQS ์šฐ์„ ์ˆœ์œ„ ๊ณต์‹์˜ ํฐ nice ๋ณด์ •, CFS๋Š” weight ๊ธฐ๋ฐ˜ ๊ท ํ˜•
Starvation ์œ„ํ—˜ CFS 0%, Basic ์œ„ํ—˜ ์ •์  ์šฐ์„ ์ˆœ์œ„๋Š” ๊ธฐ์•„ ๊ฐ€๋Šฅ, CFS๋Š” ๊ณต์ •์„ฑ ์œ ์ง€

์ƒ˜ํ”Œ ๊ฒฐ๊ณผ (seed=42)

ํ…Œ์ŠคํŠธ ์ฃผ์š” ์ˆ˜์น˜ (๋‚ฎ์„์ˆ˜๋ก ์ข‹์Œ*) ์Šน์ž
I/O-bound avg_wait Basic 7,603 / MLFQS 7,474 / CFS 7,495 MLFQS
CPU-bound avg_turnaround Basic 22,924 / MLFQS 22,908 / CFS 22,918 MLFQS
๊ณต์ •์„ฑ(mixed, fairness) MLFQS 0.509 (starvation 32%) / CFS 0.999 (starvation 0%) CFS
Nice ํšจ๊ณผ(cpu_time_ratio, log) MLFQS 4,999ร— (starvation 48%) / CFS 199ร— CFS*
P99 ๋Œ€๊ธฐ(consistency_p99) Basic 28,262 / CFS 28,262 / MLFQS 28,338 Basic (P99)

* nice_effect๋Š” CPU ์‹œ๊ฐ„ ๋น„์œจ์ด ๋‚ฎ์„์ˆ˜๋ก ๊ฐ€์ค‘์น˜ ๋น„๋ก€์— ๊ฐ€๊นŒ์›€.
* ๋‹จ์œ„: ticks. ๋ชจ๋“  ํ…Œ์ŠคํŠธ๋Š” ์ •์˜๋œ thread_count, max_ticks, seed=42 ๊ทธ๋Œ€๋กœ ์‹คํ–‰.

์ „์ฒด ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ (seed=42)

์ผ๋ฐ˜ยท์‹ค์ œ ์›Œํฌ๋กœ๋“œ

ํ…Œ์ŠคํŠธ ๋ฉ”ํŠธ๋ฆญ ์Šน์ž ํ•ต์‹ฌ ์ˆ˜์น˜
์ผ๋ฐ˜ ํ˜ผํ•ฉ avg_wait Basic 8,085 (MLFQS 9,700 / CFS 10,838)
CPU-bound avg_turnaround MLFQS 22,908 (Basic 22,924 / CFS 22,918)
I/O-bound avg_wait MLFQS 7,474 (Basic 7,603 / CFS 7,495)
์›น ์„œ๋ฒ„ avg_turnaround Basic 1,062 (MLFQS 1,065 / CFS 1,082)
๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค avg_turnaround CFS 5,332 (MLFQS 5,338 / Basic 5,381)
๋ฐฐ์น˜ ์ฒ˜๋ฆฌ avg_turnaround MLFQS 25,388 (Basic 25,406 / CFS 25,408)
๊ฒŒ์ž„/์‹ค์‹œ๊ฐ„ avg_wait Basic 8,813 (MLFQS 8,813 / CFS 8,925)

๊ณต์ •์„ฑยท์ผ๊ด€์„ฑยทNice ํšจ๊ณผ

ํ…Œ์ŠคํŠธ ๋ฉ”ํŠธ๋ฆญ ์Šน์ž ํ•ต์‹ฌ ์ˆ˜์น˜
๊ณต์ •์„ฑ (mixed) fairness CFS 0.999 vs MLFQS 0.509 (starvation 32%)
๊ณต์ •์„ฑ (extreme nice) fairness CFS 0.525 vs MLFQS 0.500 (starvation 50%)
Nice ํšจ๊ณผ cpu_time_ratio CFS 199ร— vs MLFQS 4,999ร— (starvation 48%)
์ผ๊ด€์„ฑ (CV) cv_wait CFS 29.6% vs Basic 54.5% / MLFQS 43.3%
์ผ๊ด€์„ฑ (P99) p99_wait Basic 28,262 vs CFS 28,262 / MLFQS 28,338
์ผ๊ด€์„ฑ (worst/avg) worst_ratio CFS 1.40 vs MLFQS 1.59 / Basic 1.87
๊ธฐ์•„ ๋ฐฉ์ง€ starvation_pct CFS 0% vs Basic/MLFQS 48%

ํ™•์žฅ์„ฑ

ํ…Œ์ŠคํŠธ ๋ฉ”ํŠธ๋ฆญ ์Šน์ž ํ•ต์‹ฌ ์ˆ˜์น˜
10 ์Šค๋ ˆ๋“œ context_switches Basic 361 vs MLFQS 644 / CFS 682
100 ์Šค๋ ˆ๋“œ avg_wait Basic 15,183 vs MLFQS 17,836 / CFS 20,188
500 ์Šค๋ ˆ๋“œ avg_wait CFS 34,697 vs Basic 31,696*, MLFQS 34,424* (starvation Basic 76% / MLFQS 48%)

โ€ป *starvation์ด ๋†’์€ ์Šค์ผ€์ค„๋Ÿฌ๋Š” ์Šน์ž ์„ ์ •์—์„œ ์ œ์™ธ๋ฉ๋‹ˆ๋‹ค.

๋ฐ๋ชจ ยท ๊ทธ๋ž˜ํ”„

I/O-bound avg_wait General mixed avg_wait Fairness (mixed) Scalability 10 threads (context switches) Nice effect ratio (log)

ํ•ต์‹ฌ ๋ฒ„๊ทธ/์ธ์‚ฌ์ดํŠธ Top3

  • Time slice ๋ฏธ๊ตฌํ˜„ โ†’ FCFSํ™”: ์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ์— ์„ ์  ๋กœ์ง์„ ๋„ฃ์–ด ์Šค์ผ€์ค„๋Ÿฌ ์ฐจ์ด๋ฅผ ๋ณต์›.
  • CFS vruntime ์ •๋ฐ€๋„ 0: ์ •์ˆ˜ ๋‚˜๋ˆ—์…ˆ ์Šค์ผ€์ผ์„ 1000๋ฐฐ๋กœ ์˜ฌ๋ ค ๊ฐ€์ค‘์น˜ ๋น„๋ก€ ๊ณต์ •์„ฑ์„ ํšŒ๋ณต.
  • Basic FIFO ์˜ค๋ฅ˜: TID ๊ธฐ๋ฐ˜ ์„ ํƒ์„ ํ ์‚ฝ์ž… ์ˆœ์„œ ๊ธฐ๋ฐ˜ FIFO๋กœ ์ˆ˜์ •ํ•ด ํŽธํ–ฅ ์ œ๊ฑฐ.

๐Ÿ“‹ ๋ชฉ์ฐจ

๊ฐœ์š”

ํ”„๋กœ์ ํŠธ ๋ชฉ์ 

์‹ค์ œ ์šด์˜์ฒด์ œ์—์„œ ์‚ฌ์šฉ๋˜๋Š” 3๊ฐ€์ง€ CPU ์Šค์ผ€์ค„๋ง ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ๊ณต์ •ํ•˜๊ฒŒ ๋น„๊ตํ•˜๊ณ , ๊ฐ๊ฐ์˜ ์žฅ๋‹จ์ ์„ ์ •๋Ÿ‰์ ์œผ๋กœ ์ธก์ •ํ•ฉ๋‹ˆ๋‹ค.

์ฃผ์š” ํŠน์ง•

  • โœ… ๋ชฉํ‘œ ๊ธฐ๋ฐ˜ ํ…Œ์ŠคํŠธ: ์Šค์ผ€์ค„๋Ÿฌ์— ์ค‘๋ฆฝ์ ์ธ ๋ชฉํ‘œ๋กœ ํ…Œ์ŠคํŠธ ์ •์˜
  • โœ… ์„ ํƒ์  ๋น„๊ต: ๊ฐ ํ…Œ์ŠคํŠธ๋งˆ๋‹ค ์˜๋ฏธ์žˆ๋Š” ์Šค์ผ€์ค„๋Ÿฌ ์กฐํ•ฉ๋งŒ ๋น„๊ต
  • โœ… ์‹ค์‹œ๊ฐ„ ์‹œ๊ฐํ™”: Streamlit ์›น UI๋กœ ์ฆ‰์‹œ ๊ฒฐ๊ณผ ํ™•์ธ
  • โœ… ๊ฒ€์ฆ๋œ ๊ตฌํ˜„: ๊ฐ ์Šค์ผ€์ค„๋Ÿฌ๋Š” ์‹ค์ œ OS ๊ตฌํ˜„์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ฒ€์ฆ๋จ

๋น„๊ต ๋Œ€์ƒ ์Šค์ผ€์ค„๋Ÿฌ

  1. Basic Priority - ์ •์  ์šฐ์„ ์ˆœ์œ„ ์Šค์ผ€์ค„๋Ÿฌ (Baseline)
  2. MLFQS (64-Queue) - ๋™์  ์šฐ์„ ์ˆœ์œ„, O(1) ์Šค์ผ€์ค„๋ง
  3. CFS - Linux ์ปค๋„์˜ ๊ณต์ •์„ฑ ์Šค์ผ€์ค„๋Ÿฌ

์•„ํ‚คํ…์ฒ˜

๋ชฉํ‘œ ๊ธฐ๋ฐ˜ ํ…Œ์ŠคํŠธ ์„ค๊ณ„

๊ธฐ์กด์˜ "๋ชจ๋“  ํ…Œ์ŠคํŠธ์—์„œ 3๊ฐœ ์Šค์ผ€์ค„๋Ÿฌ๋ฅผ ํ•ญ์ƒ ๋น„๊ต" ๋ฐฉ์‹ ๋Œ€์‹ , ๊ฐ ํ…Œ์ŠคํŠธ์˜ ๋ชฉํ‘œ์— ๋งž๋Š” ์Šค์ผ€์ค„๋Ÿฌ๋งŒ ์„ ํƒ์ ์œผ๋กœ ๋น„๊ตํ•ฉ๋‹ˆ๋‹ค.

์„ค๊ณ„ ์›์น™

  1. ํ…Œ์ŠคํŠธ๋Š” "๋ชฉํ‘œ"๋กœ ์ •์˜ (scheduler-neutral)

    • ์˜ˆ: "Interactive ์‘๋‹ต์„ฑ", "๊ณต์ •ํ•œ CPU ๋ฐฐ๋ถ„", "Nice ํšจ๊ณผ ์ธก์ •"
  2. ๊ฐ ํ…Œ์ŠคํŠธ๋งˆ๋‹ค ์ ์ ˆํ•œ ์Šค์ผ€์ค„๋Ÿฌ๋งŒ ๋น„๊ต

    • ์ผ๋ฐ˜ ์›Œํฌ๋กœ๋“œ: Basic + MLFQS + CFS (3-way)
    • ๊ณต์ •์„ฑ ํ…Œ์ŠคํŠธ: MLFQS + CFS๋งŒ (Basic์€ starvation ์œ„ํ—˜)
    • Nice ํšจ๊ณผ: MLFQS + CFS๋งŒ (Basic์˜ nice๋Š” ์ •์  ์šฐ์„ ์ˆœ์œ„)
  3. ๊ฐ ์Šค์ผ€์ค„๋Ÿฌ๊ฐ€ ์ž์‹ ์˜ ๋ฐฉ์‹์œผ๋กœ ๋ชฉํ‘œ ๋‹ฌ์„ฑ

    • Basic: ์ •์  ์šฐ์„ ์ˆœ์œ„
    • MLFQS: ๋™์  ์šฐ์„ ์ˆœ์œ„ ์กฐ์ •
    • CFS: ๊ณต์ •ํ•œ CPU ์‹œ๊ฐ„ ๋ฐฐ๋ถ„

์‹œ์Šคํ…œ ๊ตฌ์„ฑ

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚           Streamlit Web UI (app.py)         โ”‚
โ”‚  - ํ…Œ์ŠคํŠธ ์„ ํƒ (์นดํ…Œ๊ณ ๋ฆฌ๋ณ„)                       โ”‚
โ”‚  - ์‹ค์‹œ๊ฐ„ ์ง„ํ–‰์ƒํ™ฉ ํ‘œ์‹œ                          โ”‚
โ”‚  - ๊ฒฐ๊ณผ ์‹œ๊ฐํ™” (๊ทธ๋ž˜ํ”„, ๋ฉ”ํŠธ๋ฆญ)                   โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                  โ”‚
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚     Benchmark Tests (benchmark/tests.py)    โ”‚
โ”‚  - 18๊ฐœ ํ…Œ์ŠคํŠธ ์ •์˜                            โ”‚
โ”‚  - 6๊ฐœ ์นดํ…Œ๊ณ ๋ฆฌ ๋ถ„๋ฅ˜                            โ”‚
โ”‚  - ์Šค์ผ€์ค„๋Ÿฌ ์กฐํ•ฉ ๋ช…์‹œ                           โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                  โ”‚
         โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
         โ”‚                 โ”‚
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Workload     โ”‚  โ”‚   Simulator    โ”‚
โ”‚  Generator    โ”‚  โ”‚  (simulator/   โ”‚
โ”‚ (workload/)   โ”‚  โ”‚   simulator.py)โ”‚
โ”‚               โ”‚  โ”‚                โ”‚
โ”‚ - 9๊ฐ€์ง€ ํŒจํ„ด    โ”‚  โ”‚ - Time slice   โ”‚
โ”‚ - Seed ๊ณ ์ •    โ”‚  โ”‚ - Context SW   โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚ - I/O ์ฒ˜๋ฆฌ      โ”‚
                   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                            โ”‚
         โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
         โ”‚                  โ”‚                  โ”‚
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ Basic         โ”‚  โ”‚    MLFQS      โ”‚  โ”‚     CFS       โ”‚
โ”‚ Priority      โ”‚  โ”‚  (64-Queue)   โ”‚  โ”‚ (vruntime)    โ”‚
โ”‚ (scheduler/   โ”‚  โ”‚  (scheduler/  โ”‚  โ”‚ (scheduler/   โ”‚
โ”‚  basic_*.py)  โ”‚  โ”‚   mlfqs.py)   โ”‚  โ”‚   cfs.py)     โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
         โ”‚                  โ”‚                  โ”‚
         โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                            โ”‚
                   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                   โ”‚   Analysis      โ”‚
                   โ”‚  (analysis/     โ”‚
                   โ”‚   insights.py)  โ”‚
                   โ”‚                 โ”‚
                   โ”‚ - Metrics ๊ณ„์‚ฐ   โ”‚
                   โ”‚ - ์Šน์ž ๊ฒฐ์ •       โ”‚
                   โ”‚ - Insight ์ƒ์„ฑ   โ”‚
                   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

์„ค์น˜ ๋ฐ ์‹คํ–‰

์š”๊ตฌ์‚ฌํ•ญ

  • Python 3.8 ์ด์ƒ
  • Linux ํ™˜๊ฒฝ ๊ถŒ์žฅ (Ubuntu 20.04+)

์„ค์น˜

# ์ €์žฅ์†Œ ํด๋ก 
git clone https://github.com/dvktdr78/scheduler_benchmark.git
cd scheduler-benchmark/python_webapp

# ๊ฐ€์ƒํ™˜๊ฒฝ ์ƒ์„ฑ
python3 -m venv venv

# ๊ฐ€์ƒํ™˜๊ฒฝ ํ™œ์„ฑํ™”
source venv/bin/activate

# ์˜์กด์„ฑ ์„ค์น˜
pip install -r requirements.txt

์‹คํ–‰

# ๊ฐ€์ƒํ™˜๊ฒฝ ํ™œ์„ฑํ™” (ํ•„์š”์‹œ)
source venv/bin/activate

# Streamlit ์•ฑ ์‹คํ–‰
streamlit run app.py

๋น ๋ฅธ ์‹คํ–‰ ์Šคํฌ๋ฆฝํŠธ

# ํ”„๋กœ์ ํŠธ ๋ฃจํŠธ์—์„œ
./run.sh

์Šค์ผ€์ค„๋Ÿฌ ์ƒ์„ธ

Nice ๊ฐ’ ํ•œ๋ˆˆ์— ๋ณด๊ธฐ

  • ๊ฐœ๋…: ์‚ฌ์šฉ์ž๊ฐ€ ์ฃผ๋Š” โ€œ์–‘๋ณด๋„โ€ ํžŒํŠธ. ๋‚ฎ์„์ˆ˜๋ก ์šฐ์„ ์ˆœ์œ„ โ†‘, ๋†’์„์ˆ˜๋ก ์šฐ์„ ์ˆœ์œ„ โ†“ (๋ฐ˜๋น„๋ก€).
  • ๋ฒ”์œ„: -20(๊ฐ€์žฅ ๋†’์€ ์šฐ์„ ์ˆœ์œ„) ~ +19(๊ฐ€์žฅ ๋‚ฎ์€ ์šฐ์„ ์ˆœ์œ„), ๊ธฐ๋ณธ 0.
  • ์ ์šฉ ๋ฐฉ์‹: Basic์€ priority = 31 - nice๋กœ ์ •์  ๋ณ€ํ™˜, MLFQS๋Š” priority = PRI_MAX - (recent_cpu/4) - 2*nice์— ๋ฐ˜์˜, CFS๋Š” ๊ฐ€์ค‘์น˜ ํ…Œ์ด๋ธ”๋กœ ๋ณ€ํ™˜ํ•ด CPU ์‹œ๊ฐ„ ๋น„์œจ์„ ์กฐ์ •.

1. Basic Priority Scheduler

๊ฐœ์š”: ์ •์  ์šฐ์„ ์ˆœ์œ„ ๊ธฐ๋ฐ˜ ์„ ์ ํ˜• ์Šค์ผ€์ค„๋Ÿฌ (Baseline)

ํ•ต์‹ฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜:

  • Nice ๊ฐ’์„ ์ •์  ์šฐ์„ ์ˆœ์œ„๋กœ ๋ณ€ํ™˜: priority = PRI_DEFAULT(31) - nice
  • ์šฐ์„ ์ˆœ์œ„ ๋ฒ”์œ„: 0-63 (63์ด ์ตœ๊ณ  ์šฐ์„ ์ˆœ์œ„)
  • ๊ฐ™์€ ์šฐ์„ ์ˆœ์œ„ ๋‚ด์—์„œ FIFO ๋ฐฉ์‹

๊ตฌํ˜„ ํŠน์ง•:

  • Round-robin ๋ฐฉ์‹ (time slice = 4 ticks)
  • Preemptive (๋†’์€ ์šฐ์„ ์ˆœ์œ„ ์Šค๋ ˆ๋“œ๊ฐ€ ๋„์ฐฉํ•˜๋ฉด ์„ ์ )
  • Aging ๋ฏธ์ง€์› (starvation ์œ„ํ—˜ ์กด์žฌ)

์žฅ์ :

  • ๋‹จ์ˆœํ•˜๊ณ  ์˜ˆ์ธก ๊ฐ€๋Šฅ
  • ์˜ค๋ฒ„ํ—ค๋“œ ์ตœ์†Œ
  • ์‹ค์‹œ๊ฐ„ ์‹œ์Šคํ…œ์— ์ ํ•ฉ

๋‹จ์ :

  • Starvation ์œ„ํ—˜ (๋‚ฎ์€ ์šฐ์„ ์ˆœ์œ„ ์Šค๋ ˆ๋“œ)
  • ๋™์  ์กฐ์ • ๋ถˆ๊ฐ€
  • I/O bound ์Šค๋ ˆ๋“œ์— ๋ถˆ๋ฆฌ

์ฝ”๋“œ ์œ„์น˜: scheduler/basic_priority.py

2. MLFQS (Multi-Level Feedback Queue Scheduler)

๊ฐœ์š”: 64๊ฐœ ๋…๋ฆฝ ํ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋™์  ์šฐ์„ ์ˆœ์œ„ ์Šค์ผ€์ค„๋Ÿฌ (FreeBSD ๋ฐฉ์‹)

ํ•ต์‹ฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜:

priority = PRI_MAX - (recent_cpu / 4) - (nice * 2)

recent_cpu = (2 * load_avg) / (2 * load_avg + 1) * recent_cpu + nice

load_avg = (59/60) * load_avg + (1/60) * ready_threads

๊ตฌํ˜„ ํŠน์ง•:

  • 64๊ฐœ ๋…๋ฆฝ ํ (์šฐ์„ ์ˆœ์œ„ 0-63)
  • O(1) pick_next (๊ธฐ์กด O(n) โ†’ O(64) = O(1))
  • O(1) thread_yield (๊ธฐ์กด O(n log n) โ†’ O(1))
  • 17.14 ๊ณ ์ •์†Œ์ˆ˜์  ์—ฐ์‚ฐ (F = 1 << 14 = 16384)

์—…๋ฐ์ดํŠธ ์ฃผ๊ธฐ:

  • recent_cpu++: ๋งค tick (์‹คํ–‰ ์ค‘์ธ ์Šค๋ ˆ๋“œ๋งŒ)
  • priority ์žฌ๊ณ„์‚ฐ: 4 ticks๋งˆ๋‹ค
  • load_avg, recent_cpu ์žฌ๊ณ„์‚ฐ: 100 ticks๋งˆ๋‹ค

์žฅ์ :

  • I/O bound ์Šค๋ ˆ๋“œ ์ž๋™ ์šฐ๋Œ€
  • Starvation ๋ฐฉ์ง€ (recent_cpu๊ฐ€ ์‹œ๊ฐ„์— ๋”ฐ๋ผ ๊ฐ์†Œ)
  • ๋™์  ๋ถ€ํ•˜ ์กฐ์ •

๋‹จ์ :

  • Nice ํšจ๊ณผ๊ฐ€ ์•ฝํ•จ (nice๋Š” priority์— -2๋ฐฐ๋งŒ ๊ธฐ์—ฌ)
  • ๋ณต์žกํ•œ ๊ณ„์‚ฐ (๊ณ ์ •์†Œ์ˆ˜์ )
  • ๊ณต์ •์„ฑ์ด CFS๋ณด๋‹ค ๋‚ฎ์Œ

์ฝ”๋“œ ์œ„์น˜:

3. CFS (Completely Fair Scheduler)

๊ฐœ์š”: Linux ์ปค๋„์˜ ๊ณต์ •์„ฑ ์Šค์ผ€์ค„๋Ÿฌ (vruntime ๊ธฐ๋ฐ˜)

ํ•ต์‹ฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜:

delta_vruntime = delta * (NICE_0_WEIGHT / weight)
weight = PRIO_TO_WEIGHT[nice + 20]

์ตœ์†Œ vruntime ์Šค๋ ˆ๋“œ๋ฅผ ์„ ํƒ (Red-Black Tree ๋Œ€์‹  SortedList ์‚ฌ์šฉ)

๊ตฌํ˜„ ํŠน์ง•:

  • Linux ์ปค๋„ ๊ฐ€์ค‘์น˜ ํ…Œ์ด๋ธ” 100% ๋™์ผ ์‚ฌ์šฉ
  • vruntime์œผ๋กœ ์ž๋™ ์ •๋ ฌ (SortedList)
  • 1000๋ฐฐ ์Šค์ผ€์ผ ์ฆ๊ฐ€๋กœ ์ •๋ฐ€๋„ ํ–ฅ์ƒ ((delta * 1024 * 1000) // weight)

๊ฐ€์ค‘์น˜ ํ…Œ์ด๋ธ” ์˜ˆ์‹œ:

  • nice -20 โ†’ weight 88761 (์ตœ๊ณ  ์šฐ์„ ์ˆœ์œ„)
  • nice 0 โ†’ weight 1024 (๊ธฐ๋ณธ)
  • nice 19 โ†’ weight 15 (์ตœ์ € ์šฐ์„ ์ˆœ์œ„)

์ด๋ก ์  CPU ์‹œ๊ฐ„ ๋น„์œจ:

  • nice -20 vs nice 19: 88761 / 15 โ‰ˆ 5917:1

์žฅ์ :

  • ์™„๋ฒฝํ•œ ๊ณต์ •์„ฑ (Jain Index > 0.95)
  • Nice ํšจ๊ณผ๊ฐ€ ๊ฐ•ํ•จ (๊ฐ€์ค‘์น˜ ๊ธฐ๋ฐ˜)
  • Starvation ์™„์ „ ๋ฐฉ์ง€

๋‹จ์ :

  • I/O bound ์Šค๋ ˆ๋“œ์— ํŠน๋ณ„ํ•œ ์šฐ๋Œ€ ์—†์Œ
  • ์•ฝ๊ฐ„์˜ ์˜ค๋ฒ„ํ—ค๋“œ (SortedList ๊ด€๋ฆฌ)

์ฝ”๋“œ ์œ„์น˜: scheduler/cfs.py

ํ…Œ์ŠคํŠธ ์นดํ…Œ๊ณ ๋ฆฌ

์ด 17๊ฐœ ํ…Œ์ŠคํŠธ, 6๊ฐœ ์นดํ…Œ๊ณ ๋ฆฌ๋กœ ๊ตฌ์„ฑ

1. ์ผ๋ฐ˜ ์›Œํฌ๋กœ๋“œ (3๊ฐœ ํ…Œ์ŠคํŠธ, 3-way ๋น„๊ต)

๋ชฉ์ : ๋‹ค์–‘ํ•œ ์ผ๋ฐ˜์ ์ธ ์›Œํฌ๋กœ๋“œ ํŒจํ„ด ๋น„๊ต

ํ…Œ์ŠคํŠธ ์›Œํฌ๋กœ๋“œ ์ฃผ์š” ๋ฉ”ํŠธ๋ฆญ ๋น„๊ต ๋Œ€์ƒ
์ผ๋ฐ˜ ํ˜ผํ•ฉ ์›Œํฌ๋กœ๋“œ mixed avg_wait Basic + MLFQS + CFS
CPU ์ง‘์•ฝ์  ์›Œํฌ๋กœ๋“œ cpu_bound avg_turnaround Basic + MLFQS + CFS
I/O ์ง‘์•ฝ์  ์›Œํฌ๋กœ๋“œ io_bound avg_wait Basic + MLFQS + CFS

ํŠน์ง•:

  • mixed: Nice -5~5 (์•ฝํ•œ ์ฐจ์ด)
  • cpu_bound: Nice 0 (์ˆœ์ˆ˜ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ํšจ์œจ์„ฑ ๋น„๊ต)
  • io_bound: 60% I/O + 40% CPU ๊ฒฝ์Ÿ์ž ํ˜ผํ•ฉ (MLFQS I/O ์šฐ๋Œ€ ํ…Œ์ŠคํŠธ)

2. ์‹ค์ œ ์‘์šฉ (4๊ฐœ ํ…Œ์ŠคํŠธ, 3-way ๋น„๊ต)

๋ชฉ์ : ์‹ค์ œ ์‹œ์Šคํ…œ ํŒจํ„ด ์‹œ๋ฎฌ๋ ˆ์ด์…˜

ํ…Œ์ŠคํŠธ ์›Œํฌ๋กœ๋“œ ํŒจํ„ด ๋น„๊ต ๋Œ€์ƒ
์›น ์„œ๋ฒ„ ํŒจํ„ด web_server 90% ์งง์€ ์š”์ฒญ (Nice -5) + 10% ๊ธด ์š”์ฒญ (Nice 5) Basic + MLFQS + CFS
๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํŒจํ„ด database 70% SELECT + 30% ํŠธ๋žœ์žญ์…˜ Basic + MLFQS + CFS
๋ฐฐ์น˜ ์ฒ˜๋ฆฌ ํŒจํ„ด batch CPU-heavy, ์ˆœ์ฐจ ๋„์ฐฉ Basic + MLFQS + CFS
๊ฒŒ์ž„/์‹ค์‹œ๊ฐ„ ํŒจํ„ด gaming 30% ๋ Œ๋”๋ง (Nice -10) + 70% AI (Nice 10) Basic + MLFQS + CFS

ํŠน์ง•:

  • ์‹ค์ œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋™์ž‘ ๋ชจ๋ฐฉ
  • web_server/gaming: Nice ์ฐจ์ด๋กœ ์šฐ์„ ์ˆœ์œ„ ์ฒ˜๋ฆฌ ๋Šฅ๋ ฅ ํ…Œ์ŠคํŠธ
  • database/batch: Nice 0์œผ๋กœ ํ†ต์ผ

3. ๊ณต์ •์„ฑ (2๊ฐœ ํ…Œ์ŠคํŠธ, MLFQS vs CFS)

๋ชฉ์ : CPU ์‹œ๊ฐ„ ๋ฐฐ๋ถ„์˜ ๊ณต์ •์„ฑ ์ธก์ •

ํ…Œ์ŠคํŠธ ์›Œํฌ๋กœ๋“œ ์ฃผ์š” ๋ฉ”ํŠธ๋ฆญ ๋น„๊ต ๋Œ€์ƒ
๊ณต์ •์„ฑ: ํ˜ผํ•ฉ ์›Œํฌ๋กœ๋“œ mixed fairness MLFQS + CFS
๊ณต์ •์„ฑ: ๊ทน๋‹จ Nice ๊ฐ€์ค‘์น˜ extreme_nice_fairness fairness MLFQS + CFS

Note: cpu_bound ์›Œํฌ๋กœ๋“œ๋Š” ๋ชจ๋“  ์Šค๋ ˆ๋“œ๊ฐ€ Nice 0์œผ๋กœ ๋™์ผํ•˜์—ฌ ์Šค์ผ€์ค„๋Ÿฌ ๊ฐ„ ๊ณต์ •์„ฑ ์ฐจ์ด๊ฐ€ ์—†์–ด ํ…Œ์ŠคํŠธ์—์„œ ์ œ์™ธ๋จ.

์™œ Basic์„ ์ œ์™ธํ•˜๋Š”๊ฐ€?

  • Basic Priority๋Š” ์ •์  ์šฐ์„ ์ˆœ์œ„ ๊ธฐ๋ฐ˜์œผ๋กœ starvation ์œ„ํ—˜ ์กด์žฌ
  • ๊ณต์ •์„ฑ ์ธก์ •์— ๋ถ€์ ํ•ฉ (์• ์ดˆ์— ๊ณต์ •์„ฑ์„ ๋ชฉํ‘œ๋กœ ํ•˜์ง€ ์•Š์Œ)

๋ฉ”ํŠธ๋ฆญ: Jain's Fairness Index (1.0์— ๊ฐ€๊นŒ์šธ์ˆ˜๋ก ๊ณต์ •)

๊ณต์ •์„ฑ ์ •์˜(ํ˜„์žฌ ๊ตฌํ˜„):

  • ๊ฐ ์Šค๋ ˆ๋“œ๊ฐ€ ์‹ค์ œ๋กœ ์‹คํ–‰ ๊ฐ€๋Šฅํ•œ ์‹œ๊ฐ„(READY/RUNNING) ๋™์•ˆ ๊ฐ€์ ธ์•ผ ํ•  ๋ชซ์„ niceโ†’weight๋กœ ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ: nice -20์€ weight๊ฐ€ ํฌ๋‹ˆ ๋” ํฐ ๋ชซ์„ ๊ฐ–์Šต๋‹ˆ๋‹ค.
  • ๊ด€์ฐฐ ๊ตฌ๊ฐ„์—์„œ ๋ฐ›์€ **CPU ๋น„์ค‘ รท (runnable_time ร— weight ๋น„์ค‘)**์„ ๊ตฌํ•ด, ๋ชจ๋“  ์Šค๋ ˆ๋“œ์˜ ๊ฐ’์ด 1์— ๊ฐ€๊นŒ์šฐ๋ฉด ๊ณต์ •ํ•ฉ๋‹ˆ๋‹ค.
  • ์ด ๋น„์œจ๋“ค์— Jain Index๋ฅผ ์ ์šฉํ•ด 0~1 ์‚ฌ์ด ๊ฐ’์œผ๋กœ ํ‘œํ˜„ํ•ฉ๋‹ˆ๋‹ค(1.0 = ์ด์ƒ์  ๋น„๋ก€ ๋ฐฐ๋ถ„).
  • runnable ์‹œ๊ฐ„์ด 0์ด๊ฑฐ๋‚˜ ์™„๋ฃŒ ์Šค๋ ˆ๋“œ๊ฐ€ ์—†์œผ๋ฉด ํ•ด๋‹น ๊ฐ’์€ N/A๋กœ ํ‘œ์‹œํ•ด 0.0๊ณผ ํ˜ผ๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

4. ์ผ๊ด€์„ฑ (4๊ฐœ ํ…Œ์ŠคํŠธ, 3-way ๋น„๊ต)

๋ชฉ์ : ๋Œ€๊ธฐ ์‹œ๊ฐ„์˜ ์˜ˆ์ธก ๊ฐ€๋Šฅ์„ฑ๊ณผ ์ผ๊ด€์„ฑ ์ธก์ • (CFS ์œ ๋ฆฌ)

ํ…Œ์ŠคํŠธ ์›Œํฌ๋กœ๋“œ ์ฃผ์š” ๋ฉ”ํŠธ๋ฆญ ๋น„๊ต ๋Œ€์ƒ
์ผ๊ด€์„ฑ: ๋ณ€๋™๊ณ„์ˆ˜ mixed cv_wait Basic + MLFQS + CFS
์ผ๊ด€์„ฑ: P99 ๋ ˆ์ดํ„ด์‹œ mixed p99_wait Basic + MLFQS + CFS
์ผ๊ด€์„ฑ: ์ตœ์•…/ํ‰๊ท  ๋น„์œจ mixed worst_ratio Basic + MLFQS + CFS
๊ธฐ์•„ ๋ฐฉ์ง€: ๊ทน๋‹จ์  Nice extreme_nice starvation_pct Basic + MLFQS + CFS

๋ฉ”ํŠธ๋ฆญ ์„ค๋ช…:

  • cv_wait: ๋ณ€๋™๊ณ„์ˆ˜ (ํ‘œ์ค€ํŽธ์ฐจ/ํ‰๊ท  ร— 100), ๋‚ฎ์„์ˆ˜๋ก ์˜ˆ์ธก ๊ฐ€๋Šฅ
  • p99_wait: 99 ํผ์„ผํƒ€์ผ ๋Œ€๊ธฐ ์‹œ๊ฐ„, ๋‚ฎ์„์ˆ˜๋ก ํ…Œ์ผ ๋ ˆ์ดํ„ด์‹œ ์–‘ํ˜ธ
  • worst_ratio: ์ตœ์•…/ํ‰๊ท  ๋Œ€๊ธฐ ์‹œ๊ฐ„ ๋น„์œจ, 1.0์— ๊ฐ€๊นŒ์šธ์ˆ˜๋ก ๊ท ์ผ
  • starvation_pct: ์‹คํ–‰ ์•ˆ๋œ ์Šค๋ ˆ๋“œ ๋น„์œจ, 0%๊ฐ€ ์ด์ƒ์ 

5. Nice ํšจ๊ณผ (1๊ฐœ ํ…Œ์ŠคํŠธ, MLFQS vs CFS)

๋ชฉ์ : Nice ๊ฐ’์˜ ์‹ค์ œ ํšจ๊ณผ ๊ฒ€์ฆ

ํ…Œ์ŠคํŠธ ์›Œํฌ๋กœ๋“œ ์ฃผ์š” ๋ฉ”ํŠธ๋ฆญ ๋น„๊ต ๋Œ€์ƒ
Nice ๊ฐ’ ํšจ๊ณผ ๊ฒ€์ฆ extreme_nice cpu_time_ratio MLFQS + CFS

์™œ Basic์„ ์ œ์™ธํ•˜๋Š”๊ฐ€?

  • Basic์˜ nice๋Š” ์ •์  ์šฐ์„ ์ˆœ์œ„๋กœ ๋ณ€ํ™˜ (๋‹ค๋ฅธ ์˜๋ฏธ)
  • MLFQS/CFS๋Š” nice๋กœ CPU ์‹œ๊ฐ„ ๋น„์œจ ์กฐ์ • (๊ฐ€์ค‘์น˜ ๊ธฐ๋ฐ˜)

ํ…Œ์ŠคํŠธ ๋ฐฉ๋ฒ•:

  • ์ ˆ๋ฐ˜: nice -20 (์ตœ๊ณ  ์šฐ์„ ์ˆœ์œ„)
  • ์ ˆ๋ฐ˜: nice 19 (์ตœ์ € ์šฐ์„ ์ˆœ์œ„)
  • burst_time = 2,000 ticks (MLFQS ์„ฑ๋Šฅ ๊ณ ๋ คํ•˜์—ฌ ์ถ•์†Œ)
  • 20% ์‹œ๊ฐ„์— ์ค‘๋‹จ (์ผ๋ถ€๋งŒ ์™„๋ฃŒํ•˜์—ฌ CPU ์‹œ๊ฐ„ ๋น„์œจ ์ธก์ •, max_ticks=20,000)

๋ฉ”ํŠธ๋ฆญ: CPU ์‹œ๊ฐ„ ๋น„์œจ (nice -20 ๊ทธ๋ฃน / nice 19 ๊ทธ๋ฃน)

๊ด€์ฐฐ: MLFQS๋Š” ๋งค์šฐ ๊ฐ•ํ•œ nice ํšจ๊ณผ๋ฅผ, CFS๋Š” ๊ฐ€์ค‘์น˜ ๋น„๋ก€ ๋ฐฐ๋ถ„์„ ๋ณด์ž„

6. ํ™•์žฅ์„ฑ (3๊ฐœ ํ…Œ์ŠคํŠธ, 3-way ๋น„๊ต)

๋ชฉ์ : ์Šค๋ ˆ๋“œ ์ˆ˜์— ๋”ฐ๋ฅธ ์„ฑ๋Šฅ ๋ณ€ํ™”

ํ…Œ์ŠคํŠธ ์Šค๋ ˆ๋“œ ์ˆ˜ ์ฃผ์š” ๋ฉ”ํŠธ๋ฆญ ๋น„๊ต ๋Œ€์ƒ
ํ™•์žฅ์„ฑ: 10 ์Šค๋ ˆ๋“œ 10 context_switches Basic + MLFQS + CFS
ํ™•์žฅ์„ฑ: 100 ์Šค๋ ˆ๋“œ 100 avg_wait Basic + MLFQS + CFS
ํ™•์žฅ์„ฑ: 500 ์Šค๋ ˆ๋“œ 500 avg_wait Basic + MLFQS + CFS

๋ชฉํ‘œ: ์Šค์ผ€์ผ๋ง ๋Šฅ๋ ฅ ๋ฐ ์˜ค๋ฒ„ํ—ค๋“œ ์ธก์ •

์›Œํฌ๋กœ๋“œ

๊ธฐ๋ณธ ์›Œํฌ๋กœ๋“œ (3๊ฐœ)

1. Mixed (ํ˜ผํ•ฉ)

  • CPU burst: 100-500 ticks
  • I/O: ๋‹ค์–‘ (๋นˆ๋„ 0-500, ์ง€์† 0-200)
  • Nice: -5 ~ 5
  • ์šฉ๋„: ์ผ๋ฐ˜์ ์ธ ๋ฉ€ํ‹ฐํƒœ์Šคํ‚น ํ™˜๊ฒฝ

2. CPU-bound (CPU ์ง‘์•ฝ)

  • CPU burst: 300-800 ticks
  • I/O: ์—†์Œ
  • Nice: 0
  • ์šฉ๋„: ๊ณผํ•™ ๊ณ„์‚ฐ, ์ปดํŒŒ์ผ (์ˆœ์ˆ˜ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ํšจ์œจ์„ฑ ๋น„๊ต)

3. I/O-bound (I/O ์ง‘์•ฝ)

  • 60% I/O-bound: CPU burst 30-100, I/O ๋นˆ๋„ 10-30 (๋งค์šฐ ์žฆ์Œ)
  • 40% CPU-bound ๊ฒฝ์Ÿ์ž: CPU burst 500-1000, I/O ์—†์Œ
  • Nice: 0
  • ์šฉ๋„: MLFQS์˜ I/O ์šฐ๋Œ€ ๋Šฅ๋ ฅ ํ…Œ์ŠคํŠธ

์‹ค์ œ ์‘์šฉ ์›Œํฌ๋กœ๋“œ (4๊ฐœ)

4. Web Server (์›น ์„œ๋ฒ„)

  • 90% ์งง์€ ์š”์ฒญ: 10-50 ticks (Nice -5)
  • 10% ๊ธด ์š”์ฒญ: 200-600 ticks (Nice 5)
  • ๋ชจ๋ฐฉ: Nginx, Apache (์งง์€ ์š”์ฒญ ์šฐ์„  ์ฒ˜๋ฆฌ)

5. Database (๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค)

  • 70% SELECT ์ฟผ๋ฆฌ: 30-150 ticks
  • 30% ํŠธ๋žœ์žญ์…˜: 200-600 ticks
  • Nice: 0
  • ๋ชจ๋ฐฉ: PostgreSQL, MySQL

6. Batch Processing (๋ฐฐ์น˜ ์ฒ˜๋ฆฌ)

  • CPU burst: 400-800 ticks
  • ์ˆœ์ฐจ ๋„์ฐฉ (i * 10 ticks)
  • Nice: 0
  • ๋ชจ๋ฐฉ: ๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ, ๋นŒ๋“œ ์‹œ์Šคํ…œ

7. Gaming (๊ฒŒ์ž„/์‹ค์‹œ๊ฐ„)

  • 30% ๋ Œ๋”๋ง: 50-150 ticks, 16ms ๊ฐ„๊ฒฉ ๋„์ฐฉ (Nice -10)
  • 70% AI/๋ฌผ๋ฆฌ: 200-500 ticks (Nice 10)
  • ๋ชฉํ‘œ: 60 FPS ์œ ์ง€ (๋ Œ๋”๋ง ์šฐ์„ )

๊ทน๋‹จ ํ…Œ์ŠคํŠธ ์›Œํฌ๋กœ๋“œ (2๊ฐœ)

8. Extreme Nice (Nice ๊ทน๋‹จ ํ…Œ์ŠคํŠธ)

  • ์ ˆ๋ฐ˜: nice -20, burst_time 2,000
  • ์ ˆ๋ฐ˜: nice 19, burst_time 2,000
  • I/O: ์—†์Œ
  • ์šฉ๋„: Nice ํšจ๊ณผ ๊ฒ€์ฆ (MLFQS ์„ฑ๋Šฅ ๊ณ ๋ คํ•˜์—ฌ ์ถ•์†Œ)

9. Extreme Nice Fairness (๊ณต์ •์„ฑ ์ธก์ •์šฉ)

  • ์ ˆ๋ฐ˜: nice -20, burst_time 1,000
  • ์ ˆ๋ฐ˜: nice 19, burst_time 1,000
  • I/O: ์—†์Œ
  • ์šฉ๋„: ์ œํ•œ๋œ ์‹œ๊ฐ„ ๋‚ด ๊ฐ€์ค‘์น˜ ๋น„๋ก€ ๊ณต์ •์„ฑ ์ธก์ •

์ฝ”๋“œ ์œ„์น˜: workload/generator.py

ํŒŒ์ผ ๊ตฌ์กฐ

standalone_scheduler/
โ”œโ”€โ”€ python_webapp/
โ”‚   โ”œโ”€โ”€ app.py                      # Streamlit ๋ฉ”์ธ UI
โ”‚   โ”œโ”€โ”€ requirements.txt            # Python ์˜์กด์„ฑ
โ”‚   โ”‚
โ”‚   โ”œโ”€โ”€ scheduler/                  # ์Šค์ผ€์ค„๋Ÿฌ ๊ตฌํ˜„
โ”‚   โ”‚   โ”œโ”€โ”€ thread.py               # Thread ๋ฐ์ดํ„ฐ ํด๋ž˜์Šค
โ”‚   โ”‚   โ”œโ”€โ”€ basic_priority.py       # Basic Priority ์Šค์ผ€์ค„๋Ÿฌ
โ”‚   โ”‚   โ”œโ”€โ”€ mlfqs.py                # MLFQS ์Šค์ผ€์ค„๋Ÿฌ
โ”‚   โ”‚   โ”œโ”€โ”€ cfs.py                  # CFS ์Šค์ผ€์ค„๋Ÿฌ
โ”‚   โ”‚   โ””โ”€โ”€ fixed_point.py          # 17.14 ๊ณ ์ •์†Œ์ˆ˜์  ์—ฐ์‚ฐ
โ”‚   โ”‚
โ”‚   โ”œโ”€โ”€ workload/                   # ์›Œํฌ๋กœ๋“œ ์ƒ์„ฑ
โ”‚   โ”‚   โ””โ”€โ”€ generator.py            # 8๊ฐ€์ง€ ์›Œํฌ๋กœ๋“œ ์ƒ์„ฑ๊ธฐ
โ”‚   โ”‚
โ”‚   โ”œโ”€โ”€ simulator/                  # ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ์—”์ง„
โ”‚   โ”‚   โ””โ”€โ”€ simulator.py            # ๋‹จ์ผ CPU ์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ
โ”‚   โ”‚
โ”‚   โ”œโ”€โ”€ analysis/                   # ๋ถ„์„ ๋„๊ตฌ
โ”‚   โ”‚   โ”œโ”€โ”€ metrics.py              # ๋ฉ”ํŠธ๋ฆญ ๊ณ„์‚ฐ ํ•จ์ˆ˜
โ”‚   โ”‚   โ””โ”€โ”€ insights.py             # Insight ์ƒ์„ฑ ๋ฐ ๋น„๊ต ๋ณด๊ณ ์„œ
โ”‚   โ”‚
โ”‚   โ””โ”€โ”€ benchmark/                  # ๋ฒค์น˜๋งˆํฌ ์ •์˜
โ”‚       โ””โ”€โ”€ tests.py                # 18๊ฐœ ํ…Œ์ŠคํŠธ ์ •์˜
โ”‚
โ”œโ”€โ”€ run.sh                          # ๋น ๋ฅธ ์‹คํ–‰ ์Šคํฌ๋ฆฝํŠธ
โ””โ”€โ”€ README.md                       # ์ด ํŒŒ์ผ

์ฃผ์š” ๋ฐœ๊ฒฌ์‚ฌํ•ญ

๋ฒ„๊ทธ ์ˆ˜์ • ๊ณผ์ •์—์„œ ๋ฐœ๊ฒฌํ•œ 6๊ฐ€์ง€ ์ฃผ์š” ์ด์Šˆ

1. Time Slice ๋ฏธ๊ตฌํ˜„ (์ดˆ๊ธฐ)

์ฆ์ƒ: ๊ฒฐ๊ณผ๊ฐ€ ์ฆ‰์‹œ ๋‚˜์˜ค๊ณ  ๋ชจ๋“  ๋ฉ”ํŠธ๋ฆญ์ด ๋™์ผ (tie)

์›์ธ: ์Šค๋ ˆ๋“œ๊ฐ€ ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ๊ณ„์† ์‹คํ–‰ (์„ ์  ์—†์Œ)

ํ•ด๊ฒฐ:

  • Simulator์— time_slice=4 ์ถ”๊ฐ€
  • current_slice_remaining ์ถ”์ 
  • Time slice ๋งŒ๋ฃŒ ์‹œ thread_yield() ํ˜ธ์ถœ

์œ„์น˜: simulator/simulator.py:94-137

2. Basic Priority FIFO ๋ฒ„๊ทธ

์ฆ์ƒ: Basic์ด ๊ฑฐ์˜ ํ•ญ์ƒ ์Šน๋ฆฌ

์›์ธ: max(key=lambda t: (t.priority, -t.tid))๊ฐ€ ํ•ญ์ƒ ์ตœ์†Œ TID ์„ ํƒ (FIFO๊ฐ€ ์•„๋‹˜)

ํ•ด๊ฒฐ:

# ์ตœ๊ณ  ์šฐ์„ ์ˆœ์œ„ ์ฐพ๊ธฐ
max_priority = max(t.priority for t in self.ready_queue)

# ๊ฐ™์€ ์šฐ์„ ์ˆœ์œ„ ์ค‘ ์ฒซ ๋ฒˆ์งธ ์Šค๋ ˆ๋“œ ์„ ํƒ (์ง„์งœ FIFO)
for thread in self.ready_queue:
    if thread.priority == max_priority:
        self.ready_queue.remove(thread)
        return thread

์œ„์น˜: scheduler/basic_priority.py:41-67

3. MLFQS Nice ๋ฎ์–ด์“ฐ๊ธฐ ๋ฒ„๊ทธ

์ฆ์ƒ: MLFQS์—์„œ ๋ชจ๋“  ์Šค๋ ˆ๋“œ์˜ nice๊ฐ€ 0์ด ๋จ

์›์ธ: add_thread()์—์„œ thread.nice = 0 ์‹คํ–‰

ํ•ด๊ฒฐ: ํ•ด๋‹น ๋ผ์ธ ์ œ๊ฑฐ, ์›Œํฌ๋กœ๋“œ์—์„œ ์„ค์ •ํ•œ nice ๊ฐ’ ์œ ์ง€

์œ„์น˜: scheduler/mlfqs.py:99-109

4. CFS vruntime ์ •๋ฐ€๋„ ๋ฌธ์ œ (Critical!)

์ฆ์ƒ: CFS vruntime์ด ํ•ญ์ƒ 0

์›์ธ: ์ •์ˆ˜ ๋‚˜๋ˆ—์…ˆ (delta * 1024) // weight์—์„œ weight=88761์ผ ๋•Œ ๊ฒฐ๊ณผ๊ฐ€ 0

๋ถ„์„:

delta = 1
1024 / 88761 = 0.0115... โ†’ ์ •์ˆ˜ ๋‚˜๋ˆ—์…ˆ์œผ๋กœ 0

ํ•ด๊ฒฐ: 1000๋ฐฐ ์Šค์ผ€์ผ ์ฆ๊ฐ€

return (delta * 1024 * 1000) // weight
# nice -20 (weight 88761): delta_vruntime = 11
# nice 19 (weight 15): delta_vruntime = 68266

์œ„์น˜: scheduler/cfs.py:52-64

5. Nice ํšจ๊ณผ ์ธก์ • ๋ถˆ๊ฐ€ ๋ฌธ์ œ

์ฆ์ƒ: CPU ์‹œ๊ฐ„ ๋น„์œจ์ด 1:1๋กœ ๋‚˜์˜ด (์˜ˆ์ƒ: ์ˆ˜์ฒœ:1)

์›์ธ: ๋ชจ๋“  ์Šค๋ ˆ๋“œ๊ฐ€ ์™„๋ฃŒ โ†’ ๊ฐ์ž ์ •ํ™•ํžˆ burst_time๋งŒํผ CPU ์‚ฌ์šฉ โ†’ ๋น„์œจ 1:1

ํ•ด๊ฒฐ:

  1. extreme_nice ์›Œํฌ๋กœ๋“œ์˜ burst_time: 300 โ†’ 2,000 (MLFQS ์„ฑ๋Šฅ ๊ณ ๋ ค)
  2. Nice ํšจ๊ณผ ํ…Œ์ŠคํŠธ๋งŒ 20% ์‹œ๊ฐ„์— ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ์ค‘๋‹จ (max_ticks=20,000)
if selected_test.test_id == "nice_effect":
    total_work = sum(t.burst_time for t in base_threads)
    actual_max_ticks = int(total_work * 0.5)  # 50% ์‹œ๊ฐ„๋งŒ ์‹คํ–‰

๊ฒฐ๊ณผ: MLFQS๋Š” ๋งค์šฐ ๊ฐ•ํ•œ nice ํšจ๊ณผ, CFS๋Š” ๊ฐ€์ค‘์น˜ ๋น„๋ก€ ๋ฐฐ๋ถ„

์œ„์น˜:

6. ์ปจํ…์ŠคํŠธ ์Šค์œ„์น˜ ์ˆ˜ ์ธก์ • ๋ถˆ๊ฐ€ (ํ™•์žฅ์„ฑ ํ…Œ์ŠคํŠธ ๋ฌดํšจํ™”)

์ฆ์ƒ: ํ™•์žฅ์„ฑ ํ…Œ์ŠคํŠธ์˜ ์ฃผ์š” ๋ฉ”ํŠธ๋ฆญ context_switches๊ฐ€ ํ•ญ์ƒ 0์œผ๋กœ ๋‚˜์™€ ๊ฐœ์„ ์œจ์ด 0% ๊ณ ์ •

์›์ธ:

  • ์ปจํ…์ŠคํŠธ ์Šค์œ„์น˜ ์นด์šดํŠธ๊ฐ€ ์Šค๋ ˆ๋“œ์— ์ „๋‹ฌ๋˜์ง€ ์•Š์Œ
  • ๋งˆ์ง€๋ง‰ ์‹คํ–‰ ์Šค๋ ˆ๋“œ ID๋ฅผ ์ถ”์ ํ•˜์ง€ ์•Š์•„ ์นด์šดํŠธ๊ฐ€ ๋ˆ„๋ฝ

ํ•ด๊ฒฐ:

  • prev_running_tid๋กœ ์ปจํ…์ŠคํŠธ ์Šค์œ„์น˜ ์‹œ์ ์„ ์ •ํ™•ํžˆ ํŒŒ์•…
  • ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ์ข…๋ฃŒ ์‹œ ๋ชจ๋“  ์Šค๋ ˆ๋“œ์— context_switches ๊ธฐ๋ก
  • ๋ฉ”ํŠธ๋ฆญ ๊ณ„์‚ฐ์—์„œ context_switches๋ฅผ ์ง€์›

์œ„์น˜:

ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ ์š”์•ฝ

๊ฐ ์Šค์ผ€์ค„๋Ÿฌ๊ฐ€ ์ž์‹ ์˜ ๊ฐ•์ ์— ๋งž๋Š” ์›Œํฌ๋กœ๋“œ์—์„œ ์Šน๋ฆฌํ•˜๋ฉฐ, ํŠน์ • ์Šค์ผ€์ค„๋Ÿฌ๊ฐ€ ์••๋„์ ์œผ๋กœ ์œ ๋ฆฌํ•˜์ง€ ์•Š์Œ.

์„ค๊ณ„ ๊ฒฐ์ •์‚ฌํ•ญ

1. Burst Time์€ ์ •์ ์ด์–ด์•ผ ํ•จ

์งˆ๋ฌธ: "bursttime์„ vruntime ๊ฐ™์€ ๋ณ€์ˆ˜์— ๋งž๊ฒŒ ๋™์ ์œผ๋กœ ๋Š˜๋ ค์•ผ ํ•˜๋‚˜?"

๋‹ต๋ณ€: NO

์ด์œ :

  • burst_time์€ "์‹ค์ œ๋กœ ํ•„์š”ํ•œ ์ž‘์—…๋Ÿ‰"์„ ๋‚˜ํƒ€๋ƒ„
  • ํ”„๋กœ์„ธ์Šค๊ฐ€ ์™„๋ฃŒํ•˜๋ ค๋ฉด burst_time๋งŒํผ์˜ CPU๊ฐ€ ํ•„์š”
  • ์Šค์ผ€์ค„๋Ÿฌ๋Š” ์ด๋ฅผ ์–ด๋–ป๊ฒŒ ๋ฐฐ๋ถ„ํ• ์ง€ ๊ฒฐ์ •ํ•  ๋ฟ, ์ž‘์—…๋Ÿ‰ ์ž์ฒด๋Š” ๋ณ€ํ•˜์ง€ ์•Š์Œ
  • ๋™์ ์œผ๋กœ ๋ณ€๊ฒฝํ•˜๋ฉด "์Šค์ผ€์ค„๋Ÿฌ ์„ฑ๋Šฅ" ๋Œ€์‹  "์›Œํฌ๋กœ๋“œ ์ž์ฒด"๊ฐ€ ๋‹ฌ๋ผ์ง

Nice ํšจ๊ณผ ์ธก์ • ์‹œ:

  • burst_time 2,000 ์‚ฌ์šฉ (MLFQS ์„ฑ๋Šฅ ๊ณ ๋ ค)
  • 20% ์‹œ๊ฐ„์— ์ค‘๋‹จํ•˜์—ฌ ๋ถ€๋ถ„ ์™„๋ฃŒ ๊ด€์ฐฐ (max_ticks=20,000)
  • ์ด๊ฒƒ์ด ์˜ฌ๋ฐ”๋ฅธ ๋ฐฉ๋ฒ•

2. Nice ๊ฐ’์˜ ์˜๋ฏธ๋Š” ์Šค์ผ€์ค„๋Ÿฌ๋งˆ๋‹ค ๋‹ค๋ฆ„

Basic Priority:

  • Nice โ†’ ์ •์  ์šฐ์„ ์ˆœ์œ„ ๋ณ€ํ™˜
  • priority = 31 - nice
  • ์šฐ์„ ์ˆœ์œ„ ์ž์ฒด๊ฐ€ ๋ณ€๊ฒฝ๋จ

MLFQS:

  • Nice โ†’ ๋™์  ์šฐ์„ ์ˆœ์œ„ ๊ณ„์‚ฐ์— ๊ธฐ์—ฌ
  • priority = PRI_MAX - (recent_cpu/4) - (nice*2)
  • nice๋Š” -2๋ฐฐ๋กœ๋งŒ ๊ธฐ์—ฌ (์•ฝํ•œ ํšจ๊ณผ)

CFS:

  • Nice โ†’ ๊ฐ€์ค‘์น˜ ๋ณ€ํ™˜
  • weight = PRIO_TO_WEIGHT[nice + 20]
  • CPU ์‹œ๊ฐ„ ๋น„์œจ ๊ฒฐ์ • (๊ฐ•ํ•œ ํšจ๊ณผ)

๊ฒฐ๋ก : Nice๊ฐ€ ํฌํ•จ๋œ ์›Œํฌ๋กœ๋“œ๋Š” ์Šค์ผ€์ค„๋Ÿฌ๋งˆ๋‹ค ๋‹ค๋ฅด๊ฒŒ ํ•ด์„๋˜๋ฏ€๋กœ, ๊ณต์ •ํ•œ ๋น„๊ต๋ฅผ ์œ„ํ•ด ๋Œ€๋ถ€๋ถ„์˜ ํ…Œ์ŠคํŠธ์—์„œ nice=0 ์‚ฌ์šฉ

3. ๊ณต์ •์„ฑ/Nice ํ…Œ์ŠคํŠธ๋Š” MLFQS vs CFS๋งŒ

์ด์œ :

  • Basic Priority๋Š” ์ •์  ์šฐ์„ ์ˆœ์œ„ ๊ธฐ๋ฐ˜ (starvation ์œ„ํ—˜)
  • ๊ณต์ •์„ฑ์„ ๋ชฉํ‘œ๋กœ ์„ค๊ณ„๋˜์ง€ ์•Š์Œ
  • Nice์˜ ์˜๋ฏธ๊ฐ€ ๋‹ค๋ฆ„ (์šฐ์„ ์ˆœ์œ„ vs ๊ฐ€์ค‘์น˜)

๊ฒฐ๊ณผ:

  • ์˜๋ฏธ ์žˆ๋Š” ๋น„๊ต๋งŒ ์ˆ˜ํ–‰
  • ๊ฐ ์Šค์ผ€์ค„๋Ÿฌ์˜ ๊ฐ•์ ์„ ๊ณต์ •ํ•˜๊ฒŒ ํ‰๊ฐ€

4. Simulation Time: 35,000 ticks

์ด์œ :

  • 50๊ฐœ ์Šค๋ ˆ๋“œ ์™„๋ฃŒ์— ํ•„์š”ํ•œ ์‹œ๊ฐ„: ~30,000 ticks
  • ์—ฌ์œ ๋ฅผ ๋‘๊ณ  35,000 ticks๋กœ ์„ค์ •
  • Nice ํšจ๊ณผ ํ…Œ์ŠคํŠธ๋Š” ์˜ˆ์™ธ (50% ์‹œ๊ฐ„์— ์ค‘๋‹จ)

5. Time Slice: 4 ticks

์ด์œ :

  • ๋„ˆ๋ฌด ์งง์œผ๋ฉด: Context switch ์˜ค๋ฒ„ํ—ค๋“œ ์ฆ๊ฐ€
  • ๋„ˆ๋ฌด ๊ธธ๋ฉด: ์‘๋‹ต์„ฑ ์ €ํ•˜
  • 4 ticks๋Š” ์ผ๋ฐ˜์ ์ธ Round-robin ์„ค์ •

์ฐธ๊ณ  ๋ฌธํ—Œ

ํ•™์ˆ  ์ž๋ฃŒ

  • MLFQS: 4.4BSD Scheduler, FreeBSD Implementation
  • CFS: "Inside the Linux 2.6 Completely Fair Scheduler" (IBM DeveloperWorks)
  • Fixed Point Arithmetic: Pintos Documentation (17.14 format)

์ฝ”๋“œ ์ฐธ์กฐ

  • Linux ์ปค๋„ kernel/sched/core.c (PRIO_TO_WEIGHT ํ…Œ์ด๋ธ”)
  • FreeBSD sys/kern/sched_4bsd.c (MLFQS ๊ตฌํ˜„)

๋ฉ”ํŠธ๋ฆญ

  • Jain's Fairness Index: "Quantitative Measure of Fairness" (Jain et al., 1984)

์Šค์ผ€์ค„๋Ÿฌ ๋ฒค์น˜๋งˆํฌ ํ”„๋กœ์ ํŠธ ์†Œ๊ฐ๋ฌธ

1. ํ”„๋กœ์ ํŠธ ๊ฐœ์š”

ํ”„๋กœ์ ํŠธ ๋ช…

CPU ์Šค์ผ€์ค„๋Ÿฌ ๋ฒค์น˜๋งˆํฌ ์‹œ์Šคํ…œ: Basic Priority, MLFQS, CFS ๋น„๊ต ๋ถ„์„

๊ฐœ๋ฐœ ํ™˜๊ฒฝ

  • ์–ธ์–ด: Python 3.8+
  • ํ”„๋ ˆ์ž„์›Œํฌ: Streamlit
  • ๋ฐฐํฌ: GCP VM (Ubuntu 24.04), http://34.47.105.226:8501
  • ๋ฒ„์ „ ๊ด€๋ฆฌ: Git/GitHub

ํ”„๋กœ์ ํŠธ ๋ฒ”์œ„

3๊ฐ€์ง€ ์‹ค์ œ ์šด์˜์ฒด์ œ ์Šค์ผ€์ค„๋Ÿฌ(Basic Priority, MLFQS 64-Queue, Linux CFS)๋ฅผ ๋ชฉํ‘œ ๊ธฐ๋ฐ˜ ํ…Œ์ŠคํŠธ๋กœ ๋น„๊ตํ•˜๋Š” ๋ฒค์น˜๋งˆํฌ ์‹œ์Šคํ…œ. 18๊ฐœ ํ…Œ์ŠคํŠธ, 6๊ฐœ ์นดํ…Œ๊ณ ๋ฆฌ๋กœ ๊ตฌ์„ฑ๋˜์–ด ๊ฐ ์Šค์ผ€์ค„๋Ÿฌ์˜ ๊ฐ•์ ๊ณผ ์•ฝ์ ์„ ์ •๋Ÿ‰์ ์œผ๋กœ ์ธก์ •.


2. ์ฃผ์ œ ์„ ์ • ๊ณผ์ •

2.1 ์ดˆ๊ธฐ ๋™๊ธฐ์™€ ๋ฌธ์ œ์˜์‹

ํ”„๋กœ์ ํŠธ๋ฅผ ์‹œ์ž‘ํ•˜๋ฉด์„œ ๊ฐ€์žฅ ํฐ ๊ณ ๋ฏผ์€ **"์–ด๋–ป๊ฒŒ ํ•˜๋ฉด ์šด์˜์ฒด์ œ ์ด๋ก ์„ ์‹ค์ œ๋กœ ๊ฒ€์ฆํ•  ์ˆ˜ ์žˆ์„๊นŒ?"**์˜€์Šต๋‹ˆ๋‹ค. OS๋ฅผ ํ•™์Šตํ•˜๋ฉด์„œ ๋ฐฐ์šด CPU ์Šค์ผ€์ค„๋ง ์•Œ๊ณ ๋ฆฌ์ฆ˜๋“ค์€ ์ด๋ก ์ ์œผ๋กœ๋Š” ๋ช…ํ™•ํ–ˆ์ง€๋งŒ, ์‹ค์ œ๋กœ ์–ด๋А ๊ฒƒ์ด ๋” ์ข‹์€์ง€, ์™œ Linux๊ฐ€ CFS๋ฅผ ์ฑ„ํƒํ–ˆ๋Š”์ง€, MLFQS๋Š” ์–ด๋–ค ์ƒํ™ฉ์—์„œ ์œ ๋ฆฌํ•œ์ง€ ๋“ฑ์˜ ์งˆ๋ฌธ์— ๋Œ€ํ•œ ๋ช…ํ™•ํ•œ ๋‹ต์ด ์—†์—ˆ์Šต๋‹ˆ๋‹ค.

๋‹จ์ˆœํžˆ "์ด๋ก ์„ ์•ˆ๋‹ค"๋Š” ๊ฒƒ๊ณผ "์‹ค์ œ๋กœ ๊ตฌํ˜„ํ•˜๊ณ  ์ธก์ •ํ•œ๋‹ค"๋Š” ๊ฒƒ ์‚ฌ์ด์—๋Š” ํฐ ์ฐจ์ด๊ฐ€ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ๊นจ๋‹ฌ์•˜๊ณ , ์ง์ ‘ ๊ตฌํ˜„ํ•ด๋ณด๊ธฐ๋กœ ๊ฒฐ์‹ฌํ–ˆ์Šต๋‹ˆ๋‹ค.

2.2 ์ดˆ๊ธฐ ์„ค๊ณ„์˜ ๋ฌธ์ œ์ 

์ฒ˜์Œ์—๋Š” ๋‹จ์ˆœํžˆ "3๊ฐœ ์Šค์ผ€์ค„๋Ÿฌ๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ  ๋ชจ๋“  ํ…Œ์ŠคํŠธ์—์„œ ๋น„๊ต"ํ•˜๋Š” ๊ฒƒ์„ ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๊ณง ์—ฌ๋Ÿฌ ๋ฌธ์ œ์ ์„ ๋ฐœ๊ฒฌํ–ˆ์Šต๋‹ˆ๋‹ค:

๋ฌธ์ œ 1: ๋น„๊ต ๊ธฐ์ค€์˜ ๋ชจํ˜ธํ•จ

์–ด๋–ค ๋ฉ”ํŠธ๋ฆญ์œผ๋กœ "๋” ์ข‹๋‹ค"๋ฅผ ํŒ๋‹จํ•  ๊ฒƒ์ธ๊ฐ€? ํ‰๊ท  ๋Œ€๊ธฐ ์‹œ๊ฐ„? ๋ฐ˜ํ™˜ ์‹œ๊ฐ„? ๊ณต์ •์„ฑ? ๊ฐ ์Šค์ผ€์ค„๋Ÿฌ๋Š” ์„œ๋กœ ๋‹ค๋ฅธ ๋ชฉํ‘œ๋ฅผ ๊ฐ€์ง€๊ณ  ์„ค๊ณ„๋˜์—ˆ๋Š”๋ฐ, ๋‹จ์ผ ๋ฉ”ํŠธ๋ฆญ์œผ๋กœ ๋น„๊ตํ•˜๋Š” ๊ฒƒ์ด ๊ณต์ •ํ•œ๊ฐ€?

๋ฌธ์ œ 2: ๊ณต์ •์„ฑ์˜ ๋ฌธ์ œ

Basic Priority๋Š” ์• ์ดˆ์— ๊ณต์ •์„ฑ์„ ๋ชฉํ‘œ๋กœ ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ •์  ์šฐ์„ ์ˆœ์œ„ ๊ธฐ๋ฐ˜์ด๋ฏ€๋กœ ๋‚ฎ์€ ์šฐ์„ ์ˆœ์œ„ ์Šค๋ ˆ๋“œ๋Š” starvation ์œ„ํ—˜์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฐ ์Šค์ผ€์ค„๋Ÿฌ๋ฅผ "๊ณต์ •์„ฑ ํ…Œ์ŠคํŠธ"์— ํฌํ•จ์‹œํ‚ค๋Š” ๊ฒƒ์€ ๋ถ€์ ์ ˆํ•ฉ๋‹ˆ๋‹ค.

๋ฌธ์ œ 3: Nice ๊ฐ’์˜ ์˜๋ฏธ ์ฐจ์ด

  • Basic Priority: nice โ†’ ์ •์  ์šฐ์„ ์ˆœ์œ„ ๋ณ€ํ™˜ (priority = 31 - nice)
  • MLFQS: nice โ†’ ๋™์  ์šฐ์„ ์ˆœ์œ„ ๊ณ„์‚ฐ์— ๊ธฐ์—ฌ (priority = PRI_MAX - recent_cpu/4 - 2*nice)
  • CFS: nice โ†’ ๊ฐ€์ค‘์น˜ ๋ณ€ํ™˜ (Linux PRIO_TO_WEIGHT ํ…Œ์ด๋ธ”)

๊ฐ ์Šค์ผ€์ค„๋Ÿฌ๊ฐ€ nice๋ฅผ ์™„์ „ํžˆ ๋‹ค๋ฅด๊ฒŒ ํ•ด์„ํ•˜๋Š”๋ฐ, ๋™์ผํ•œ nice ๊ฐ’์œผ๋กœ ๋น„๊ตํ•˜๋Š” ๊ฒƒ์ด ์˜๋ฏธ๊ฐ€ ์žˆ๋Š”๊ฐ€?

2.3 ํ•ต์‹ฌ ์ธ์‚ฌ์ดํŠธ: ๋ชฉํ‘œ ๊ธฐ๋ฐ˜ ํ…Œ์ŠคํŠธ ์„ค๊ณ„

๊ณ ๋ฏผ ๋์— ๋„๋‹ฌํ•œ ํ•ด๋‹ต์€ **"ํ…Œ์ŠคํŠธ๋ฅผ ๋ชฉํ‘œ/๊ฐœ๋…์œผ๋กœ ์ •์˜ํ•˜๊ณ , ๊ฐ ํ…Œ์ŠคํŠธ๋งˆ๋‹ค ์˜๋ฏธ ์žˆ๋Š” ์Šค์ผ€์ค„๋Ÿฌ๋งŒ ์„ ํƒ์ ์œผ๋กœ ๋น„๊ต"**ํ•˜๋Š” ๊ฒƒ์ด์—ˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด:

  • ์ผ๋ฐ˜ ์›Œํฌ๋กœ๋“œ ํ…Œ์ŠคํŠธ: 3๊ฐœ ๋ชจ๋‘ ๋น„๊ต (์ˆœ์ˆ˜ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ํšจ์œจ์„ฑ)

    • nice ๊ฐ’์€ 0 ๋˜๋Š” ์•ฝํ•œ ์ฐจ์ด(-5~5)
    • ๋ชฉํ‘œ: ์Šค์ผ€์ค„๋ง ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ž์ฒด์˜ ํšจ์œจ์„ฑ ๋น„๊ต
  • ๊ณต์ •์„ฑ ํ…Œ์ŠคํŠธ: MLFQS vs CFS๋งŒ

    • Basic์€ starvation ์œ„ํ—˜์ด ์žˆ์–ด ์ œ์™ธ
    • ๋ชฉํ‘œ: CPU ์‹œ๊ฐ„ ๋ฐฐ๋ถ„์˜ ๊ณต์ •์„ฑ ์ธก์ •
  • Nice ํšจ๊ณผ ํ…Œ์ŠคํŠธ: MLFQS vs CFS๋งŒ

    • Basic์˜ nice๋Š” ๋‹ค๋ฅธ ์˜๋ฏธ(์ •์  ์šฐ์„ ์ˆœ์œ„)
    • ๋ชฉํ‘œ: nice ๊ฐ’์ด ์‹ค์ œ CPU ์‹œ๊ฐ„ ๋ฐฐ๋ถ„์— ๋ฏธ์น˜๋Š” ์˜ํ–ฅ

์ด ๊ฒฐ์ •์ด ํ”„๋กœ์ ํŠธ์˜ ๊ฐ€์žฅ ์ค‘์š”ํ•œ ์ฐจ๋ณ„์ ์ด ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋‹จ์ˆœํ•œ "๋ชจ๋“  ์กฐํ•ฉ ๋น„๊ต"๊ฐ€ ์•„๋‹ˆ๋ผ, ๊ฐ ํ…Œ์ŠคํŠธ์˜ ๋ชฉํ‘œ์— ๋งž๋Š” ๊ณต์ •ํ•œ ๋น„๊ต๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ฒŒ ๋œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

2.4 ์Šค์ผ€์ค„๋Ÿฌ ์„ ํƒ๊ณผ ๋ฒ”์œ„ ์„ค์ •

์Šค์ผ€์ค„๋Ÿฌ ์„ ํƒ์—์„œ๋„ ์‹ ์ค‘ํ•œ ๊ณ ๋ฏผ์ด ํ•„์š”ํ–ˆ์Šต๋‹ˆ๋‹ค:

์„ ํƒ ๊ธฐ์ค€

  • ์‹ค์ œ ์šด์˜์ฒด์ œ์—์„œ ์‚ฌ์šฉ: ๊ฒ€์ฆ๋œ ์•Œ๊ณ ๋ฆฌ์ฆ˜
  • ๋ณต์žก๋„ ์ŠคํŽ™ํŠธ๋Ÿผ: ๋‹จ์ˆœ โ†’ ๋ณต์žก
  • ๊ตฌํ˜„ ๊ฐ€๋Šฅ์„ฑ: ์ œํ•œ๋œ ์‹œ๊ฐ„ ๋‚ด ์™„์„ฑ ๊ฐ€๋Šฅ

์ตœ์ข… ์„ ํƒ

1. Basic Priority Scheduler - ๋‹จ์ˆœํ•จ์˜ ๋ฏธํ•™

ํ•ต์‹ฌ ๊ฐœ๋…: Basic Priority๋Š” ๊ฐ€์žฅ ์ง๊ด€์ ์ธ ์Šค์ผ€์ค„๋Ÿฌ์ž…๋‹ˆ๋‹ค. ๊ฐ ์Šค๋ ˆ๋“œ์— "์šฐ์„ ์ˆœ์œ„ ์ˆซ์ž"๋ฅผ ๋ถ€์—ฌํ•˜๊ณ , ํ•ญ์ƒ ๊ฐ€์žฅ ๋†’์€ ์šฐ์„ ์ˆœ์œ„๋ฅผ ๊ฐ€์ง„ ์Šค๋ ˆ๋“œ๋ฅผ ๋จผ์ € ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

์ž‘๋™ ๋ฐฉ์‹:

Step 1: Nice ๊ฐ’์„ ์šฐ์„ ์ˆœ์œ„๋กœ ๋ณ€ํ™˜
  - nice -20 โ†’ priority 51 (์ตœ๊ณ  ์šฐ์„ ์ˆœ์œ„)
  - nice 0   โ†’ priority 31 (๋ณดํ†ต)
  - nice 19  โ†’ priority 12 (์ตœ์ € ์šฐ์„ ์ˆœ์œ„)

Step 2: Pick Next ์‹คํ–‰ ์‹œ
  - Ready queue์—์„œ priority๊ฐ€ ๊ฐ€์žฅ ๋†’์€ ์Šค๋ ˆ๋“œ ์ฐพ๊ธฐ
  - ๊ฐ™์€ priority๋ฉด ๋จผ์ € ๋“ค์–ด์˜จ ๊ฒƒ ์„ ํƒ (FIFO)

Step 3: Time Slice ๋งŒ๋ฃŒ ์‹œ
  - ์Šค๋ ˆ๋“œ๋ฅผ ready queue ๋งจ ๋’ค์— ์žฌ์‚ฝ์ž…
  - ์šฐ์„ ์ˆœ์œ„๋Š” ์ ˆ๋Œ€ ๋ณ€ํ•˜์ง€ ์•Š์Œ (์ •์  ์šฐ์„ ์ˆœ์œ„)

์žฅ์ :

  • ๋‹จ์ˆœํ•จ: ๊ตฌํ˜„์ด ์‰ฝ๊ณ , ๋™์ž‘์ด ์˜ˆ์ธก ๊ฐ€๋Šฅ
  • ๋‚ฎ์€ ์˜ค๋ฒ„ํ—ค๋“œ: ์šฐ์„ ์ˆœ์œ„ ์žฌ๊ณ„์‚ฐ ์—†์Œ
  • CPU-bound์— ์œ ๋ฆฌ: ๋ณต์žกํ•œ ๊ณ„์‚ฐ ์—†์ด ๋ฐ”๋กœ ์‹คํ–‰

๋‹จ์ :

  • ๋ถˆ๊ณต์ •์„ฑ: ๋†’์€ ์šฐ์„ ์ˆœ์œ„ ์Šค๋ ˆ๋“œ๊ฐ€ ๋…์  ๊ฐ€๋Šฅ
  • Starvation ์œ„ํ—˜: ๋‚ฎ์€ ์šฐ์„ ์ˆœ์œ„๋Š” ์˜์›ํžˆ ๋Œ€๊ธฐํ•  ์ˆ˜ ์žˆ์Œ
  • I/O ์‘๋‹ต์„ฑ ๋ถ€์กฑ: I/O ์Šค๋ ˆ๋“œ๋ฅผ ์ž๋™์œผ๋กœ ์šฐ๋Œ€ํ•˜์ง€ ์•Š์Œ

์‹ค์ œ ์‚ฌ์šฉ์ฒ˜: ๋งŽ์€ RTOS(Real-Time Operating System)์—์„œ ์‚ฌ์šฉ. ์˜ˆ์ธก ๊ฐ€๋Šฅ์„ฑ์ด ์ค‘์š”ํ•œ ์ž„๋ฒ ๋””๋“œ ์‹œ์Šคํ…œ์— ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค.


2. MLFQS (Multi-Level Feedback Queue Scheduler) - ์ ์‘ํ•˜๋Š” ์ง€๋Šฅ

ํ•ต์‹ฌ ๊ฐœ๋…: MLFQS๋Š” "์Šค๋ ˆ๋“œ๊ฐ€ ์–ด๋–ป๊ฒŒ ํ–‰๋™ํ•˜๋Š”์ง€ ๊ด€์ฐฐํ•˜๊ณ , ๊ทธ์— ๋งž๊ฒŒ ์šฐ์„ ์ˆœ์œ„๋ฅผ ๋™์ ์œผ๋กœ ์กฐ์ •"ํ•˜๋Š” ์Šค์ผ€์ค„๋Ÿฌ์ž…๋‹ˆ๋‹ค. CPU๋ฅผ ๋งŽ์ด ์“ฐ๋Š” ์Šค๋ ˆ๋“œ๋Š” ์šฐ์„ ์ˆœ์œ„๊ฐ€ ๋‚ด๋ ค๊ฐ€๊ณ , I/O ๋Œ€๊ธฐ๊ฐ€ ๋งŽ์€ ์Šค๋ ˆ๋“œ๋Š” ์šฐ์„ ์ˆœ์œ„๊ฐ€ ์˜ฌ๋ผ๊ฐ‘๋‹ˆ๋‹ค.

์ž‘๋™ ๋ฐฉ์‹:

Step 1: 64๊ฐœ์˜ ์šฐ์„ ์ˆœ์œ„ ํ ์ค€๋น„
  - ๊ฐ ์šฐ์„ ์ˆœ์œ„(0~63)๋งˆ๋‹ค ๋…๋ฆฝ๋œ ํ
  - ๋†’์€ ์šฐ์„ ์ˆœ์œ„ ํ๋ถ€ํ„ฐ ๊ฒ€์ƒ‰ โ†’ O(1) ์„ฑ๋Šฅ

Step 2: ์Šค๋ ˆ๋“œ ์‹คํ–‰ ์‹œ recent_cpu ์ฆ๊ฐ€
  - ๋งค tick๋งˆ๋‹ค running ์Šค๋ ˆ๋“œ์˜ recent_cpu++
  - "์ตœ๊ทผ ์–ผ๋งˆ๋‚˜ CPU๋ฅผ ์‚ฌ์šฉํ–ˆ๋Š”๊ฐ€"๋ฅผ ์ถ”์ 

Step 3: 4 ticks๋งˆ๋‹ค ์šฐ์„ ์ˆœ์œ„ ์žฌ๊ณ„์‚ฐ (๋ชจ๋“  ์Šค๋ ˆ๋“œ)
  priority = PRI_MAX - (recent_cpu / 4) - (nice * 2)

  ์˜ˆ์‹œ:
  - Thread A: recent_cpu=100, nice=0
    โ†’ priority = 63 - (100/4) - 0 = 38

  - Thread B: recent_cpu=10, nice=0 (I/O ๋Œ€๊ธฐ๊ฐ€ ๋งŽ์•˜์Œ)
    โ†’ priority = 63 - (10/4) - 0 = 60 (๋†’์€ ์šฐ์„ ์ˆœ์œ„!)

Step 4: 100 ticks๋งˆ๋‹ค recent_cpu ๊ฐ์‡ 
  recent_cpu = (2*load_avg)/(2*load_avg+1) * recent_cpu

  ์ด ๊ณต์‹์€ "์˜ค๋ž˜๋œ CPU ์‚ฌ์šฉ์€ ์ ์ฐจ ์žŠ์–ด๋ฒ„๋ฆผ"์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.
  ์˜ˆ: recent_cpu=1000 โ†’ 800 โ†’ 640 โ†’ 512... (์ ์  ๊ฐ์†Œ)

17.14 ๊ณ ์ •์†Œ์ˆ˜์ ์ด๋ž€? MLFQS๋Š” ๋ถ€๋™์†Œ์ˆ˜์  ์—ฐ์‚ฐ์„ ํ”ผํ•˜๊ธฐ ์œ„ํ•ด "17.14" ํ˜•์‹์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค:

  • ์ •์ˆ˜๋ฅผ 16384(2^14)๋ฐฐ ํ™•๋Œ€ํ•ด์„œ ์ €์žฅ
  • ์˜ˆ: 1.5๋ฅผ ์ €์žฅํ•˜๋ ค๋ฉด โ†’ 1.5 ร— 16384 = 24576 ์ €์žฅ
  • ๋‚˜๋ˆ—์…ˆ: a // 16384
  • ๊ณฑ์…ˆ: (a * b) // 16384

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ •์ˆ˜ ์—ฐ์‚ฐ๋งŒ์œผ๋กœ ์†Œ์ˆ˜์  ๊ณ„์‚ฐ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

์žฅ์ :

  • I/O ์‘๋‹ต์„ฑ ์šฐ์ˆ˜: I/O ๋Œ€๊ธฐ ์ค‘์—๋Š” recent_cpu๊ฐ€ ์ฆ๊ฐ€ํ•˜์ง€ ์•Š์•„ ์šฐ์„ ์ˆœ์œ„ ์œ ์ง€
  • CPU-bound ์ž๋™ ๊ฐ์ง€: CPU๋ฅผ ๋งŽ์ด ์“ฐ๋ฉด ์šฐ์„ ์ˆœ์œ„ ์ž๋™ ํ•˜๋ฝ
  • ๋™์  ์ ์‘: ์›Œํฌ๋กœ๋“œ ํŒจํ„ด ๋ณ€ํ™”์— ์ž๋™์œผ๋กœ ๋Œ€์‘

๋‹จ์ :

  • ๋ณต์žกํ•œ ๊ณ„์‚ฐ: 4 ticks๋งˆ๋‹ค ๋ชจ๋“  ์Šค๋ ˆ๋“œ ์žฌ๊ณ„์‚ฐ, 100 ticks๋งˆ๋‹ค load_avg ์žฌ๊ณ„์‚ฐ
  • Nice ํšจ๊ณผ ์•ฝํ•จ: recent_cpu ์ฆ๊ฐ€๊ฐ€ nice ๊ฐ’์„ ์••๋„ํ•  ์ˆ˜ ์žˆ์Œ
  • ์˜ˆ์ธก ์–ด๋ ค์›€: ์šฐ์„ ์ˆœ์œ„๊ฐ€ ๋™์ ์œผ๋กœ ๋ณ€ํ•˜๋ฏ€๋กœ ์‹คํ–‰ ์ˆœ์„œ ์˜ˆ์ธก ๊ณค๋ž€

์‹ค์ œ ์‚ฌ์šฉ์ฒ˜: FreeBSD 4.4BSD์˜ ๊ธฐ๋ณธ ์Šค์ผ€์ค„๋Ÿฌ. ๋ฒ”์šฉ ์„œ๋ฒ„/๋ฐ์Šคํฌํ†ฑ ํ™˜๊ฒฝ์— ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค.


3. CFS (Completely Fair Scheduler) - ์ ˆ๋Œ€ ๊ณต์ •์„ฑ์˜ ์ถ”๊ตฌ

ํ•ต์‹ฌ ๊ฐœ๋…: CFS๋Š” "๋ชจ๋“  ์Šค๋ ˆ๋“œ๊ฐ€ ์ •ํ™•ํžˆ ๊ณตํ‰ํ•˜๊ฒŒ CPU ์‹œ๊ฐ„์„ ๋ฐ›์•„์•ผ ํ•œ๋‹ค"๋Š” ์ฒ ํ•™์„ ๊ฐ€์ง„ ์Šค์ผ€์ค„๋Ÿฌ์ž…๋‹ˆ๋‹ค. "Virtual Runtime(vruntime)"์ด๋ผ๋Š” ๊ฐœ๋…์œผ๋กœ "๋ˆ„๊ฐ€ CPU๋ฅผ ๋œ ๋ฐ›์•˜๋Š”๊ฐ€"๋ฅผ ์ถ”์ ํ•˜๊ณ , ํ•ญ์ƒ ๊ฐ€์žฅ ์ ๊ฒŒ ๋ฐ›์€ ์Šค๋ ˆ๋“œ๋ฅผ ๋‹ค์Œ์— ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

์ž‘๋™ ๋ฐฉ์‹:

Step 1: ๊ฐ ์Šค๋ ˆ๋“œ๋Š” vruntime ๊ฐ’์„ ๊ฐ€์ง (์ฒ˜์Œ์—” ๋ชจ๋‘ 0)

Step 2: ์Šค๋ ˆ๋“œ๊ฐ€ 1 tick ์‹คํ–‰๋˜๋ฉด vruntime ์ฆ๊ฐ€
  delta_vruntime = (1 tick ร— NICE_0_WEIGHT) / weight
  vruntime += delta_vruntime

  weight๋Š” nice ๊ฐ’์— ๋”ฐ๋ผ ๋‹ค๋ฆ„:
  - nice -20 โ†’ weight 88761 (๋งค์šฐ ํผ)
  - nice 0   โ†’ weight 1024
  - nice 19  โ†’ weight 15 (๋งค์šฐ ์ž‘์Œ)

Step 3: ๊ตฌ์ฒด์ ์ธ ๊ณ„์‚ฐ ์˜ˆ์‹œ
  1 tick ์‹คํ–‰ ํ›„ vruntime ์ฆ๊ฐ€๋Ÿ‰:

  nice -20 (weight=88761):
    delta = (1 ร— 1024 ร— 1000) / 88761 = 11
    โ†’ vruntime์ด ์•„์ฃผ ์ฒœ์ฒœํžˆ ์ฆ๊ฐ€

  nice 0 (weight=1024):
    delta = (1 ร— 1024 ร— 1000) / 1024 = 1000
    โ†’ ๊ธฐ์ค€ ์†๋„๋กœ ์ฆ๊ฐ€

  nice 19 (weight=15):
    delta = (1 ร— 1024 ร— 1000) / 15 = 68266
    โ†’ vruntime์ด ๋งค์šฐ ๋น ๋ฅด๊ฒŒ ์ฆ๊ฐ€

Step 4: Pick Next ์‹คํ–‰ ์‹œ
  - vruntime์ด ๊ฐ€์žฅ ์ž‘์€ ์Šค๋ ˆ๋“œ ์„ ํƒ
  - "CPU๋ฅผ ๊ฐ€์žฅ ์ ๊ฒŒ ๋ฐ›์€ ์Šค๋ ˆ๋“œ"๋ฅผ ์˜๋ฏธ

์™œ ์ด๊ฒŒ ๊ณต์ •ํ•œ๊ฐ€?

์˜ˆ์‹œ: Thread A (nice -20), Thread B (nice 0)

Tick 1: A ์‹คํ–‰ โ†’ vruntime_A = 0+11 = 11
Tick 2: B ์‹คํ–‰ โ†’ vruntime_B = 0+1000 = 1000
Tick 3: A ์‹คํ–‰ (11 < 1000์ด๋ฏ€๋กœ) โ†’ vruntime_A = 11+11 = 22
Tick 4: A ์‹คํ–‰ (22 < 1000์ด๋ฏ€๋กœ) โ†’ vruntime_A = 22+11 = 33
...
Tick 92: A ์‹คํ–‰ โ†’ vruntime_A = 1001
Tick 93: B ์‹คํ–‰ (1001 > 1000์ด๋ฏ€๋กœ) โ†’ vruntime_B = 1000+1000 = 2000

๊ฒฐ๊ณผ: A๊ฐ€ 91 ticks, B๊ฐ€ 1 tick ์‹คํ–‰
๋น„์œจ: 91:1 โ‰ˆ weight ๋น„์œจ (88761:1024 โ‰ˆ 87:1)

vruntime์€ ๋ชจ๋“  ์Šค๋ ˆ๋“œ๋ฅผ "๊ฐ€์ƒ์˜ ๊ณตํ‰ํ•œ ์ฒ™๋„"๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์‹ค์ œ ์‹คํ–‰ ์‹œ๊ฐ„์€ ๋‹ค๋ฅด์ง€๋งŒ, vruntime์€ ๊ฑฐ์˜ ๊ฐ™์€ ์†๋„๋กœ ์ฆ๊ฐ€ํ•˜๋„๋ก ์กฐ์ •๋ฉ๋‹ˆ๋‹ค.

Linux PRIO_TO_WEIGHT ํ…Œ์ด๋ธ”: CFS๋Š” Linux ์ปค๋„๊ณผ ์ •ํ™•ํžˆ ๋™์ผํ•œ ๊ฐ€์ค‘์น˜ ํ…Œ์ด๋ธ”์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค:

[88761, 71755, 56483, 46273, 36291,  # nice -20 ~ -16
 29154, 23254, 18705, 14949, 11916,  # nice -15 ~ -11
 9548, 7620, 6100, 4904, 3906,       # nice -10 ~ -6
 3121, 2501, 1991, 1586, 1277,       # nice -5 ~ -1
 1024,                                # nice 0 (๊ธฐ์ค€๊ฐ’)
 820, 655, 526, 423, 335,             # nice 1 ~ 5
 272, 215, 172, 137, 110,             # nice 6 ~ 10
 87, 70, 56, 45, 36,                  # nice 11 ~ 15
 29, 23, 18, 15]                      # nice 16 ~ 19

์ด ํ…Œ์ด๋ธ”์˜ ํ•ต์‹ฌ์€: nice 1 ์ฐจ์ด = ์•ฝ 1.25๋ฐฐ ๊ฐ€์ค‘์น˜ ์ฐจ์ด = ์•ฝ 10% CPU ์‹œ๊ฐ„ ์ฐจ์ด์ž…๋‹ˆ๋‹ค.

์žฅ์ :

  • ์™„๋ฒฝํ•œ ๊ณต์ •์„ฑ: ๋ชจ๋“  ์Šค๋ ˆ๋“œ๊ฐ€ weight์— ๋น„๋ก€ํ•˜์—ฌ ์ •ํ™•ํžˆ CPU ๋ฐ›์Œ
  • ๊ฐ•ํ•œ nice ํšจ๊ณผ: nice ๊ฐ’์ด CPU ์‹œ๊ฐ„์— ์ง์ ‘์ ์œผ๋กœ ์˜ํ–ฅ
  • ์˜ˆ์ธก ๊ฐ€๋Šฅ์„ฑ: vruntime ๊ณ„์‚ฐ์ด ๋‹จ์ˆœํ•˜๊ณ  ๋ช…ํ™•

๋‹จ์ :

  • I/O ์šฐ๋Œ€ ์—†์Œ: I/O ๋Œ€๊ธฐ ์ค‘์—๋„ vruntime์€ ์ฆ๊ฐ€ํ•˜์ง€ ์•Š์ง€๋งŒ, ํŠน๋ณ„ํžˆ ์šฐ๋Œ€ํ•˜์ง€๋„ ์•Š์Œ
  • ์•ฝ๊ฐ„์˜ ์˜ค๋ฒ„ํ—ค๋“œ: ๋งค tick๋งˆ๋‹ค vruntime ๊ณ„์‚ฐ ๋ฐ ์žฌ์ •๋ ฌ ํ•„์š”

์‹ค์ œ ์‚ฌ์šฉ์ฒ˜: Linux 2.6.23 ์ดํ›„ ๊ธฐ๋ณธ ์Šค์ผ€์ค„๋Ÿฌ. ๋ฐ์Šคํฌํ†ฑ, ์„œ๋ฒ„, ๋ชจ๋ฐ”์ผ ๋“ฑ ๊ฑฐ์˜ ๋ชจ๋“  Linux ์‹œ์Šคํ…œ.


์ด ์กฐํ•ฉ์€ ๋ณต์žก๋„์˜ ์ŠคํŽ™ํŠธ๋Ÿผ(Basic โ†’ MLFQS โ†’ CFS)์„ ์ž˜ ํ‘œํ˜„ํ•˜๋ฉด์„œ๋„, ๊ฐ๊ฐ์ด ์‹ค์ œ ์šด์˜์ฒด์ œ์—์„œ ์‚ฌ์šฉ๋˜๋Š” ๊ฒ€์ฆ๋œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด๋ผ๋Š” ์ ์—์„œ ์˜๋ฏธ๊ฐ€ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.


3. ๊ตฌํ˜„ ๊ณผ์ •์—์„œ์˜ ์–ด๋ ค์›€๊ณผ ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ…

3.1 Critical Bug #1: Time Slice ๋ฏธ๊ตฌํ˜„

๋ฌธ์ œ ๋ฐœ๊ฒฌ๊ณผ ์ฆ์ƒ

์ฒ˜์Œ ๋ฒค์น˜๋งˆํฌ๋ฅผ ์‹คํ–‰ํ–ˆ์„ ๋•Œ ๋ชจ๋“  ์Šค์ผ€์ค„๋Ÿฌ๊ฐ€ ์ •ํ™•ํžˆ ๊ฐ™์€ ๊ฒฐ๊ณผ๋ฅผ ๋ƒˆ์Šต๋‹ˆ๋‹ค. ํ‰๊ท  ๋Œ€๊ธฐ ์‹œ๊ฐ„, ๋ฐ˜ํ™˜ ์‹œ๊ฐ„, ๊ณต์ •์„ฑ ์ง€์ˆ˜ ๋ชจ๋‘ ๋™์ผ. ๊ฐœ์„ ์œจ์€ ๋ชจ๋‘ 0%, ์Šน์ž๋Š” ํ•ญ์ƒ tie.

์›์ธ ๋ถ„์„

๋””๋ฒ„๊น…์„ ์‹œ์ž‘ํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ฐ ์Šค์ผ€์ค„๋Ÿฌ์˜ pick_next() ํ•จ์ˆ˜๋Š” ์ œ๋Œ€๋กœ ์ž‘๋™ํ–ˆ์Šต๋‹ˆ๋‹ค. ์šฐ์„ ์ˆœ์œ„ ๊ณ„์‚ฐ๋„ ์ •์ƒ์ด์—ˆ์Šต๋‹ˆ๋‹ค. ๋ฌธ์ œ๋Š” ์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ์— ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

# ๋ฌธ์ œ๊ฐ€ ์žˆ๋˜ ์ดˆ๊ธฐ ์ฝ”๋“œ
while not scheduler.is_empty():
    thread = scheduler.pick_next()
    # ์Šค๋ ˆ๋“œ๊ฐ€ ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ๊ณ„์† ์‹คํ–‰!
    while thread.remaining_time > 0:
        thread.remaining_time -= 1
        current_tick += 1
    # ์™„๋ฃŒ๋œ ์Šค๋ ˆ๋“œ ์ฒ˜๋ฆฌ

์Šค๋ ˆ๋“œ๊ฐ€ ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ๊ณ„์† ์‹คํ–‰๋˜๊ณ  ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์„ ์ (preemption)์ด ์ „ํ˜€ ์ผ์–ด๋‚˜์ง€ ์•Š์•˜๋˜ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ์— time slice ๊ฐœ๋… ์ž์ฒด๊ฐ€ ์—†์—ˆ์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ์น˜๋ช…์ ์ธ ์˜ค๋ฅ˜์˜€์Šต๋‹ˆ๋‹ค. Round-robin์˜ ํ•ต์‹ฌ์€ time slice์ธ๋ฐ, ์ด๊ฒƒ ์—†์ด๋Š” ๋ชจ๋“  ์Šค์ผ€์ค„๋Ÿฌ๊ฐ€ ์‚ฌ์‹ค์ƒ FCFS(First-Come, First-Served)๋กœ ๋™์ž‘ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

ํ•ด๊ฒฐ ๊ณผ์ •

  1. Time slice ์ƒ์ˆ˜ ์ •์˜: TIME_SLICE = 4 ticks
  2. ํ˜„์žฌ time slice ์ถ”์ : current_slice_remaining ๋ณ€์ˆ˜ ์ถ”๊ฐ€
  3. Time slice ๋งŒ๋ฃŒ ์ฒ˜๋ฆฌ: ๋งŒ๋ฃŒ ์‹œ thread_yield() ํ˜ธ์ถœ
# ์ˆ˜์ •๋œ ์ฝ”๋“œ
TIME_SLICE = 4

while not scheduler.is_empty():
    thread = scheduler.pick_next()
    current_slice_remaining = TIME_SLICE

    while thread.remaining_time > 0 and current_slice_remaining > 0:
        # CPU ์‚ฌ์šฉ
        thread.remaining_time -= 1
        current_slice_remaining -= 1
        current_tick += 1

        # I/O ์ฒ˜๋ฆฌ ๋“ฑ...

    # Time slice ๋งŒ๋ฃŒํ–ˆ์ง€๋งŒ ์Šค๋ ˆ๋“œ๋Š” ์•„์ง ์™„๋ฃŒ ์•ˆ ๋จ
    if thread.remaining_time > 0:
        scheduler.thread_yield(thread)  # ๋‹ค์‹œ ready queue๋กœ

๊ฒฐ๊ณผ์™€ ๊ฒ€์ฆ

Time slice๋ฅผ ์ถ”๊ฐ€ํ•œ ํ›„, ๋“œ๋””์–ด ๊ฐ ์Šค์ผ€์ค„๋Ÿฌ๊ฐ€ ์„œ๋กœ ๋‹ค๋ฅธ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์ด๊ธฐ ์‹œ์ž‘ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ˆ˜์ • ์ „์—๋Š” ๋ชจ๋“  ์Šค์ผ€์ค„๋Ÿฌ์˜ ๊ฒฐ๊ณผ๊ฐ€ ๋™์ผํ–ˆ์ง€๋งŒ, ์ˆ˜์ • ํ›„์—๋Š” ๊ฐ ์Šค์ผ€์ค„๋Ÿฌ๊ฐ€ ์ž์‹ ๋งŒ์˜ ํŠน์„ฑ์— ๋”ฐ๋ผ ๋‹ค๋ฅธ ์„ฑ๋Šฅ์„ ๋ณด์—ฌ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

๋ฐฐ์šด ์ 

  • ์ด๋ก ๊ณผ ๊ตฌํ˜„์˜ ๊ดด๋ฆฌ: ์ด๋ก ์—์„œ๋Š” "Round-robin์€ time slice๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค"๊ฐ€ ๋‹น์—ฐํ•˜์ง€๋งŒ, ๊ตฌํ˜„์—์„œ๋Š” ๋ช…์‹œ์ ์œผ๋กœ ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ํ…Œ์ŠคํŠธ์˜ ์ค‘์š”์„ฑ: "๋ชจ๋‘ ๊ฐ™๋‹ค"๋Š” ๊ฒƒ์€ ๋ช…๋ฐฑํžˆ ์ด์ƒํ•œ ๊ฒฐ๊ณผ์˜€๊ณ , ์ด๋ฅผ ๋ฏผ๊ฐํ•˜๊ฒŒ ๊ฐ์ง€ํ•œ ๊ฒƒ์ด ๋ฒ„๊ทธ ๋ฐœ๊ฒฌ์˜ ์‹œ์ž‘์ด์—ˆ์Šต๋‹ˆ๋‹ค.

3.2 Critical Bug #2: CFS vruntime ์ •๋ฐ€๋„ ๋ฌธ์ œ

๋ฌธ์ œ ๋ฐœ๊ฒฌ

CFS๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ  ํ…Œ์ŠคํŠธํ–ˆ์„ ๋•Œ, ์ด์ƒํ•œ ํ˜„์ƒ์ด ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. ๋ชจ๋“  ์Šค๋ ˆ๋“œ์˜ vruntime์ด ํ•ญ์ƒ 0์ด์—ˆ์Šต๋‹ˆ๋‹ค:

Thread 1 (nice -20, weight 88761): vruntime=0
Thread 2 (nice 0,   weight 1024):  vruntime=0
Thread 3 (nice 19,  weight 15):    vruntime=0

nice ๊ฐ’์ด ๊ทน๋‹จ์ ์œผ๋กœ ๋‹ค๋ฅธ๋ฐ๋„ vruntime์ด ๋ชจ๋‘ 0์œผ๋กœ ๋™์ผํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ CFS์˜ ํ•ต์‹ฌ ๋ฉ”์ปค๋‹ˆ์ฆ˜์ด ์ž‘๋™ํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์˜๋ฏธ์˜€์Šต๋‹ˆ๋‹ค.

์›์ธ ๋ถ„์„: ์ •์ˆ˜ ๋‚˜๋ˆ—์…ˆ์˜ ํ•จ์ •

๋ฌธ์ œ๋Š” delta vruntime ๊ณ„์‚ฐ ํ•จ์ˆ˜์— ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค:

# Linux ์ปค๋„ ์Šคํƒ€์ผ ๊ณต์‹ (์ด๋ก )
delta_vruntime = delta_exec * (NICE_0_WEIGHT / weight)

# ์ž˜๋ชป๋œ ๊ตฌํ˜„ (์ •์ˆ˜ ๋‚˜๋ˆ—์…ˆ)
def calc_delta_vruntime(delta, weight):
    return (delta * 1024) // weight

nice -20์ผ ๋•Œ weight๋Š” 88761์ž…๋‹ˆ๋‹ค. ๊ณ„์‚ฐํ•ด๋ณด๋ฉด:

delta = 1 (1 tick ์‹คํ–‰)
(1 * 1024) // 88761 = 1024 // 88761 = 0

Python์˜ //๋Š” ์ •์ˆ˜ ๋‚˜๋ˆ—์…ˆ(floor division)์ด๋ฏ€๋กœ, 1024๋ฅผ 88761๋กœ ๋‚˜๋ˆ„๋ฉด 0์ด ๋ฉ๋‹ˆ๋‹ค!

์ด๊ฒƒ์€ nice -20(์ตœ๊ณ  ์šฐ์„ ์ˆœ์œ„)์ผ ๋•Œ vruntime์ด ์ „ํ˜€ ์ฆ๊ฐ€ํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์˜๋ฏธ์ž…๋‹ˆ๋‹ค. ๋ฐ˜๋Œ€๋กœ nice 19(์ตœ์ € ์šฐ์„ ์ˆœ์œ„)์ผ ๋•Œ๋Š”:

(1 * 1024) // 15 = 68

ํ•˜์ง€๋งŒ ์ด๊ฒƒ๋„ ์ด๋ก ๊ฐ’(68266)๊ณผ๋Š” ํฌ๊ฒŒ ๋‹ค๋ฆ…๋‹ˆ๋‹ค.

ํ•ด๊ฒฐ ๊ณผ์ •: ์Šค์ผ€์ผ ์ฆ๊ฐ€

์ •๋ฐ€๋„๋ฅผ ํ™•๋ณดํ•˜๊ธฐ ์œ„ํ•ด 1000๋ฐฐ ์Šค์ผ€์ผ์„ ์ฆ๊ฐ€์‹œ์ผฐ์Šต๋‹ˆ๋‹ค:

# ์ˆ˜์ •๋œ ์ฝ”๋“œ
def calc_delta_vruntime(delta, weight):
    # 1000๋ฐฐ ์Šค์ผ€์ผ ์ฆ๊ฐ€๋กœ ์ •๋ฐ€๋„ ํ™•๋ณด
    return (delta * 1024 * 1000) // weight

์ด์ œ ๊ณ„์‚ฐํ•ด๋ณด๋ฉด:

nice -20 (weight 88761):
  (1 * 1024 * 1000) // 88761 = 1,024,000 // 88761 = 11

nice 0 (weight 1024):
  (1 * 1024 * 1000) // 1024 = 1,024,000 // 1024 = 1000

nice 19 (weight 15):
  (1 * 1024 * 1000) // 15 = 1,024,000 // 15 = 68,266

๊ฒ€์ฆ: ์ด๋ก ๊ฐ’๊ณผ ๋น„๊ต

์ด๋ก ์ ์œผ๋กœ nice -20๊ณผ nice 19์˜ CPU ์‹œ๊ฐ„ ๋น„์œจ์€:

weight(-20) / weight(19) = 88761 / 15 โ‰ˆ 5917:1

vruntime ์ฆ๊ฐ€ ๋น„์œจ์€ ๊ทธ ์—ญ์ˆ˜์ด๋ฏ€๋กœ:

delta_vruntime(19) / delta_vruntime(-20) = 68266 / 11 โ‰ˆ 6206

์ด๋Š” ์ด๋ก ๊ฐ’๊ณผ ๋งค์šฐ ๊ฐ€๊น์Šต๋‹ˆ๋‹ค.

๊ฒฐ๊ณผ

Before fix:
  All threads: vruntime=0 (no differentiation)
  CFS behaves like FIFO

After fix:
  nice -20: vruntime += 11/tick  (๋งค์šฐ ๋А๋ฆฌ๊ฒŒ ์ฆ๊ฐ€)
  nice 19:  vruntime += 68266/tick  (๋งค์šฐ ๋น ๋ฅด๊ฒŒ ์ฆ๊ฐ€)
  โ†’ nice -20 ์Šค๋ ˆ๋“œ๊ฐ€ ํ›จ์”ฌ ์ž์ฃผ ์„ ํƒ๋จ (์˜๋„๋Œ€๋กœ!)

๋ฐฐ์šด ์ 

  • ์ •์ˆ˜ ์—ฐ์‚ฐ์˜ ํ•จ์ •: Python๋„ //๋Š” ์ •์ˆ˜ ๋‚˜๋ˆ—์…ˆ์ž…๋‹ˆ๋‹ค. ๋ถ€๋™์†Œ์ˆ˜์ ์„ ํ”ผํ•˜๋ฉด์„œ ์ •๋ฐ€๋„๋ฅผ ์œ ์ง€ํ•˜๋ ค๋ฉด ์ถฉ๋ถ„ํžˆ ํฐ ์Šค์ผ€์ผ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
  • Linux ์ปค๋„์˜ ์ง€ํ˜œ: ์‹ค์ œ Linux ์ปค๋„๋„ NICE_0_LOAD = 1024๋ฅผ ์‚ฌ์šฉํ•˜๋ฉฐ, ์ด๋Š” ์ •๋ฐ€๋„์™€ ์„ฑ๋Šฅ์˜ ๊ท ํ˜•์ž…๋‹ˆ๋‹ค.
  • ์ด๋ก  vs ๊ตฌํ˜„: ์ˆ˜ํ•™์ ์œผ๋กœ๋Š” delta / weight์ง€๋งŒ, ์ปดํ“จํ„ฐ์—์„œ๋Š” (delta * scale) // weight๋กœ ๋ณ€ํ™˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ๊ณ ์ •์†Œ์ˆ˜์  ์—ฐ์‚ฐ: ์šด์˜์ฒด์ œ๋Š” ๋ถ€๋™์†Œ์ˆ˜์ ์„ ํ”ผํ•˜๊ณ , ๋Œ€์‹  ๊ณ ์ •๋œ ์Šค์ผ€์ผ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค (MLFQS์˜ 17.14, CFS์˜ 1024ร—1000).

3.3 Subtle Bug #3: MLFQS Nice ๋ฎ์–ด์“ฐ๊ธฐ

๋ฌธ์ œ ๋ฐœ๊ฒฌ

"Nice ํšจ๊ณผ ํ…Œ์ŠคํŠธ"๋ฅผ ์‹คํ–‰ํ–ˆ์„ ๋•Œ, MLFQS์˜ ๊ฒฐ๊ณผ๊ฐ€ ์ด์ƒํ–ˆ์Šต๋‹ˆ๋‹ค:

Expected: nice -20 vs nice 19 โ†’ CPU time ratio ~1000:1
Actual:   CPU time ratio = 1:1

CFS๋Š” ์ œ๋Œ€๋กœ ์ž‘๋™ํ•˜๋Š”๋ฐ, MLFQS๋งŒ 1:1์ด์—ˆ์Šต๋‹ˆ๋‹ค.

์›์ธ ๋ถ„์„

MLFQS ์ฝ”๋“œ๋ฅผ ๋””๋ฒ„๊น…ํ•˜๋˜ ์ค‘, add_thread() ํ•จ์ˆ˜์—์„œ ์ถฉ๊ฒฉ์ ์ธ ๋ฐœ๊ฒฌ์„ ํ–ˆ์Šต๋‹ˆ๋‹ค:

# MLFQS์˜ add_thread() ์ฝ”๋“œ
def add_thread(self, thread):
    thread.nice = 0  # โ† ์ด ๋ผ์ธ!
    thread.recent_cpu = 0
    thread.priority = self.PRI_MAX
    self.queues[thread.priority].append(thread)

์›Œํฌ๋กœ๋“œ ์ƒ์„ฑ ์‹œ ์„ค์ •ํ•œ nice ๊ฐ’(-20, 19)์ด ์Šค์ผ€์ค„๋Ÿฌ ์ถ”๊ฐ€ ์‹œ ๋ชจ๋‘ 0์œผ๋กœ ๋ฎ์–ด์จ์ง€๊ณ  ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค!

์ด๊ฒƒ์€ ์ œ ์‹ค์ˆ˜์˜€์Šต๋‹ˆ๋‹ค. recent_cpu์™€ priority๋Š” ์ดˆ๊ธฐํ™”ํ•ด์•ผ ํ•˜์ง€๋งŒ, nice๋Š” ์›Œํฌ๋กœ๋“œ์—์„œ ์„ค์ •ํ•œ ๊ฐ’์„ ๋ณด์กดํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

ํ•ด๊ฒฐ ๊ณผ์ •

# ์ˆ˜์ •๋œ ์ฝ”๋“œ
def add_thread(self, thread):
    # thread.nice = 0  โ† ์ด ๋ผ์ธ ์ œ๊ฑฐ!
    if thread.recent_cpu is None:
        thread.recent_cpu = 0
    thread.priority = self.PRI_MAX - (thread.recent_cpu // 4) - (thread.nice * 2)
    self.queues[thread.priority].append(thread)

๊ฒฐ๊ณผ

Before: CPU time ratio = 1:1 (๋ชจ๋“  ์Šค๋ ˆ๋“œ nice=0์ด๋ฏ€๋กœ)
After:  CPU time ratio์—์„œ nice -20๊ณผ nice 19์˜ ๊ทน๋‹จ์  ์ฐจ์ด ๋ฐœ์ƒ

๋ฐฐ์šด ์ 

  • ์ดˆ๊ธฐํ™” vs ๋ณด์กด: ์–ด๋–ค ๊ฐ’์€ ์ดˆ๊ธฐํ™”ํ•ด์•ผ ํ•˜๊ณ (recent_cpu, priority), ์–ด๋–ค ๊ฐ’์€ ๋ณด์กดํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค(nice, burst_time).
  • ์ฑ…์ž„์˜ ๋ถ„๋ฆฌ: ์›Œํฌ๋กœ๋“œ ์ƒ์„ฑ๊ธฐ๋Š” ์Šค๋ ˆ๋“œ์˜ ํŠน์„ฑ(nice, burst_time)์„ ์„ค์ •ํ•˜๊ณ , ์Šค์ผ€์ค„๋Ÿฌ๋Š” ์ด๋ฅผ ์กด์ค‘ํ•˜๋ฉฐ ์ž์‹ ์˜ ๋‚ด๋ถ€ ์ƒํƒœ(recent_cpu, priority)๋งŒ ๊ด€๋ฆฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ํ…Œ์ŠคํŠธ์˜ ์ค‘์š”์„ฑ: Nice ํšจ๊ณผ ํ…Œ์ŠคํŠธ๊ฐ€ ์—†์—ˆ๋‹ค๋ฉด ์ด ๋ฒ„๊ทธ๋ฅผ ๋ฐœ๊ฒฌํ•˜์ง€ ๋ชปํ–ˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

3.4 Measurement Bug #4: Nice ํšจ๊ณผ ์ธก์ • ๋ถˆ๊ฐ€

๋ฌธ์ œ ๋ฐœ๊ฒฌ

MLFQS Nice ๋ฒ„๊ทธ๋ฅผ ์ˆ˜์ •ํ•œ ํ›„์—๋„ ์—ฌ์ „ํžˆ ๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. CPU time ratio๊ฐ€ 1:1๋กœ ๋‚˜์™”์Šต๋‹ˆ๋‹ค.

์›์ธ ๋ถ„์„: ์ธก์ • ๋ฐฉ๋ฒ•์˜ ์˜ค๋ฅ˜

๋ฌธ์ œ๋Š” ์ธก์ • ๋ฐฉ๋ฒ•์— ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์‹œ๋ฎฌ๋ ˆ์ด์…˜์ด ๋๋‚  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฌ๋ฉด, ๋ชจ๋“  ์Šค๋ ˆ๋“œ๊ฐ€ ์™„๋ฃŒ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด:

Thread 1 (nice -20, burst_time=300): cpu_time=300 (์™„๋ฃŒ)
Thread 2 (nice 19,  burst_time=300): cpu_time=300 (์™„๋ฃŒ)
Ratio: 300/300 = 1:1

๊ฐ ์Šค๋ ˆ๋“œ๋Š” ์ •ํ™•ํžˆ burst_time๋งŒํผ CPU๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. nice ๊ฐ’๊ณผ ๋ฌด๊ด€ํ•˜๊ฒŒ!

Nice๋Š” "์–ผ๋งˆ๋‚˜ ๋นจ๋ฆฌ ์™„๋ฃŒ๋˜๋Š”๊ฐ€"์— ์˜ํ–ฅ์„ ์ฃผ์ง€, "์ตœ์ข… CPU ์‹œ๊ฐ„"์—๋Š” ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

nice -20 ์Šค๋ ˆ๋“œ๋Š” 1000 tick์— ์™„๋ฃŒ๋˜๊ณ , nice 19 ์Šค๋ ˆ๋“œ๋Š” 10000 tick์— ์™„๋ฃŒ๋˜์ง€๋งŒ, ๋‘˜ ๋‹ค ์ตœ์ข…์ ์œผ๋กœ๋Š” burst_time๋งŒํผ CPU๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

ํ•ด๊ฒฐ ๊ณผ์ •: ์ธก์ • ์‹œ์  ๋ณ€๊ฒฝ

Nice ํšจ๊ณผ๋ฅผ ์ธก์ •ํ•˜๋ ค๋ฉด ์ผ๋ถ€๋งŒ ์™„๋ฃŒํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค:

  1. burst_time ์ฆ๊ฐ€: 300 โ†’ 2,000 (MLFQS ์„ฑ๋Šฅ ๊ณ ๋ ค)
  2. ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ์กฐ๊ธฐ ์ข…๋ฃŒ: 20% ์‹œ๊ฐ„์— ์ค‘๋‹จ (max_ticks=20,000)
# app.py์— ์ถ”๊ฐ€๋œ ์ฝ”๋“œ
if selected_test.test_id == "nice_effect":
    total_work = sum(t.burst_time for t in base_threads)
    actual_max_ticks = int(total_work * 0.5)  # 50% ์‹œ๊ฐ„๋งŒ ์‹คํ–‰
    st.info(f"Nice ํšจ๊ณผ ์ธก์ •: {actual_max_ticks:,} ticks์—์„œ ์ค‘๋‹จ")

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด:

nice -20 ์Šค๋ ˆ๋“œ: ๋Œ€๋ถ€๋ถ„ ์™„๋ฃŒ
nice 19 ์Šค๋ ˆ๋“œ: ๊ฑฐ์˜ ์‹œ์ž‘ ์•ˆ ํ•จ
โ†’ CPU time ratio์—์„œ ํฐ ์ฐจ์ด ๋ฐœ์ƒ

๊ฒฐ๊ณผ

MLFQS๋Š” ๋งค์šฐ ๊ฐ•ํ•œ nice ํšจ๊ณผ๋ฅผ, CFS๋Š” ๊ฐ€์ค‘์น˜ ๋น„๋ก€ ๋ฐฐ๋ถ„์„ ๋ณด์ž„.

๋ฐฐ์šด ์ 

  • ์ธก์ • ๋ฐฉ๋ฒ•๋ก ์˜ ์ค‘์š”์„ฑ: "๋ฌด์—‡์„ ์ธก์ •ํ•  ๊ฒƒ์ธ๊ฐ€"๋งŒํผ "์–ด๋–ป๊ฒŒ ์ธก์ •ํ•  ๊ฒƒ์ธ๊ฐ€"๋„ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.
  • ์™„๋ฃŒ vs ์ง„ํ–‰ ์ค‘: Nice ํšจ๊ณผ๋Š” "์ง„ํ–‰ ์ค‘"์ผ ๋•Œ ๋“œ๋Ÿฌ๋‚˜๋ฏ€๋กœ, ์˜๋„์ ์œผ๋กœ ์ค‘๋‹จํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ์ด๋ก ๊ณผ ์‹คํ—˜์˜ ์ฐจ์ด: ์ด๋ก ๊ฐ’๊ณผ ์‹ค์ œ๊ฐ’์˜ ์ฐจ์ด๋Š” ์ปจํ…์ŠคํŠธ ์Šค์œ„์น˜ ์˜ค๋ฒ„ํ—ค๋“œ, time slice ํฌ๊ธฐ ๋“ฑ ์‹ค์ œ ํ™˜๊ฒฝ์˜ ์˜ํ–ฅ์ž…๋‹ˆ๋‹ค.

3.5 Algorithm Bug #5: Basic Priority FIFO ์œ„๋ฐ˜

๋ฌธ์ œ ๋ฐœ๊ฒฌ

ํ…Œ์ŠคํŠธ๋ฅผ ๋ฐ˜๋ณตํ•˜๋˜ ์ค‘, Basic Priority๊ฐ€ ์ด์ƒํ•˜๊ฒŒ ์ž์ฃผ ์Šน๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค. MLFQS๋‚˜ CFS๋ณด๋‹ค ๊ฑฐ์˜ ํ•ญ์ƒ ๋น ๋ฅธ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์˜€์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ์˜์‹ฌ์Šค๋Ÿฌ์› ์Šต๋‹ˆ๋‹ค. Basic Priority๋Š” ๊ฐ€์žฅ ๋‹จ์ˆœํ•œ ์Šค์ผ€์ค„๋Ÿฌ์ธ๋ฐ, ์™œ ํ•ญ์ƒ ์ด๊ธธ๊นŒ์š”?

์›์ธ ๋ถ„์„

Basic Priority์˜ pick_next() ํ•จ์ˆ˜๋ฅผ ์ž์„ธํžˆ ์‚ดํŽด๋ดค์Šต๋‹ˆ๋‹ค:

# ๋ฌธ์ œ๊ฐ€ ์žˆ๋˜ ์ฝ”๋“œ
def pick_next(self):
    if not self.ready_queue:
        return None
    thread = max(self.ready_queue, key=lambda t: (t.priority, -t.tid))
    self.ready_queue.remove(thread)
    return thread

์ด ์ฝ”๋“œ๋Š” "๊ฐ™์€ ์šฐ์„ ์ˆœ์œ„ ์ค‘ TID๊ฐ€ ๊ฐ€์žฅ ์ž‘์€ ๊ฒƒ"์„ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด๊ฒƒ์€ FIFO๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค!

์˜ˆ์‹œ๋กœ ์„ค๋ช…ํ•˜๋ฉด:

Scenario 1:
  Ready queue: [Thread 1 (pri=31), Thread 5 (pri=31), Thread 3 (pri=31)]
  Expected (FIFO): Thread 1 ์„ ํƒ (๋จผ์ € ๋“ค์–ด์˜ด)
  Actual:          Thread 1 ์„ ํƒ (TID ์ตœ์†Œ, ์šฐ์—ฐํžˆ ์ผ์น˜)

Scenario 2:
  Ready queue: [Thread 5 (pri=31), Thread 1 (pri=31), Thread 3 (pri=31)]
  Expected (FIFO): Thread 5 ์„ ํƒ (๋จผ์ € ๋“ค์–ด์˜ด)
  Actual:          Thread 1 ์„ ํƒ โ† ์ž˜๋ชป๋จ!

TID๊ฐ€ ์ž‘๋‹ค๊ณ  ๋จผ์ € ๋„์ฐฉํ•œ ๊ฒƒ์ด ์•„๋‹™๋‹ˆ๋‹ค. TID๋Š” ์Šค๋ ˆ๋“œ ์ƒ์„ฑ ์ˆœ์„œ์ผ ๋ฟ, ready queue ์‚ฝ์ž… ์ˆœ์„œ์™€๋Š” ๋‹ค๋ฆ…๋‹ˆ๋‹ค.

์ด ๋ฒ„๊ทธ๋กœ ์ธํ•ด ํŠน์ • ์›Œํฌ๋กœ๋“œ์—์„œ Basic Priority๊ฐ€ ์šฐ์—ฐํžˆ ์œ ๋ฆฌํ•œ ์ˆœ์„œ๋กœ ์Šค๋ ˆ๋“œ๋ฅผ ์„ ํƒํ–ˆ๊ณ , ๊ฒฐ๊ณผ์ ์œผ๋กœ ๋” ์ข‹์€ ์„ฑ๋Šฅ์„ ๋ณด์ธ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

ํ•ด๊ฒฐ ๊ณผ์ •: ์ง„์งœ FIFO ๊ตฌํ˜„

# ์ˆ˜์ •๋œ ์ฝ”๋“œ
def pick_next(self):
    if not self.ready_queue:
        return None

    # 1. ์ตœ๊ณ  ์šฐ์„ ์ˆœ์œ„ ์ฐพ๊ธฐ
    max_priority = max(t.priority for t in self.ready_queue)

    # 2. ๊ฐ™์€ ์šฐ์„ ์ˆœ์œ„ ์ค‘ ์ฒซ ๋ฒˆ์งธ ์„ ํƒ (์ง„์งœ FIFO)
    for thread in self.ready_queue:
        if thread.priority == max_priority:
            self.ready_queue.remove(thread)
            return thread

    return None

Python list๋Š” ์‚ฝ์ž… ์ˆœ์„œ๋ฅผ ์œ ์ง€ํ•˜๋ฏ€๋กœ, ์ˆœํšŒํ•˜๋ฉด์„œ ์ฒซ ๋ฒˆ์งธ๋กœ ์ผ์น˜ํ•˜๋Š” ๊ฒƒ์„ ์ฐพ์œผ๋ฉด FIFO๊ฐ€ ๋ณด์žฅ๋ฉ๋‹ˆ๋‹ค.

๊ฒฐ๊ณผ

์ˆ˜์ • ํ›„, Basic์˜ ๋ถ€๋‹นํ•œ ์ด์ ์ด ์ œ๊ฑฐ๋˜์—ˆ๊ณ  ๊ฐ ์Šค์ผ€์ค„๋Ÿฌ๊ฐ€ ์ž์‹ ์˜ ์ง„์งœ ๊ฐ•์ ์—์„œ๋งŒ ์Šน๋ฆฌํ•˜๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

๋ฐฐ์šด ์ 

  • FIFO์˜ ์ •ํ™•ํ•œ ์˜๋ฏธ: FIFO๋Š” "First-In, First-Out"์ด๋ฉฐ, ์ด๊ฒƒ์€ TID๊ฐ€ ์•„๋‹ˆ๋ผ ํ ์‚ฝ์ž… ์ˆœ์„œ๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.
  • Python list์˜ ํŠน์„ฑ: list๋Š” ์‚ฝ์ž… ์ˆœ์„œ๋ฅผ ์œ ์ง€ํ•˜๊ณ , remove()๋Š” ์ฒซ ๋ฒˆ์งธ ์ผ์น˜ ํ•ญ๋ชฉ์„ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค.
  • ์šฐ์—ฐํ•œ ์Šน๋ฆฌ๋Š” ์˜์‹ฌ: ํ•œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ์••๋„์ ์œผ๋กœ ์ด๊ธฐ๋ฉด, ๊ตฌํ˜„ ๋ฒ„๊ทธ์ผ ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์Šต๋‹ˆ๋‹ค.
  • ๊ณต์ •ํ•œ ํ…Œ์ŠคํŠธ: ๋ฒ„๊ทธ๋ฅผ ์ˆ˜์ •ํ•œ ํ›„์—์•ผ ๋น„๋กœ์†Œ "๊ณต์ •ํ•œ ๋น„๊ต"๊ฐ€ ๊ฐ€๋Šฅํ–ˆ์Šต๋‹ˆ๋‹ค.

3.6 Infrastructure Bug #6: ์ปจํ…์ŠคํŠธ ์Šค์œ„์น˜ ์นด์šดํŠธ ๋ˆ„๋ฝ

๋ฌธ์ œ ๋ฐœ๊ฒฌ

ํ™•์žฅ์„ฑ ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ–ˆ์„ ๋•Œ, ์ฃผ์š” ๋ฉ”ํŠธ๋ฆญ์ธ context_switches๊ฐ€ ํ•ญ์ƒ 0์œผ๋กœ ๋‚˜์™”์Šต๋‹ˆ๋‹ค:

10 threads:  context_switches=0
100 threads: context_switches=0
500 threads: context_switches=0

์›์ธ ๋ถ„์„

  1. ์นด์šดํŠธ ๋ฏธ์ „๋‹ฌ: ์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ๊ฐ€ ์ปจํ…์ŠคํŠธ ์Šค์œ„์น˜๋ฅผ ์นด์šดํŠธํ•˜์ง€ ์•Š์Œ
  2. ์ด์ „ ์Šค๋ ˆ๋“œ ๋ฏธ์ถ”์ : "์ด์ „ ์Šค๋ ˆ๋“œ โ‰  ํ˜„์žฌ ์Šค๋ ˆ๋“œ"๋ฅผ ๊ฐ์ง€ํ•  ๋ฐฉ๋ฒ•์ด ์—†์Œ
# ๋ฌธ์ œ๊ฐ€ ์žˆ๋˜ ์ฝ”๋“œ
def run(self, max_ticks):
    while current_tick < max_ticks and not self.scheduler.is_empty():
        thread = self.scheduler.pick_next()
        # ์—ฌ๊ธฐ์„œ ์ปจํ…์ŠคํŠธ ์Šค์œ„์น˜๊ฐ€ ๋ฐœ์ƒํ–ˆ๋Š”์ง€ ์•Œ ์ˆ˜ ์—†์Œ!
        ...

ํ•ด๊ฒฐ ๊ณผ์ •

# ์ˆ˜์ •๋œ ์ฝ”๋“œ
class Simulator:
    def __init__(self, scheduler, threads):
        self.scheduler = scheduler
        self.prev_running_tid = None  # ์ด์ „ ์‹คํ–‰ ์Šค๋ ˆ๋“œ ์ถ”์ 
        self.total_context_switches = 0

    def run(self, max_ticks):
        current_tick = 0

        while current_tick < max_ticks and not self.scheduler.is_empty():
            thread = self.scheduler.pick_next()

            # ์ปจํ…์ŠคํŠธ ์Šค์œ„์น˜ ๊ฐ์ง€
            if self.prev_running_tid is not None and \
               self.prev_running_tid != thread.tid:
                self.total_context_switches += 1

            self.prev_running_tid = thread.tid

            # Time slice ์‹คํ–‰...

        # ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ์ข…๋ฃŒ ์‹œ ๋ชจ๋“  ์Šค๋ ˆ๋“œ์— ๊ธฐ๋ก
        all_threads = (self.scheduler.ready_queue +
                      self.scheduler.waiting_queue +
                      [self.scheduler.running] if self.scheduler.running else [])
        for t in all_threads:
            t.context_switches = self.total_context_switches

        return self.create_dataframe()

๊ฒฐ๊ณผ

์ˆ˜์ • ์ „์—๋Š” context_switches๊ฐ€ ํ•ญ์ƒ 0์œผ๋กœ ๋‚˜์™”์ง€๋งŒ, ์ˆ˜์ • ํ›„์—๋Š” ์˜๋ฏธ ์žˆ๋Š” ์ธก์ •์ด ๊ฐ€๋Šฅํ•ด์กŒ์Šต๋‹ˆ๋‹ค. CFS๊ฐ€ ์•ฝ๊ฐ„ ๋” ๋งŽ์€ ์ปจํ…์ŠคํŠธ ์Šค์œ„์น˜๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค์ง€๋งŒ, ์ฐจ์ด๋Š” ํฌ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋ฐฐ์šด ์ 

  • ์ƒํƒœ ์ถ”์ : ์ปจํ…์ŠคํŠธ ์Šค์œ„์น˜๋Š” "์ด์ „ ์Šค๋ ˆ๋“œ โ‰  ํ˜„์žฌ ์Šค๋ ˆ๋“œ"๋กœ ๊ฐ์ง€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ๋ฉ”ํŠธ๋ฆญ ์ „ํŒŒ: ์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ๊ฐ€ ์ธก์ •ํ•œ ๊ฐ’์„ ์Šค๋ ˆ๋“œ ๊ฐ์ฒด์— ์ „๋‹ฌํ•ด์•ผ ๋ถ„์„ ๋‹จ๊ณ„์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์ธํ”„๋ผ์˜ ์ค‘์š”์„ฑ: ์•Œ๊ณ ๋ฆฌ์ฆ˜๋งŒ ์ค‘์š”ํ•œ ๊ฒƒ์ด ์•„๋‹ˆ๋ผ, ์ด๋ฅผ ์ธก์ •ํ•˜๋Š” ์ธํ”„๋ผ(์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ, ๋ฉ”ํŠธ๋ฆญ ์ˆ˜์ง‘)๋„ ์ •ํ™•ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

4. ์•„ํ‚คํ…์ฒ˜ ์„ค๊ณ„์™€ ์ฃผ์š” ๊ฒฐ์ •

4.1 ๋ชฉํ‘œ ๊ธฐ๋ฐ˜ ํ…Œ์ŠคํŠธ ์„ค๊ณ„์˜ ๊ตฌ์ฒด์  ๊ตฌํ˜„

Test ํด๋ž˜์Šค ์„ค๊ณ„

@dataclass
class Test:
    test_id: str
    name: str
    schedulers: List[str]  # ๋น„๊ตํ•  ์Šค์ผ€์ค„๋Ÿฌ ๋ช…์‹œ
    workload_type: str
    thread_count: int
    goal: str
    primary_metric: str
    description: str

์„ ํƒ์  ๋น„๊ต์˜ ์˜ˆ์‹œ

# ๊ณต์ •์„ฑ ํ…Œ์ŠคํŠธ: MLFQS vs CFS๋งŒ (Nice ์ฐจ์ด๊ฐ€ ์žˆ๋Š” ์›Œํฌ๋กœ๋“œ)
Test(
    test_id="fairness_mixed",
    name="๊ณต์ •์„ฑ: ํ˜ผํ•ฉ ์›Œํฌ๋กœ๋“œ",
    schedulers=["mlfqs", "cfs"],  # Basic ์ œ์™ธ!
    workload_type="mixed",
    goal="๊ณต์ •ํ•œ CPU ๋ฐฐ๋ถ„",
    primary_metric="fairness",
    description="..."
)

# ์ผ๋ฐ˜ ์›Œํฌ๋กœ๋“œ: 3๊ฐœ ๋ชจ๋‘
Test(
    test_id="general_mixed",
    name="์ผ๋ฐ˜ ํ˜ผํ•ฉ ์›Œํฌ๋กœ๋“œ",
    schedulers=["basic", "mlfqs", "cfs"],  # ๋ชจ๋‘ ํฌํ•จ
    workload_type="mixed",
    goal="๋‹ค์–‘ํ•œ ์ž‘์—…์˜ ์ „๋ฐ˜์  ์„ฑ๋Šฅ",
    primary_metric="avg_wait"
)

์ด ๋น„๊ต ์ˆ˜

  • ์ผ๋ฐ˜ ์›Œํฌ๋กœ๋“œ: 3๊ฐœ ร— 3-way = 9๊ฐœ
  • ์‹ค์ œ ์‘์šฉ: 4๊ฐœ ร— 3-way = 12๊ฐœ
  • ๊ณต์ •์„ฑ: 2๊ฐœ ร— 2-way = 4๊ฐœ
  • ์ผ๊ด€์„ฑ: 4๊ฐœ ร— 3-way = 12๊ฐœ
  • Nice ํšจ๊ณผ: 1๊ฐœ ร— 2-way = 2๊ฐœ
  • ํ™•์žฅ์„ฑ: 3๊ฐœ ร— 3-way = 9๊ฐœ
  • ์ด 48๊ฐœ ๋น„๊ต (17๊ฐœ ํ…Œ์ŠคํŠธ)

4.2 Burst Time ์„ค๊ณ„ ์ฒ ํ•™

ํ•ต์‹ฌ ์งˆ๋ฌธ

ํ”„๋กœ์ ํŠธ ์ค‘๊ฐ„์— ์Šค์Šค๋กœ์—๊ฒŒ ๋ฌผ์—ˆ์Šต๋‹ˆ๋‹ค: "burst_time์„ vruntime์ด๋‚˜ priority์— ๋งž๊ฒŒ ๋™์ ์œผ๋กœ ์กฐ์ •ํ•ด์•ผ ํ•˜๋‚˜?"

๋‹ต๋ณ€: NO

์ด์œ : burst_time์€ "์‹ค์ œ๋กœ ํ•„์š”ํ•œ ์ž‘์—…๋Ÿ‰"์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด:

  • ์ปดํŒŒ์ผ ์ž‘์—…: burst_time = 1000 (1000 ticks์˜ CPU ํ•„์š”)
  • ์งง์€ ์ฟผ๋ฆฌ: burst_time = 50

ํ”„๋กœ์„ธ์Šค๊ฐ€ ์™„๋ฃŒํ•˜๋ ค๋ฉด ์ •ํ™•ํžˆ burst_time๋งŒํผ์˜ CPU๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์Šค์ผ€์ค„๋Ÿฌ๋Š” ์ด๋ฅผ ์–ด๋–ป๊ฒŒ ๋ฐฐ๋ถ„ํ• ์ง€ ๊ฒฐ์ •ํ•  ๋ฟ, ์ž‘์—…๋Ÿ‰ ์ž์ฒด๋Š” ๋ณ€ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋น„์œ :

burst_time = ํŒŒ์ผ ํฌ๊ธฐ (100MB)
scheduler  = ์ „์†ก ์ˆœ์„œ ๋ฐ ๋Œ€์—ญํญ ๊ฒฐ์ •

ํŒŒ์ผ ํฌ๊ธฐ๋Š” ๊ณ ์ •์ด๊ณ , ์Šค์ผ€์ค„๋Ÿฌ๋Š”:
- ์–ด๋А ํŒŒ์ผ์„ ๋จผ์ € ์ „์†กํ• ์ง€ (pick_next)
- ๊ฐ ํŒŒ์ผ์— ์–ผ๋งˆ๋‚˜ ๋นจ๋ฆฌ ์ „์†กํ• ์ง€ (nice, priority)
๋ฅผ ๊ฒฐ์ •ํ•  ๋ฟ์ž…๋‹ˆ๋‹ค.

๋Œ€์•ˆ: ์ธก์ • ๋ฐฉ๋ฒ• ๋ณ€๊ฒฝ

์ž‘์—…๋Ÿ‰์„ ๋ฐ”๊พธ์ง€ ๋ง๊ณ , ์ธก์ • ์‹œ์ ์„ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค:

  • ๋ชจ๋“  ์Šค๋ ˆ๋“œ ์™„๋ฃŒ ํ›„ ์ธก์ •: Nice ํšจ๊ณผ ์ธก์ • ๋ถˆ๊ฐ€ (๋ชจ๋‘ burst_time๋งŒํผ ์‚ฌ์šฉ)
  • 50% ์‹œ๊ฐ„์— ์ค‘๋‹จ: Nice ํšจ๊ณผ ๋ช…ํ™•ํžˆ ๋“œ๋Ÿฌ๋‚จ

์ด๊ฒƒ์ด Nice ํšจ๊ณผ ํ…Œ์ŠคํŠธ์—์„œ ์‹œ๋ฎฌ๋ ˆ์ด์…˜์„ ์กฐ๊ธฐ ์ข…๋ฃŒํ•œ ์ด์œ ์ž…๋‹ˆ๋‹ค.

4.3 ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ํŒŒ๋ผ๋ฏธํ„ฐ ๊ฒฐ์ •

Time Slice: 4 ticks

์„ ํƒ ์ด์œ :

  • ๋„ˆ๋ฌด ์งง์œผ๋ฉด (1-2 ticks): ์ปจํ…์ŠคํŠธ ์Šค์œ„์น˜ ์˜ค๋ฒ„ํ—ค๋“œ ๊ณผ๋‹ค
  • ๋„ˆ๋ฌด ๊ธธ๋ฉด (10+ ticks): ์‘๋‹ต์„ฑ ์ €ํ•˜, I/O bound ์Šค๋ ˆ๋“œ ๋ถˆ๋ฆฌ
  • 4 ticks: ์ผ๋ฐ˜์ ์ธ Round-robin ์„ค์ •, Linux ๊ธฐ๋ณธ๊ฐ’(4ms)๊ณผ ์œ ์‚ฌ

๊ฒ€์ฆ: ์‹ค์ œ๋กœ 4 ticks๋Š” 50๊ฐœ ์Šค๋ ˆ๋“œ ํ™˜๊ฒฝ์—์„œ ์ ์ ˆํ•œ ๊ท ํ˜•์„ ๋ณด์—ฌ์คฌ์Šต๋‹ˆ๋‹ค. ์ปจํ…์ŠคํŠธ ์Šค์œ„์น˜๋Š” ์ถฉ๋ถ„ํžˆ ์ž์ฃผ ๋ฐœ์ƒํ•˜์ง€๋งŒ(500+ ํšŒ), ์˜ค๋ฒ„ํ—ค๋“œ๋Š” ๋ฌด์‹œํ•  ์ˆ˜์ค€์ด์—ˆ์Šต๋‹ˆ๋‹ค.

Max Ticks: 35,000

๊ณ„์‚ฐ ๊ทผ๊ฑฐ:

  • ํ‰๊ท  burst_time: ~500-600 ticks
  • ์Šค๋ ˆ๋“œ ์ˆ˜: 50๊ฐœ
  • ํ•„์š”ํ•œ ์ด CPU: 50 ร— 600 = 30,000 ticks
  • ์—ฌ์œ : +5,000 ticks (I/O ๋Œ€๊ธฐ, ์ปจํ…์ŠคํŠธ ์Šค์œ„์น˜ ์˜ค๋ฒ„ํ—ค๋“œ)

์˜ˆ์™ธ: Nice ํšจ๊ณผ ํ…Œ์ŠคํŠธ๋Š” 50% ์‹œ๊ฐ„(total_work ร— 0.5)์— ์ค‘๋‹จ

Thread Count: 50 (๊ธฐ๋ณธ)

์„ ํƒ ์ด์œ :

  • ๋„ˆ๋ฌด ์ ์œผ๋ฉด (10): ์Šค์ผ€์ค„๋Ÿฌ ์ฐจ์ด๊ฐ€ ๋“œ๋Ÿฌ๋‚˜์ง€ ์•Š์Œ
  • ๋„ˆ๋ฌด ๋งŽ์œผ๋ฉด (500): ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ์‹œ๊ฐ„ ๊ณผ๋‹ค (10์ดˆ+)
  • 50: ์˜๋ฏธ ์žˆ๋Š” ์ฐจ์ด๋ฅผ ๋ณด์ด๋ฉด์„œ๋„ ๋น ๋ฅธ ์‹คํ–‰ (2-3์ดˆ)

ํ™•์žฅ์„ฑ ํ…Œ์ŠคํŠธ: 10, 100, 500์œผ๋กœ ๋ณ€๊ฒฝํ•˜์—ฌ ์Šค์ผ€์ผ๋ง ๋Šฅ๋ ฅ ์ธก์ •


5. ํ•ต์‹ฌ ๋ฐฐ์šด ์ 

5.1 ์ด๋ก ๊ณผ ๊ตฌํ˜„์˜ ๊ดด๋ฆฌ

์‚ฌ๋ก€ 1: Time Slice

  • ์ด๋ก : "Round-robin์€ time slice๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค" (์•”๋ฌต์ )
  • ๊ตฌํ˜„: TIME_SLICE = 4; current_slice_remaining = TIME_SLICE (๋ช…์‹œ์ )

์‚ฌ๋ก€ 2: FIFO

  • ์ด๋ก : "๋จผ์ € ์˜จ ๊ฒƒ์„ ๋จผ์ € ์ฒ˜๋ฆฌ" (๋ชจํ˜ธํ•จ)
  • ๊ตฌํ˜„: "ready_queue์˜ ์‚ฝ์ž… ์ˆœ์„œ" (์ •ํ™•ํ•จ, TID โ‰  ๋„์ฐฉ ์ˆœ์„œ)

์‚ฌ๋ก€ 3: ์ •๋ฐ€๋„

  • ์ด๋ก : delta / weight (์ˆ˜ํ•™์ )
  • ๊ตฌํ˜„: (delta * 1024 * 1000) // weight (์ •์ˆ˜ ์—ฐ์‚ฐ + ์Šค์ผ€์ผ)

5.2 ์ •์ˆ˜ ์—ฐ์‚ฐ๊ณผ ๊ณ ์ •์†Œ์ˆ˜์ 

์šด์˜์ฒด์ œ๋Š” ์™œ ๋ถ€๋™์†Œ์ˆ˜์ ์„ ํ”ผํ• ๊นŒ์š”?

์ธก๋ฉด ๋ถ€๋™์†Œ์ˆ˜์  (float) ์ •์ˆ˜ + ์Šค์ผ€์ผ
์ •๋ฐ€๋„ ๋†’์Œ (ํ•˜์ง€๋งŒ ์˜ˆ์ธก ๋ถˆ๊ฐ€๋Šฅ) ์ถฉ๋ถ„ (์˜ˆ์ธก ๊ฐ€๋Šฅ)
์„ฑ๋Šฅ ๋А๋ฆผ (FPU ํ•„์š”) ๋น ๋ฆ„ (ALU๋งŒ)
๊ฒฐ์ •์„ฑ ๋‚ฎ์Œ (๋ฐ˜์˜ฌ๋ฆผ ์˜ค์ฐจ) ๋†’์Œ (์ •ํ™•)
์‚ฌ์šฉ์ฒ˜ ๊ณผํ•™ ๊ณ„์‚ฐ ์‹ค์‹œ๊ฐ„ ์‹œ์Šคํ…œ, OS

์‹ค์ œ ์‚ฌ์šฉ ์˜ˆ:

  • MLFQS: 17.14 ๊ณ ์ •์†Œ์ˆ˜์  (F = 1 << 14 = 16384)

    recent_cpu = (2 * load_avg * F) // (2 * load_avg + 1 * F) * recent_cpu // F
  • CFS: 1024 ร— 1000 ์Šค์ผ€์ผ

    delta_vruntime = (delta * 1024 * 1000) // weight

5.3 ์ธก์ • ๋ฐฉ๋ฒ•๋ก ์˜ ์ค‘์š”์„ฑ

๋ชฉํ‘œ ์ž˜๋ชป๋œ ๋ฐฉ๋ฒ• ์˜ฌ๋ฐ”๋ฅธ ๋ฐฉ๋ฒ• ์ด์œ 
Nice ํšจ๊ณผ ๋ชจ๋‘ ์™„๋ฃŒ ํ›„ CPU ์‹œ๊ฐ„ ์ธก์ • 20% ์‹œ๊ฐ„์— ์ค‘๋‹จ ์™„๋ฃŒ๋˜๋ฉด ๋ชจ๋‘ burst_time๋งŒํผ ์‚ฌ์šฉ (1:1)
๊ณต์ •์„ฑ ๋ชจ๋“  ์Šค์ผ€์ค„๋Ÿฌ ๋น„๊ต ๊ณต์ •์„ฑ ๋ชฉํ‘œ๋งŒ ๋น„๊ต Basic์€ starvation ์œ„ํ—˜ (๋‹ค๋ฅธ ๋ชฉํ‘œ)
ํ™•์žฅ์„ฑ ๋‹จ์ผ ์Šค๋ ˆ๋“œ ์ˆ˜ ํ…Œ์ŠคํŠธ 10, 100, 500 ๋น„๊ต ์Šค์ผ€์ผ๋ง ํŒจํ„ด์„ ๋ณด๋ ค๋ฉด ์—ฌ๋Ÿฌ ์  ํ•„์š”

5.4 ๋””๋ฒ„๊น… ์ „๋žต

์˜์‹ฌํ•ด์•ผ ํ•  ์‹ ํ˜ธ๋“ค

  1. ๋ชจ๋“  ๊ฒฐ๊ณผ๊ฐ€ ๊ฐ™์Œ (tie) โ†’ Time slice ๋ฏธ๊ตฌํ˜„
  2. ํ•œ ์Šค์ผ€์ค„๋Ÿฌ๊ฐ€ ์••๋„์  โ†’ ๊ตฌํ˜„ ๋ฒ„๊ทธ (Basic FIFO)
  3. ๋ฉ”ํŠธ๋ฆญ์ด ํ•ญ์ƒ 0 โ†’ ์ธก์ • ์˜ค๋ฅ˜ (vruntime, context_switches)
  4. ์ด๋ก ๊ณผ ํฌ๊ฒŒ ๋‹ค๋ฆ„ โ†’ ์ธก์ • ๋ฐฉ๋ฒ• ์˜ค๋ฅ˜ (Nice ํšจ๊ณผ 1:1)

์ฒด๊ณ„์  ์ ‘๊ทผ

  1. ๊ด€์ฐฐ: ์ด์ƒํ•œ ๊ฒฐ๊ณผ ์ธ์‹
  2. ๊ฐ€์„ค: "Time slice๊ฐ€ ์—†๋‚˜?", "์ •์ˆ˜ ๋‚˜๋ˆ—์…ˆ ๋ฌธ์ œ?"
  3. ์‹คํ—˜: print() ๋””๋ฒ„๊น…, ๋‹จ๊ณ„๋ณ„ ์‹คํ–‰, ๋‹จ์ˆœํ™”๋œ ํ…Œ์ŠคํŠธ
  4. ๊ฒ€์ฆ: ์ˆ˜์ • ํ›„ ๊ฒฐ๊ณผ ํ™•์ธ, ์ด๋ก ๊ฐ’๊ณผ ๋น„๊ต

5.5 ์‹ค์ œ ์šด์˜์ฒด์ œ์˜ ๋ณต์žก์„ฑ

๊ฐ ์Šค์ผ€์ค„๋Ÿฌ์˜ ์‹ค์ œ ๋ณต์žก๋„:

Basic Priority (67์ค„)

  • ๊ฐ€์žฅ ๋‹จ์ˆœํ•˜์ง€๋งŒ, FIFO ๊ตฌํ˜„๋„ ์ฃผ์˜ ํ•„์š”
  • ์šฐ์„ ์ˆœ์œ„ ๊ด€๋ฆฌ, ์„ ์  ์ฒ˜๋ฆฌ

MLFQS (250์ค„)

  • 3๊ฐ€์ง€ ์—…๋ฐ์ดํŠธ ์ฃผ๊ธฐ:
    • ๋งค tick: recent_cpu++ (์‹คํ–‰ ์ค‘์ธ ์Šค๋ ˆ๋“œ๋งŒ)
    • 4 ticks๋งˆ๋‹ค: priority ์žฌ๊ณ„์‚ฐ (๋ชจ๋“  ์Šค๋ ˆ๋“œ)
    • 100 ticks๋งˆ๋‹ค: load_avg, recent_cpu ์žฌ๊ณ„์‚ฐ (๋ชจ๋“  ์Šค๋ ˆ๋“œ)
  • 17.14 ๊ณ ์ •์†Œ์ˆ˜์  ์—ฐ์‚ฐ
  • 64๊ฐœ ๋…๋ฆฝ ํ ๊ด€๋ฆฌ

CFS (100์ค„)

  • Linux ๊ฐ€์ค‘์น˜ ํ…Œ์ด๋ธ” 40๊ฐœ ํ•ญ๋ชฉ
  • vruntime ์Šค์ผ€์ผ ์กฐ์ • (1024ร—1000)
  • SortedList๋กœ ์ž๋™ ์ •๋ ฌ (Red-Black Tree ๋Œ€์‹ )
  • min_vruntime ์ถ”์ 

6. ํ”„๋กœ์ ํŠธ ์„ฑ๊ณผ

6.1 ์ •๋Ÿ‰์  ์„ฑ๊ณผ

์ฝ”๋“œ ๊ทœ๋ชจ

  • ์ด ๋ผ์ธ ์ˆ˜: 2,939์ค„
  • ํŒŒ์ผ ์ˆ˜: 21๊ฐœ
  • ์Šค์ผ€์ค„๋Ÿฌ ๊ตฌํ˜„:
    • Basic Priority: 67์ค„
    • MLFQS: 250์ค„
    • CFS: 100์ค„
  • ์›Œํฌ๋กœ๋“œ: 9๊ฐ€์ง€ ํŒจํ„ด
  • ํ…Œ์ŠคํŠธ: 18๊ฐœ, 6๊ฐœ ์นดํ…Œ๊ณ ๋ฆฌ

๋ฒ„๊ทธ ์ˆ˜์ •

  • ๋ฐœ๊ฒฌ: 6๊ฐœ major bugs
  • ์ˆ˜์ •๋ฅ : 100%
  • ์žฌ๋ฐœ: 0๊ฐœ

์ตœ์ข… ๊ฒฐ๊ณผ

์œ ์˜๋ฏธํ•œ ํŽธํ–ฅ ์—†์Œ โ†’ ๊ฐ ์Šค์ผ€์ค„๋Ÿฌ๊ฐ€ ์ž์‹ ์˜ ๊ฐ•์ ์—์„œ๋งŒ ์Šน๋ฆฌ

๋ฐฐํฌ

  • ํ”Œ๋žซํผ: GCP VM (Ubuntu 24.04, 16GB RAM, 4 vCPU)
  • ์›น ํ”„๋ ˆ์ž„์›Œํฌ: Streamlit
  • ์ ‘๊ทผ์„ฑ: ๊ณต๊ฐœ URL (http://34.47.105.226:8501)
  • ๊ฐ€๋™์‹œ๊ฐ„: systemd ์„œ๋น„์Šค๋กœ 24/7 ์šด์˜
  • ๋„คํŠธ์›Œํฌ: ํฌํŠธ 80 โ†’ 8501 ํฌ์›Œ๋”ฉ (iptables)

6.2 ์ •์„ฑ์  ์„ฑ๊ณผ

ํ•™์Šต ๋ชฉํ‘œ ๋‹ฌ์„ฑ

  1. โœ… 3๊ฐ€์ง€ ์Šค์ผ€์ค„๋Ÿฌ ๊นŠ์€ ์ดํ•ด

    • ๋‹จ์ˆœ ์•”๊ธฐ๊ฐ€ ์•„๋‹Œ ๊ตฌํ˜„์„ ํ†ตํ•œ ์ดํ•ด
    • ๊ฐ ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ํŠธ๋ ˆ์ด๋“œ์˜คํ”„ ์ฒดํ—˜
  2. โœ… ์‹ค์ œ OS ์—ฐ๊ฒฐ

    • FreeBSD 4.4BSD MLFQS ๊ตฌํ˜„ ์ฐธ์กฐ
    • Linux CFS PRIO_TO_WEIGHT ํ…Œ์ด๋ธ” ๋™์ผ ์‚ฌ์šฉ
    • PintOS ๋ฌธ์„œ์˜ 17.14 ๊ณ ์ •์†Œ์ˆ˜์ 
  3. โœ… ์ •๋Ÿ‰์  ๋ถ„์„ ๋Šฅ๋ ฅ

    • "๋А๋‚Œ"์ด ์•„๋‹Œ ๋ฉ”ํŠธ๋ฆญ ๊ธฐ๋ฐ˜ ๋น„๊ต
    • Jain's Fairness Index, ์ปจํ…์ŠคํŠธ ์Šค์œ„์น˜ ์ˆ˜ ๋“ฑ
  4. โœ… ์„ค๊ณ„ ๋ฐฉ๋ฒ•๋ก 

    • ๋ชฉํ‘œ ๊ธฐ๋ฐ˜ ํ…Œ์ŠคํŠธ ์„ค๊ณ„
    • ๊ณต์ •ํ•œ ๋น„๊ต ๋ฐฉ๋ฒ•๋ก 

์˜ˆ์ƒ์น˜ ๋ชปํ•œ ๋ฐœ๊ฒฌ

์ด ์„น์…˜์—์„œ๋Š” ์‹ค์ œ ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ์—์„œ ๋ฐœ๊ฒฌํ•œ ํฅ๋ฏธ๋กœ์šด ํŒจํ„ด๋“ค์„ ์ƒ์„ธํžˆ ๋ถ„์„ํ•ฉ๋‹ˆ๋‹ค.


1. Nice ํšจ๊ณผ์˜ ๊ทน๋‹จ์  ์ฐจ์ด - MLFQS vs CFS

์ธก์ • ๊ฒฐ๊ณผ: MLFQS๋Š” ๋งค์šฐ ๊ฐ•ํ•œ nice ํšจ๊ณผ๋ฅผ, CFS๋Š” ๊ฐ€์ค‘์น˜ ๋น„๋ก€ ๋ฐฐ๋ถ„์„ ๋ณด์ž„.

์™œ MLFQS๊ฐ€ ํ›จ์”ฌ ๊ทน๋‹จ์ ์ธ๊ฐ€?

MLFQS์˜ ์šฐ์„ ์ˆœ์œ„ ๊ณต์‹์„ ๋‹ค์‹œ ์‚ดํŽด๋ณด๋ฉด:

priority = 63 - (recent_cpu / 4) - (nice * 2)

nice -20 ์Šค๋ ˆ๋“œ:

  • ์ดˆ๊ธฐ: priority = 63 - 0 - (-20*2) = 63 - 0 + 40 = 103 (์ตœ๋Œ€๊ฐ’์œผ๋กœ clamped โ†’ 63)
  • ์‹คํ–‰ ํ›„: recent_cpu๊ฐ€ ์ฆ๊ฐ€ํ•ด๋„ nice*2 = 40์ด ๋งค์šฐ ํฐ ๋ณด์ •
  • ์˜ˆ: recent_cpu=100์ผ ๋•Œ โ†’ priority = 63 - 25 + 40 = 78 (์—ฌ์ „ํžˆ ๋งค์šฐ ๋†’์Œ)

nice 19 ์Šค๋ ˆ๋“œ:

  • ์ดˆ๊ธฐ: priority = 63 - 0 - (19*2) = 63 - 38 = 25
  • ์‹คํ–‰ ํ›„: recent_cpu=100์ผ ๋•Œ โ†’ priority = 63 - 25 - 38 = 0 (์ตœ์ €)

ํ•ต์‹ฌ ์ฐจ์ด์ :

  • nice -20 ์Šค๋ ˆ๋“œ๋Š” recent_cpu๊ฐ€ ์ฆ๊ฐ€ํ•ด๋„ +40 ๋ณด์ •์ด ์••๋„์ ์ด์–ด์„œ ์šฐ์„ ์ˆœ์œ„๊ฐ€ ๊ฑฐ์˜ ์•ˆ ๋–จ์–ด์ง
  • nice 19 ์Šค๋ ˆ๋“œ๋Š” -38 ํŽ˜๋„ํ‹ฐ๋กœ ์‹œ์ž‘ํ•ด์„œ ์กฐ๊ธˆ๋งŒ ์‹คํ–‰ํ•ด๋„ ์šฐ์„ ์ˆœ์œ„ ๋ฐ”๋‹ฅ

๊ฒฐ๊ณผ: nice -20 ์Šค๋ ˆ๋“œ๊ฐ€ ๊ฑฐ์˜ ๋…์ ์ ์œผ๋กœ ์‹คํ–‰๋˜๊ณ , nice 19 ์Šค๋ ˆ๋“œ๋Š” ๊ฑฐ์˜ ์‹คํ–‰ ๊ธฐํšŒ๋ฅผ ๋ชป ๋ฐ›์Œ.


์™œ CFS๋Š” ์ด๋ก ๊ฐ’๋ณด๋‹ค ์•ฝํ•œ๊ฐ€?

์ด๋ก ์ ์œผ๋กœ CFS๋Š” ์ •ํ™•ํžˆ weight ๋น„์œจ๋Œ€๋กœ CPU๋ฅผ ๋ฐฐ๋ถ„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์‹ค์ œ ๊ฒฐ๊ณผ๋Š” ์ด๋ก ๊ฐ’๋ณด๋‹ค ์•ฝํ•ฉ๋‹ˆ๋‹ค.

์›์ธ 1: Time Slice ๊ฒฝ๊ณ„ ํšจ๊ณผ

Time slice = 4 ticks

์‹œ๋‚˜๋ฆฌ์˜ค:
- nice -20 ์Šค๋ ˆ๋“œ๊ฐ€ 4 ticks ์‹คํ–‰ โ†’ vruntime += 11*4 = 44
- nice 19 ์Šค๋ ˆ๋“œ๊ฐ€ 4 ticks ์‹คํ–‰ โ†’ vruntime += 68266*4 = 273,064

์ด์ƒ์ : 44์™€ 273,064๊ฐ€ ๊ฐ™์•„์งˆ ๋•Œ๊นŒ์ง€ nice -20์ด ์‹คํ–‰
์‹ค์ œ: 4 tick ๋‹จ์œ„๋กœ ๋Š์–ด์ง€๋ฏ€๋กœ nice 19๋„ ์ตœ์†Œ 4 ticks๋Š” ๋ฐ›์Œ

nice 19 ์Šค๋ ˆ๋“œ๊ฐ€ "4 tick ๋‹จ์œ„๋กœ ๊ฐ•์ œ ์‹คํ–‰"๋˜๋ฉด์„œ ์˜ˆ์ƒ๋ณด๋‹ค ๋งŽ์€ CPU๋ฅผ ๋ฐ›๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

์›์ธ 2: ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ์กฐ๊ธฐ ์ข…๋ฃŒ

Nice ํšจ๊ณผ ํ…Œ์ŠคํŠธ๋Š” total_work์˜ 50%์—์„œ ์ค‘๋‹จํ•ฉ๋‹ˆ๋‹ค. ์ด ์‹œ์ ์—์„œ nice -20 ์Šค๋ ˆ๋“œ๋Š” ๋Œ€๋ถ€๋ถ„ ์™„๋ฃŒ๋˜์ง€๋งŒ, nice 19 ์Šค๋ ˆ๋“œ๋Š” ๊ฑฐ์˜ ์‹œ์ž‘๋„ ๋ชป ํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ time slice ๋•Œ๋ฌธ์— nice 19๋„ ์ตœ์†Œํ•œ์˜ ์ง„ํ–‰์„ ํ•˜๋ฉด์„œ, ์ด๋ก ๊ฐ’๋ณด๋‹ค ์•ฝํ•ด์ง‘๋‹ˆ๋‹ค.

์›์ธ 3: ์ปจํ…์ŠคํŠธ ์Šค์œ„์น˜ ์˜ค๋ฒ„ํ—ค๋“œ

๋งค๋ฒˆ ์Šค๋ ˆ๋“œ๋ฅผ ๋ฐ”๊ฟ€ ๋•Œ:

  1. vruntime ๊ณ„์‚ฐ (๋‚˜๋ˆ—์…ˆ ์—ฐ์‚ฐ)
  2. SortedList ์žฌ์ •๋ ฌ
  3. ๋ฉ”๋ชจ๋ฆฌ ์ ‘๊ทผ

์ด ์˜ค๋ฒ„ํ—ค๋“œ๋Š” ์ธก์ •๋˜์ง€ ์•Š์ง€๋งŒ ์‹ค์ œ๋กœ ์‹œ๊ฐ„์„ ์†Œ๋ชจํ•ฉ๋‹ˆ๋‹ค. nice -20์ด ์••๋„์ ์œผ๋กœ ์ž์ฃผ ์‹คํ–‰๋˜๋ฏ€๋กœ, ์ƒ๋Œ€์ ์œผ๋กœ ์˜ค๋ฒ„ํ—ค๋“œ์˜ ์˜ํ–ฅ์„ ๋” ๋ฐ›์Šต๋‹ˆ๋‹ค.

๊ฒฐ๋ก : CFS์˜ ๊ฒฐ๊ณผ๋Š” "์ด๋ก ๊ฐ’๋ณด๋‹ค ์•ฝํ•˜๋‹ค"๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ, **"ํ˜„์‹ค ์„ธ๊ณ„์˜ ์ œ์•ฝ(time slice, ์˜ค๋ฒ„ํ—ค๋“œ) ์†์—์„œ ๋‹ฌ์„ฑํ•œ ๊ฐ•๋ ฅํ•œ nice ํšจ๊ณผ"**์ž…๋‹ˆ๋‹ค.


2. Basic Priority์˜ ๊ฑดํˆฌ - ๋‹จ์ˆœํ•จ์ด ๋•Œ๋กœ๋Š” ์ตœ์„ 

์„ธ ์Šค์ผ€์ค„๋Ÿฌ๊ฐ€ ๋น„์Šทํ•œ ์Šน๋ฅ ์„ ๋ณด์ž…๋‹ˆ๋‹ค. ์ฒ˜์Œ ๋ณด๋Š” ์‚ฌ๋žŒ์€ ์ด์ƒํ•˜๊ฒŒ ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. "๊ฐ€์žฅ ๋‹จ์ˆœํ•œ Basic์ด ๊ฐ€์žฅ ๋ณต์žกํ•œ CFS๋งŒํผ ์ด๊ธด๋‹ค๊ณ ?"

์™œ Basic์ด ์Šน๋ฆฌํ•˜๋Š”๊ฐ€?

Basic์ด ์Šน๋ฆฌํ•œ ํ…Œ์ŠคํŠธ๋“ค์„ ๋ถ„์„ํ•˜๋ฉด:

  1. CPU-bound ์›Œํฌ๋กœ๋“œ (์ผ๋ฐ˜ ์›Œํฌ๋กœ๋“œ ํ…Œ์ŠคํŠธ ์ค‘ ์ผ๋ถ€)
  2. I/O๊ฐ€ ๊ฑฐ์˜ ์—†๋Š” ํ…Œ์ŠคํŠธ
  3. Nice ๊ฐ’์ด ์•ฝํ•˜๊ฑฐ๋‚˜ ๋™์ผํ•œ ๊ฒฝ์šฐ (nice 0 ๋˜๋Š” -5~5)

์Šน๋ฆฌ ์ด์œ  1: ์ตœ์†Œ ์˜ค๋ฒ„ํ—ค๋“œ

๋งค tick๋งˆ๋‹ค ์ˆ˜ํ–‰ํ•˜๋Š” ์ž‘์—…:

Basic Priority:
  - pick_next(): O(n) - ready queue ์„ ํ˜• ํƒ์ƒ‰
  - ์šฐ์„ ์ˆœ์œ„ ์žฌ๊ณ„์‚ฐ: 0ํšŒ (์ •์  ์šฐ์„ ์ˆœ์œ„)
  - ์ถ”๊ฐ€ ์—ฐ์‚ฐ: ์—†์Œ

MLFQS:
  - pick_next(): O(1) - 64๊ฐœ ํ์—์„œ ์ฒซ ๋ฒˆ์งธ ๋น„์–ด์žˆ์ง€ ์•Š์€ ํ
  - ๋งค tick: recent_cpu++ (์‹คํ–‰ ์ค‘์ธ ์Šค๋ ˆ๋“œ)
  - 4 ticks๋งˆ๋‹ค: ๋ชจ๋“  ์Šค๋ ˆ๋“œ์˜ priority ์žฌ๊ณ„์‚ฐ (O(n))
  - 100 ticks๋งˆ๋‹ค: load_avg, recent_cpu ์žฌ๊ณ„์‚ฐ (O(n))

CFS:
  - pick_next(): O(log n) - SortedList์—์„œ ์ตœ์†Œ vruntime
  - ๋งค tick: delta_vruntime ๊ณ„์‚ฐ (๋‚˜๋ˆ—์…ˆ) + vruntime ์—…๋ฐ์ดํŠธ
  - ๋งค yield: SortedList ์žฌ์ •๋ ฌ (O(log n))

์Šค๋ ˆ๋“œ ์ˆ˜๊ฐ€ 50๊ฐœ ์ •๋„์ด๊ณ  CPU-bound์ผ ๋•Œ:

  • Basic์˜ O(n) ์„ ํ˜• ํƒ์ƒ‰: ๋งค์šฐ ๋น ๋ฆ„ (50๋ฒˆ ๋น„๊ต)
  • MLFQS์˜ ์ฃผ๊ธฐ์  ์žฌ๊ณ„์‚ฐ: 4 ticks๋งˆ๋‹ค 50๊ฐœ ์žฌ๊ณ„์‚ฐ
  • CFS์˜ ๋กœ๊ทธ ์‹œ๊ฐ„ ์ •๋ ฌ: ๋งค๋ฒˆ log(50) โ‰ˆ 5.6 ๋น„๊ต

๋†€๋ผ์šด ์ : Basic์˜ ์„ ํ˜• ํƒ์ƒ‰์ด ์‹ค์ œ๋กœ๋Š” ๋งค์šฐ ๋น ๋ฆ…๋‹ˆ๋‹ค!

  • CPU ์บ์‹œ ์นœํ™”์  (์ˆœ์ฐจ ์ ‘๊ทผ)
  • ๋ถ„๊ธฐ ์˜ˆ์ธก ์„ฑ๊ณต๋ฅ  ๋†’์Œ
  • ์ถ”๊ฐ€ ๊ณ„์‚ฐ ์ „ํ˜€ ์—†์Œ

์Šน๋ฆฌ ์ด์œ  2: ์˜ˆ์ธก ๊ฐ€๋Šฅ์„ฑ

Basic์€ ์šฐ์„ ์ˆœ์œ„๊ฐ€ ์ ˆ๋Œ€ ์•ˆ ๋ณ€ํ•˜๋ฏ€๋กœ:

์ฒ˜์Œ: Thread 1(pri=31), Thread 2(pri=31), Thread 3(pri=25)
์‹คํ–‰ ์ˆœ์„œ: 1 โ†’ 2 โ†’ 1 โ†’ 2 โ†’ 1 โ†’ 2 โ†’ ... โ†’ 3

MLFQS:
์ฒ˜์Œ: Thread 1(pri=50), Thread 2(pri=50), Thread 3(pri=50)
10 ticks ํ›„: Thread 1(pri=45), Thread 2(pri=48), Thread 3(pri=47)
20 ticks ํ›„: Thread 1(pri=40), Thread 2(pri=46), Thread 3(pri=44)
โ†’ ๊ณ„์† ๋ณ€ํ•จ, ์˜ˆ์ธก ๋ถˆ๊ฐ€

์˜ˆ์ธก ๊ฐ€๋Šฅํ•œ ์ˆœ์„œ๋Š” ์บ์‹œ ํžˆํŠธ์œจ์„ ๋†’์ž…๋‹ˆ๋‹ค. ๊ฐ™์€ ์Šค๋ ˆ๋“œ๊ฐ€ ๊ทœ์น™์ ์œผ๋กœ ์‹คํ–‰๋˜๋ฉด ํ•ด๋‹น ์Šค๋ ˆ๋“œ์˜ ๋ฐ์ดํ„ฐ๊ฐ€ ์บ์‹œ์— ๋‚จ์•„์žˆ์„ ํ™•๋ฅ ์ด ๋†’์Šต๋‹ˆ๋‹ค.

์Šน๋ฆฌ ์ด์œ  3: Nice ๊ฐ’์ด ์•ฝํ•  ๋•Œ ์ฐจ์ด ์—†์Œ

nice 0์œผ๋กœ ๋ชจ๋‘ ๋™์ผํ•˜๊ฑฐ๋‚˜, nice -5~5 ๋ฒ”์œ„์ผ ๋•Œ:

  • Basic: priority ์ฐจ์ด ์ตœ๋Œ€ 10 (26~36)
  • MLFQS: nice*2 ์ฐจ์ด ์ตœ๋Œ€ 20, ํ•˜์ง€๋งŒ recent_cpu๊ฐ€ ๋” ํฐ ์˜ํ–ฅ
  • CFS: weight ์ฐจ์ด ์•ฝ 3๋ฐฐ, ํ•˜์ง€๋งŒ ์—ฌ์ „ํžˆ ๋ชจ๋‘ ๋น„์Šทํ•œ ์ˆ˜์ค€

โ†’ ์„ธ ์Šค์ผ€์ค„๋Ÿฌ ๋ชจ๋‘ ๊ฑฐ์˜ ๋ผ์šด๋“œ ๋กœ๋นˆ์ฒ˜๋Ÿผ ๋™์ž‘ โ†’ ์˜ค๋ฒ„ํ—ค๋“œ๊ฐ€ ๊ฐ€์žฅ ์ ์€ Basic์ด ์Šน๋ฆฌ

๊ฒฐ๋ก : Basic Priority๊ฐ€ ์Šน๋ฆฌํ•˜๋Š” ๊ฒƒ์€ ๋ฒ„๊ทธ๊ฐ€ ์•„๋‹ˆ๋ผ, **"ํŠน์ • ์›Œํฌ๋กœ๋“œ(CPU-bound, ์•ฝํ•œ nice)์—์„œ ๋‹จ์ˆœํ•จ์ด ์ตœ์„ "**์ด๋ผ๋Š” ๊ตํ›ˆ์ž…๋‹ˆ๋‹ค. ๊ณผ๋„ํ•œ ์ตœ์ ํ™”๋‚˜ ๋ณต์žกํ•œ ๊ณต์ •์„ฑ์ด ์˜คํžˆ๋ ค ์„ฑ๋Šฅ์„ ํ•ด์น  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


3. ์ปจํ…์ŠคํŠธ ์Šค์œ„์น˜ ์˜ค๋ฒ„ํ—ค๋“œ - ๊ณต์ •์„ฑ์˜ ๋Œ€๊ฐ€

์ธก์ • ๊ฒฐ๊ณผ (500 ์Šค๋ ˆ๋“œ ํ…Œ์ŠคํŠธ): CFS๊ฐ€ ์•ฝ๊ฐ„ ๋” ๋งŽ์€ ์ปจํ…์ŠคํŠธ ์Šค์œ„์น˜๋ฅผ ๋ฐœ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค.

์™œ CFS๊ฐ€ ๋” ๋งŽ์€๊ฐ€?

์ปจํ…์ŠคํŠธ ์Šค์œ„์น˜๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ฒฝ์šฐ:

  1. Time slice ๋งŒ๋ฃŒ
  2. I/O ๋Œ€๊ธฐ ์‹œ์ž‘
  3. ์Šค๋ ˆ๋“œ ์™„๋ฃŒ

CFS์˜ ํŠน์„ฑ:

vruntime ๊ธฐ๋ฐ˜ ์„ ํƒ โ†’ ํ•ญ์ƒ "๊ฐ€์žฅ ๋œ ๋ฐ›์€ ์Šค๋ ˆ๋“œ" ์„ ํƒ

์˜ˆ์‹œ (5๊ฐœ ์Šค๋ ˆ๋“œ):
vruntime: [1000, 1001, 1002, 1003, 1004]

Basic/MLFQS:
  - ์šฐ์„ ์ˆœ์œ„๊ฐ€ ๊ฐ™์œผ๋ฉด ๊ฐ™์€ ์Šค๋ ˆ๋“œ๊ฐ€ ์—ฌ๋Ÿฌ time slice ์—ฐ์† ์‹คํ–‰ ๊ฐ€๋Šฅ
  - ์˜ˆ: Thread 1์ด 4 slice ์—ฐ์† ์‹คํ–‰ โ†’ ์ปจํ…์ŠคํŠธ ์Šค์œ„์น˜ 3ํšŒ ๊ฐ์†Œ

CFS:
  - ๋งค slice ํ›„ vruntime ์ฆ๊ฐ€ โ†’ ๋‹ค์Œ pick_next()์—์„œ ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ ์„ ํƒ๋  ๊ฐ€๋Šฅ์„ฑ ๋†’์Œ
  - Thread 1(vruntime=1000) ์‹คํ–‰ โ†’ vruntime=2000
  - ๋‹ค์Œ: Thread 2(vruntime=1001) ์„ ํƒ (๊ฐ€์žฅ ์ž‘์Œ)
  - Thread 2 ์‹คํ–‰ โ†’ vruntime=2001
  - ๋‹ค์Œ: Thread 3(vruntime=1002) ์„ ํƒ
  โ†’ ๋งค๋ฒˆ ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ๋กœ ์ „ํ™˜!

๊ฒฐ๊ณผ: CFS๋Š” ๊ณต์ •์„ฑ์„ ์œ„ํ•ด ์Šค๋ ˆ๋“œ๋ฅผ ์ž์ฃผ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค โ†’ ์ปจํ…์ŠคํŠธ ์Šค์œ„์น˜ ์ฆ๊ฐ€

๊ทธ๋Ÿฐ๋ฐ ์™œ ์ฐจ์ด๊ฐ€ ์ž‘์„๊นŒ?

์ฐจ์ด๊ฐ€ ์ž‘์€ ์ด์œ ๋Š”:

  1. ๋Œ€๋ถ€๋ถ„์˜ ์ปจํ…์ŠคํŠธ ์Šค์œ„์น˜๋Š” I/O ๋•Œ๋ฌธ

    • I/O ๋Œ€๊ธฐ ์‹œ์ž‘ โ†’ ๋ฌด์กฐ๊ฑด ์ปจํ…์ŠคํŠธ ์Šค์œ„์น˜
    • ์ด๊ฒƒ์€ ๋ชจ๋“  ์Šค์ผ€์ค„๋Ÿฌ์—์„œ ๋™์ผ
  2. Time slice๊ฐ€ ์ถฉ๋ถ„ํžˆ ๊ธธ๋‹ค (4 ticks)

    • ๋„ˆ๋ฌด ์งง์œผ๋ฉด ๋งค tick๋งˆ๋‹ค ์ „ํ™˜ โ†’ 100% ์ฐจ์ด
    • 4 ticks๋Š” ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ๊ฐ€ time slice ๋‚ด์— ๋น„์Šทํ•œ progress๋ฅผ ๋งŒ๋“ฆ
  3. 500๊ฐœ ์Šค๋ ˆ๋“œ โ†’ ๋Œ€๋ถ€๋ถ„ ๋Œ€๊ธฐ ์ค‘

    • Ready queue์— ์žˆ๋Š” ์Šค๋ ˆ๋“œ: ํ‰๊ท  10-20๊ฐœ
    • ๋‚˜๋จธ์ง€๋Š” I/O ๋Œ€๊ธฐ ๋˜๋Š” ์™„๋ฃŒ
    • Ready ์Šค๋ ˆ๋“œ๊ฐ€ ์ ์œผ๋ฉด ์„ ํƒ์ง€๊ฐ€ ์ œํ•œ์  โ†’ ์ฐจ์ด ๊ฐ์†Œ

๊ฒฐ๋ก : CFS์˜ ์•ฝ๊ฐ„ ๋” ๋งŽ์€ ์ปจํ…์ŠคํŠธ ์Šค์œ„์น˜๋Š” **"๊ณต์ •์„ฑ์˜ ๋Œ€๊ฐ€๋กœ ์ถฉ๋ถ„ํžˆ ๋ฐ›์•„๋“ค์ผ ๋งŒํ•œ ์ˆ˜์ค€"**์ž…๋‹ˆ๋‹ค. ๊ฑฐ์˜ ๋ฌด์‹œํ•  ์ˆ˜ ์žˆ๋Š” ์˜ค๋ฒ„ํ—ค๋“œ์ž…๋‹ˆ๋‹ค.

์‹ค์ œ Linux ์‹œ์Šคํ…œ์—์„œ๋„ CFS์˜ ์ปจํ…์ŠคํŠธ ์Šค์œ„์น˜ ์˜ค๋ฒ„ํ—ค๋“œ๋Š” ์ธก์ •ํ•˜๊ธฐ ์–ด๋ ค์šธ ์ •๋„๋กœ ์ž‘์œผ๋ฉฐ, ๊ทธ ๋Œ€๊ฐ€๋กœ ์–ป๋Š” ๊ฐ€์ค‘์น˜ ๊ธฐ๋ฐ˜ ๊ณต์ •์„ฑ์€ ํ›จ์”ฌ ํฐ ๊ฐ€์น˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.


4. I/O Bound ์šฐ๋Œ€ - MLFQS์˜ ์ˆจ์€ ๊ฐ•์ 

์ธก์ • ๊ฒฐ๊ณผ (I/O-bound ํ…Œ์ŠคํŠธ):

ํ˜„์žฌ ์‹œ๋ฎฌ๋ ˆ์ด์…˜์—์„œ๋Š” ์„ธ ์Šค์ผ€์ค„๋Ÿฌ๊ฐ€ ์œ ์‚ฌํ•œ ์„ฑ๋Šฅ์„ ๋ณด์ž…๋‹ˆ๋‹ค. ์ด๋Š” I/O ํŒจํ„ด์ด ๋‹จ์ˆœํ™”๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

์ฐธ๊ณ : ์‹ค์ œ Linux ํ™˜๊ฒฝ์—์„œ MLFQS(BSD ์Šคํƒ€์ผ)๊ฐ€ I/O-bound ์ž‘์—…์—์„œ ๊ฐ•์ ์„ ๋ณด์ด๋Š” ์ด์œ ๋Š” ์•„๋ž˜์— ์„ค๋ช…๋œ recent_cpu ๋ฉ”์ปค๋‹ˆ์ฆ˜ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

MLFQS์˜ I/O ์šฐ๋Œ€ ๋ฉ”์ปค๋‹ˆ์ฆ˜ (์ด๋ก ):

MLFQS์˜ recent_cpu ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ์ดํ•ดํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค:

๋งค tick:
  - ์‹คํ–‰ ์ค‘์ธ ์Šค๋ ˆ๋“œ: recent_cpu++
  - I/O ๋Œ€๊ธฐ ์ค‘์ธ ์Šค๋ ˆ๋“œ: recent_cpu ์ฆ๊ฐ€ ์•ˆ ํ•จ (๋ณ€ํ™” ์—†์Œ)

100 ticks๋งˆ๋‹ค:
  recent_cpu = (2*load_avg)/(2*load_avg+1) * recent_cpu
  โ†’ ๋ชจ๋“  ์Šค๋ ˆ๋“œ์˜ recent_cpu ๊ฐ์‡ 

์˜ˆ์‹œ:
Thread A (CPU-bound):
  - 0~100 ticks: ๊ณ„์† ์‹คํ–‰ โ†’ recent_cpu = 100
  - 100 tick ์‹œ์ : recent_cpu = (2*5)/(2*5+1) * 100 โ‰ˆ 91 (์•ฝ๊ฐ„ ๊ฐ์‡ )
  - 101~200 ticks: ๊ณ„์† ์‹คํ–‰ โ†’ recent_cpu = 191
  - 200 tick ์‹œ์ : recent_cpu = 0.91 * 191 โ‰ˆ 174
  โ†’ recent_cpu๊ฐ€ ์ง€์†์ ์œผ๋กœ ๋†’์Œ

Thread B (I/O-bound, 80% I/O ๋Œ€๊ธฐ):
  - 0~100 ticks: 20 ticks๋งŒ ์‹คํ–‰ โ†’ recent_cpu = 20
  - 100 tick ์‹œ์ : recent_cpu = 0.91 * 20 โ‰ˆ 18
  - 101~200 ticks: 20 ticks๋งŒ ์‹คํ–‰ โ†’ recent_cpu = 38
  - 200 tick ์‹œ์ : recent_cpu = 0.91 * 38 โ‰ˆ 35
  โ†’ recent_cpu๊ฐ€ ๋‚ฎ๊ฒŒ ์œ ์ง€๋จ

์šฐ์„ ์ˆœ์œ„ ์ฐจ์ด:

priority = 63 - (recent_cpu / 4) - (nice * 2)

Thread A (CPU-bound, recent_cpu=174, nice=0):
  priority = 63 - 43 - 0 = 20 (๋‚ฎ์€ ์šฐ์„ ์ˆœ์œ„)

Thread B (I/O-bound, recent_cpu=35, nice=0):
  priority = 63 - 8 - 0 = 55 (๋†’์€ ์šฐ์„ ์ˆœ์œ„!)

๊ฒฐ๊ณผ: I/O-bound ์Šค๋ ˆ๋“œ๊ฐ€ I/O ์™„๋ฃŒ ํ›„ ready queue์— ๋Œ์•„์˜ค๋ฉด:

  • MLFQS: ๋†’์€ ์šฐ์„ ์ˆœ์œ„ (55) โ†’ ์ฆ‰์‹œ ์„ ํƒ๋จ โ†’ ๋น ๋ฅธ ์‘๋‹ต
  • Basic: ์ •์  ์šฐ์„ ์ˆœ์œ„ (31) โ†’ ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ๋“ค๊ณผ ๋™๋“ฑ โ†’ ๋А๋ฆฐ ์‘๋‹ต
  • CFS: vruntime ๊ธฐ๋ฐ˜ โ†’ I/O ๋Œ€๊ธฐ ์ค‘ vruntime ์ฆ๊ฐ€ ์•ˆ ํ–ˆ์œผ๋ฏ€๋กœ ์•ฝ๊ฐ„ ์œ ๋ฆฌ, ํ•˜์ง€๋งŒ ๋ช…์‹œ์  ์šฐ๋Œ€๋Š” ์—†์Œ

์™œ ์ด๊ฒŒ ์ค‘์š”ํ•œ๊ฐ€?

I/O-bound ์ž‘์—…์€ ๋ณดํ†ต ์‚ฌ์šฉ์ž ๋Œ€ํ™”ํ˜• ์ž‘์—…์ž…๋‹ˆ๋‹ค:

  • ์›น ๋ธŒ๋ผ์šฐ์ € (๋„คํŠธ์›Œํฌ I/O)
  • ํ…์ŠคํŠธ ์—๋””ํ„ฐ (ํ‚ค๋ณด๋“œ ์ž…๋ ฅ)
  • ๋น„๋””์˜ค ํ”Œ๋ ˆ์ด์–ด (ํŒŒ์ผ I/O)

์ด๋Ÿฐ ์ž‘์—…๋“ค์€ CPU๋ฅผ ์กฐ๊ธˆ๋งŒ ์“ฐ๊ณ  ๋ฐ”๋กœ I/O ๋Œ€๊ธฐ์— ๋“ค์–ด๊ฐ‘๋‹ˆ๋‹ค. MLFQS๋Š” ์ด๋ฅผ ์ž๋™์œผ๋กœ ๊ฐ์ง€ํ•˜๊ณ  ์šฐ๋Œ€ํ•˜์—ฌ ์‚ฌ์šฉ์ž๊ฐ€ ๋А๋ผ๋Š” ์‘๋‹ต์„ฑ์„ ํฌ๊ฒŒ ํ–ฅ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค.

CFS๋Š” ์™œ I/O ์šฐ๋Œ€๊ฐ€ ์—†๋‚˜?

CFS์˜ ์ฒ ํ•™์€ "Completely Fair"์ž…๋‹ˆ๋‹ค:

  • ๋ชจ๋“  ์Šค๋ ˆ๋“œ๋Š” weight์— ๋น„๋ก€ํ•˜์—ฌ ์ •ํ™•ํžˆ ๊ณตํ‰ํ•˜๊ฒŒ CPU๋ฅผ ๋ฐ›์•„์•ผ ํ•จ
  • I/O ๋Œ€๊ธฐ ์ค‘์ด๋“  CPU ์‚ฌ์šฉ ์ค‘์ด๋“ , ๊ทธ๊ฒƒ์€ ์Šค๋ ˆ๋“œ์˜ ์„ ํƒ์ด์ง€ ์Šค์ผ€์ค„๋Ÿฌ๊ฐ€ ํŒ๋‹จํ•  ๋ฌธ์ œ๊ฐ€ ์•„๋‹˜

์ด๊ฒƒ์€ ์ฒ ํ•™์˜ ์ฐจ์ด์ž…๋‹ˆ๋‹ค:

  • MLFQS: "I/O ๋Œ€๊ธฐ๊ฐ€ ๋งŽ์œผ๋ฉด ๋Œ€ํ™”ํ˜• ์ž‘์—…์ผ ๊ฒƒ์ด๋‹ค โ†’ ์šฐ๋Œ€ํ•˜์ž"
  • CFS: "๋ชจ๋“  ์Šค๋ ˆ๋“œ๋ฅผ ๊ณตํ‰ํ•˜๊ฒŒ, I/O๋“  CPU๋“  ์ƒ๊ด€์—†์ด"

๊ฒฐ๋ก : MLFQS๊ฐ€ I/O-bound์—์„œ ์Šน๋ฆฌํ•˜๋Š” ๊ฒƒ์€ ์šฐ์—ฐ์ด ์•„๋‹ˆ๋ผ, "์›Œํฌ๋กœ๋“œ ํŒจํ„ด์„ ๊ด€์ฐฐํ•˜๊ณ  ์ ์‘"ํ•˜๋Š” ์„ค๊ณ„์˜ ๊ฒฐ๊ณผ์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด FreeBSD๊ฐ€ ์˜ค๋žซ๋™์•ˆ MLFQS ๊ณ„์—ด ์Šค์ผ€์ค„๋Ÿฌ๋ฅผ ์œ ์ง€ํ•œ ์ด์œ ์ด๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค.


7. ์•„์‰ฌ์šด ์ ๊ณผ ๊ฐœ์„  ๋ฐฉํ–ฅ

7.1 ๊ตฌํ˜„ํ•˜์ง€ ๋ชปํ•œ ๊ธฐ๋Šฅ

1. ๋ฉ€ํ‹ฐ CPU

  • ํ˜„์žฌ: ๋‹จ์ผ CPU ์‹œ๋ฎฌ๋ ˆ์ด์…˜
  • ํ•„์š”: Load balancing, cache coherency, migration cost
  • ์˜ํ–ฅ: ํ˜„๋Œ€ ๋ฉ€ํ‹ฐ์ฝ”์–ด ํ™˜๊ฒฝ์˜ ์‹ค์ œ ๋™์ž‘ ๋ฐ˜์˜ ๋ชป ํ•จ

2. Real-time ์Šค์ผ€์ค„๋Ÿฌ

  • ํ˜„์žฌ: Fair ์Šค์ผ€์ค„๋Ÿฌ๋งŒ (Basic, MLFQS, CFS)
  • ๋ถ€์žฌ: SCHED_FIFO, SCHED_RR, SCHED_DEADLINE
  • ์ด์œ : ํ…Œ์ŠคํŠธ ๋ฐฉ๋ฒ•๋ก ์ด ๋‹ค๋ฆ„ (deadline, response time)

3. I/O ์Šค์ผ€์ค„๋Ÿฌ ํ†ตํ•ฉ

  • ํ˜„์žฌ: I/O๋Š” ๋‹จ์ˆœ ๋Œ€๊ธฐ๋กœ ๋ชจ๋ธ๋ง
  • ์ด์ƒ: Block I/O scheduler์™€ ํ†ตํ•ฉ (CFQ, Deadline, NOOP)

7.2 ์ธก์ •์˜ ํ•œ๊ณ„

CFS ์ด๋ก ๊ฐ’๊ณผ ์‹ค์ œ๊ฐ’ ๊ดด๋ฆฌ

CFS์˜ ์‹ค์ œ ์ธก์ •๊ฐ’์ด ์ด๋ก ์  weight ๋น„์œจ๋ณด๋‹ค ์•ฝํ•˜๊ฒŒ ๋‚˜์˜ต๋‹ˆ๋‹ค.

๊ฐ€๋Šฅํ•œ ์›์ธ:

  • ์ปจํ…์ŠคํŠธ ์Šค์œ„์น˜ ์˜ค๋ฒ„ํ—ค๋“œ (4 ticks time slice)
  • vruntime ์Šค์ผ€์ผ์˜ ๋ถ€์ž‘์šฉ
  • ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ์กฐ๊ธฐ ์ข…๋ฃŒ์˜ ์˜ํ–ฅ

์ถ”๊ฐ€ ๋ถ„์„ ํ•„์š”: ๋” ๊ธด ์‹œ๋ฎฌ๋ ˆ์ด์…˜, ๋” ํฐ burst_time์œผ๋กœ ์žฌํ…Œ์ŠคํŠธ

Starvation ์ธก์ •

  • ํ˜„์žฌ: "has_starvation" boolean ํ”Œ๋ž˜๊ทธ๋งŒ
  • ์ด์ƒ: ์‹ค์ œ ๋Œ€๊ธฐ ์‹œ๊ฐ„ ๋ถ„ํฌ, ์ตœ์•… ์ผ€์ด์Šค ๋Œ€๊ธฐ ์‹œ๊ฐ„, P99 latency

7.3 ์‚ฌ์šฉ์ž ๊ฒฝํ—˜ ๊ฐœ์„ 

์‹œ๋ฎฌ๋ ˆ์ด์…˜ ์‹œ๊ฐ„

  • ํ˜„์žฌ: 500 ์Šค๋ ˆ๋“œ ํ…Œ์ŠคํŠธ 10์ดˆ ์ด์ƒ ์†Œ์š”
  • ๊ฐœ์„ : Python ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋”ฉ, Cython ์ตœ์ ํ™”, C ํ™•์žฅ ๋ชจ๋“ˆ

๊ฒฐ๊ณผ ์‹œ๊ฐํ™”

  • ํ˜„์žฌ: ๊ธฐ๋ณธ์ ์ธ ๋ง‰๋Œ€ ๊ทธ๋ž˜ํ”„
  • ์ด์ƒ:
    • ์‹œ๊ฐ„์— ๋”ฐ๋ฅธ ready queue ๋ณ€ํ™” ์• ๋‹ˆ๋ฉ”์ด์…˜
    • vruntime/priority ๋ณ€ํ™” ์ถ”์ด ๊ทธ๋ž˜ํ”„
    • ๊ฐ„ํŠธ ์ฐจํŠธ (Gantt chart)
    • ์Šค๋ ˆ๋“œ๋ณ„ ์‹คํ–‰ ํƒ€์ž„๋ผ์ธ

8. ํšŒ๊ณ 

8.1 ๊ธฐ์ˆ ์  ์„ฑ์žฅ

Before

  • CPU ์Šค์ผ€์ค„๋ง: ์ด๋ก ์  ๊ฐœ๋… (FIFO, SJF, RR, Priority)
  • ์šด์˜์ฒด์ œ: "์–ด๋ ต๊ณ  ๋ณต์žกํ•œ ๊ฒƒ"
  • ๋””๋ฒ„๊น…: print() ๋‚จ๋ฐœ, ๋ง‰์—ฐํ•œ ์ถ”์ธก

After

  • CPU ์Šค์ผ€์ค„๋ง: ๊ตฌํ˜„ ๊ฐ€๋Šฅํ•œ ์•Œ๊ณ ๋ฆฌ์ฆ˜, ์ธก์ • ๊ฐ€๋Šฅํ•œ ํŠธ๋ ˆ์ด๋“œ์˜คํ”„
  • ์šด์˜์ฒด์ œ: "๋ณต์žกํ•˜์ง€๋งŒ ์ดํ•ด ๊ฐ€๋Šฅํ•œ ์‹œ์Šคํ…œ"
  • ๋””๋ฒ„๊น…: ๊ฐ€์„ค ์ˆ˜๋ฆฝ โ†’ ๊ฒ€์ฆ โ†’ ์ˆ˜์ •์˜ ์ฒด๊ณ„์  ์ ‘๊ทผ

8.2 ํ•ต์‹ฌ ์ธ์‚ฌ์ดํŠธ

์šด์˜์ฒด์ œ๋Š” Trade-off์˜ ์˜ˆ์ˆ 

  • Basic Priority: ๋‹จ์ˆœ, ์˜ˆ์ธก ๊ฐ€๋Šฅ, ์˜ค๋ฒ„ํ—ค๋“œ ์ตœ์†Œ โ†’ ํ•˜์ง€๋งŒ ๋ถˆ๊ณต์ •, starvation ์œ„ํ—˜
  • MLFQS: ๋™์ , ์‘๋‹ต์„ฑ ์šฐ์ˆ˜, I/O ์šฐ๋Œ€ โ†’ ํ•˜์ง€๋งŒ ๋ณต์žก, nice ํšจ๊ณผ ์•ฝํ•จ
  • CFS: ์™„๋ฒฝํ•œ ๊ณต์ •์„ฑ, ๊ฐ•ํ•œ nice ํšจ๊ณผ โ†’ ํ•˜์ง€๋งŒ I/O ์šฐ๋Œ€ ์—†์Œ, ์•ฝ๊ฐ„์˜ ์˜ค๋ฒ„ํ—ค๋“œ

์™„๋ฒฝํ•œ ์Šค์ผ€์ค„๋Ÿฌ๋Š” ์—†์Šต๋‹ˆ๋‹ค. ๊ฐ ์›Œํฌ๋กœ๋“œ, ๊ฐ ์‹œ์Šคํ…œ ์š”๊ตฌ์‚ฌํ•ญ์— ๋งž๋Š” ์„ ํƒ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

์ธก์ • ์—†๋Š” ์ตœ์ ํ™”๋Š” ๋งน๋ชฉ

"CFS๊ฐ€ ๋ฌด์กฐ๊ฑด ์ข‹๋‹ค"๋Š” ๋ง‰์—ฐํ•œ ๋ฏฟ์Œ์ด ์žˆ์—ˆ์ง€๋งŒ, ์‹ค์ œ ์ธก์ • ๊ฒฐ๊ณผ:

  • I/O-bound ์›Œํฌ๋กœ๋“œ: MLFQS ์Šน๋ฆฌ
  • CPU-bound ์›Œํฌ๋กœ๋“œ: Basic ์Šน๋ฆฌ (์˜ค๋ฒ„ํ—ค๋“œ ์ตœ์†Œ)
  • ๊ณต์ •์„ฑ: CFS ์Šน๋ฆฌ

์ƒํ™ฉ์— ๋”ฐ๋ผ ๋‹ค๋ฆ…๋‹ˆ๋‹ค.

๋””๋ฒ„๊น…์€ ๊ณผํ•™์  ๋ฐฉ๋ฒ•๋ก 

  1. ๊ด€์ฐฐ: ์ด์ƒํ•œ ๊ฒฐ๊ณผ (vruntime=0, ๋ชจ๋‘ tie, ํ•œ ์ชฝ ์••์Šน)
  2. ๊ฐ€์„ค: "Time slice๊ฐ€ ์—†๋‚˜?", "์ •์ˆ˜ ๋‚˜๋ˆ—์…ˆ ๋ฌธ์ œ?", "FIFO ์ˆœ์„œ ๋ฌธ์ œ?"
  3. ์‹คํ—˜: print() ๋””๋ฒ„๊น…, ๋‹จ์ˆœํ™”๋œ ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค, ๋‹จ๊ณ„๋ณ„ ์‹คํ–‰
  4. ๊ฒ€์ฆ: ์ˆ˜์ • ํ›„ ๊ฒฐ๊ณผ ํ™•์ธ, ์ด๋ก ๊ฐ’๊ณผ ๋น„๊ต, ๋‹ค๋ฅธ ํ…Œ์ŠคํŠธ์—์„œ๋„ ํ™•์ธ

9. ๊ฒฐ๋ก 

ํ”„๋กœ์ ํŠธ ์š”์•ฝ

์ด ํ”„๋กœ์ ํŠธ๋Š” ๋‹จ์ˆœํžˆ "์Šค์ผ€์ค„๋Ÿฌ 3๊ฐœ๋ฅผ ๊ตฌํ˜„"ํ•˜๋Š” ๊ฒƒ์„ ๋„˜์–ด์„œ, ์šด์˜์ฒด์ œ์˜ ํ•ต์‹ฌ ํŠธ๋ ˆ์ด๋“œ์˜คํ”„๋ฅผ ์ง์ ‘ ์ฒดํ—˜ํ•˜๋Š” ์—ฌ์ •์ด์—ˆ์Šต๋‹ˆ๋‹ค.

6๊ฐ€์ง€ ์ฃผ์š” ๋ฒ„๊ทธ๋ฅผ ์ˆ˜์ •ํ•˜๋ฉด์„œ:

  • ์ด๋ก ๊ณผ ๊ตฌํ˜„์˜ ๊ดด๋ฆฌ๋ฅผ ๊นŠ์ด ์ดํ•ดํ–ˆ๊ณ 
  • ์ •์ˆ˜ ์—ฐ์‚ฐ๊ณผ ๊ณ ์ •์†Œ์ˆ˜์ ์˜ ์ค‘์š”์„ฑ์„ ์ฒดํ—˜ํ–ˆ์œผ๋ฉฐ
  • ์ธก์ • ๋ฐฉ๋ฒ•๋ก ์˜ ์ค‘์š”์„ฑ์„ ๊นจ๋‹ฌ์•˜์Šต๋‹ˆ๋‹ค

๋ชฉํ‘œ ๊ธฐ๋ฐ˜ ํ…Œ์ŠคํŠธ ์„ค๊ณ„๋ฅผ ํ†ตํ•ด:

  • ๊ณต์ •ํ•œ ๋น„๊ต ๋ฐฉ๋ฒ•๋ก ์„ ํ™•๋ฆฝํ–ˆ๊ณ 
  • ๊ฐ ์Šค์ผ€์ค„๋Ÿฌ์˜ ์ง„์งœ ๊ฐ•์ ์„ ๋ฐœ๊ฒฌํ–ˆ์Šต๋‹ˆ๋‹ค

์ตœ์ข… ์„ฑ๊ณผ

  • ์ฝ”๋“œ: 3๊ฐœ ์Šค์ผ€์ค„๋Ÿฌ, 9๊ฐ€์ง€ ์›Œํฌ๋กœ๋“œ, 18๊ฐœ ํ…Œ์ŠคํŠธ
  • ๋ฐฐํฌ: GCP VM์— 24/7 ์šด์˜ ์ค‘ (http://34.47.105.226:8501)
  • ๊ฒฐ๊ณผ: ์œ ์˜๋ฏธํ•œ ํŽธํ–ฅ ์—†๋Š” ๊ณต์ •ํ•œ ๋น„๊ต
    • ๊ฐ ์Šค์ผ€์ค„๋Ÿฌ๊ฐ€ ์ž์‹ ์˜ ๊ฐ•์ ์—์„œ๋งŒ ์Šน๋ฆฌ

๊ฐœ์ธ์  ์„ฑ์žฅ

Before: CPU ์Šค์ผ€์ค„๋ง์€ ํ˜„์—…๊ณผ ๋™๋–จ์–ด์ง„ OS ๊ณต๋ถ€์šฉ ์ด๋ก  After: ์‹ค์ œ๋กœ ๊ตฌํ˜„ ๊ฐ€๋Šฅํ•˜๊ณ , ๊ฐ๊ฐ์˜ ํŠธ๋ ˆ์ด๋“œ์˜คํ”„๋ฅผ ์ •๋Ÿ‰์ ์œผ๋กœ ์ธก์ •ํ•  ์ˆ˜ ์žˆ๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜

์ด์ œ "์™œ Linux๊ฐ€ CFS๋ฅผ ์„ ํƒํ–ˆ๋Š”๊ฐ€?"๋ผ๋Š” ์งˆ๋ฌธ์— ๋‹ตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

  • ๊ทน๋‹จ์  nice ๊ฐ€์ค‘์น˜์—์„œ ๊ณต์ •์„ฑ ์šฐ์œ„: ๋‹ค์–‘ํ•œ nice ๊ฐ’์ด ์„ž์ธ ์›Œํฌ๋กœ๋“œ์—์„œ CFS๊ฐ€ ๋” ์ •ํ™•ํ•œ ๋น„๋ก€ ๋ฐฐ๋ถ„
  • ์˜ˆ์ธก ๊ฐ€๋Šฅ์„ฑ: vruntime์€ ๋‹จ์ˆœํ•˜๊ณ  ์˜ˆ์ธก ๊ฐ€๋Šฅ
  • ๋‹จ์  ๊ฐ์ˆ˜: I/O ์šฐ๋Œ€ ์—†์Œ, ์•ฝ๊ฐ„์˜ ์˜ค๋ฒ„ํ—ค๋“œ โ†’ ๊ณต์ •์„ฑ์˜ ๋Œ€๊ฐ€๋กœ ๋ฐ›์•„๋“ค์ž„

๊ฐ์‚ฌ์˜ ๋ง

์ด ํ”„๋กœ์ ํŠธ๋Š” ๋‹ค์Œ์˜ ๋„์›€์œผ๋กœ ๊ฐ€๋Šฅํ–ˆ์Šต๋‹ˆ๋‹ค:

  • PintOS ๋ฌธ์„œ: MLFQS 17.14 ๊ณ ์ •์†Œ์ˆ˜์  ์—ฐ์‚ฐ ์ƒ์„ธ ์„ค๋ช…
  • Linux ์ปค๋„ ์†Œ์Šค: CFS PRIO_TO_WEIGHT ํ…Œ์ด๋ธ” (kernel/sched/core.c)
  • FreeBSD ์†Œ์Šค: MLFQS ๊ตฌํ˜„ ์ฐธ์กฐ (sys/kern/sched_4bsd.c)
  • StackOverflow: ์ •์ˆ˜ ๋‚˜๋ˆ—์…ˆ ์ •๋ฐ€๋„ ๋ฌธ์ œ ํ•ด๊ฒฐ ํžŒํŠธ
  • Operating System: Three Easy Pieces: ์šด์˜์ฒด์ œ๋ฅผ 3๊ฐ€์ง€ ํ•ญ๋ชฉ์œผ๋กœ ๋ถ„๋ฅ˜ํ•˜์—ฌ ์šด์˜์ฒด์ œ ์ดํ•ด ์ž์ฒด์— ๊ฒฐ์ •์ ์ธ ๋„์›€์„ ์„ ์‚ฌ, ์ด ์ฑ…์ด ์•„๋‹ˆ์—ˆ์œผ๋ฉด ์ด ํ”„๋กœ์ ํŠธ๋Š” ์ ˆ๋Œ€ ๋งˆ๋ฌด๋ฆฌ ๋  ์ˆ˜ ์—†์—ˆ์Šต๋‹ˆ๋‹ค
  • ๊ทธ๋ฆฌ๊ณ  ๋ฌด์—‡๋ณด๋‹ค, ๋๊นŒ์ง€ ํฌ๊ธฐํ•˜์ง€ ์•Š์€ ๋‚˜ ์ž์‹ ์—๊ฒŒ.

ํ”„๋กœ์ ํŠธ ์ •๋ณด

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published