Skip to content

Diff Engines

Won-Kyu Park edited this page Aug 4, 2026 · 2 revisions

Diff ์—”์ง„

SimpleRCS ์•ˆ์—๋Š” diff ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ์—ฌ๋Ÿฌ ๋ฒŒ ์žˆ๋‹ค. ์™œ ์ด๋ ‡๊ฒŒ ๋งŽ๊ณ , ์‹ค์ œ๋กœ ๋ญ๊ฐ€ ๋Œ์•„๊ฐ€๊ณ  ์žˆ๊ณ , ๋‚˜๋จธ์ง€๋Š” ์™œ ์•„์ง๋„ ๋ถ™์–ด์žˆ๋Š”์ง€๋ฅผ ์ •๋ฆฌํ•œ๋‹ค.

์‹ค์ œ๋กœ ์“ฐ์ด๋Š” ๊ฑด ํ•˜๋‚˜๋ฟ์ด๋‹ค

commit()/checkout()์ด ๋ธํƒ€๋ฅผ ๊ณ„์‚ฐํ•  ๋•Œ ๋ถ€๋ฅด๋Š” ๊ฑด pydifflib.py์˜ StreamSequenceMatcher ๋”ฑ ํ•˜๋‚˜๋‹ค. ๋‚˜๋จธ์ง€(Myers ๊ณ„์—ด, Cython ๋ฒ„์ „)๋Š” ์ „๋ถ€ tools/bench_diff.py๋ฅผ ํ†ตํ•œ ๋น„๊ต/๋ฒค์น˜๋งˆํฌ์šฉ์œผ๋กœ๋งŒ ์กด์žฌํ•œ๋‹ค.

StreamSequenceMatcher๊ฐ€ ํ•˜๋Š” ์ผ

ํ•ด์‹œ ๊ธฐ๋ฐ˜ ๊ทธ๋ฆฌ๋”” ๋งค์นญ์ด๋‹ค. ๋Œ€๋žต ์ด๋Ÿฐ ์ˆœ์„œ๋กœ ๋™์ž‘ํ•œ๋‹ค.

  1. ์–‘์ชฝ ์‹œํ€€์Šค๋ฅผ ํ•ด์‹œ๋กœ ์ธ๋ฑ์‹ฑํ•ด์„œ ๋™์ผํ•œ ๋ผ์ธ๋“ค์„ ๋น ๋ฅด๊ฒŒ ์ฐพ๋Š”๋‹ค
  2. ๋งค์นญ๋˜๋Š” ๋ธ”๋ก๋“ค์„ ๊ทธ๋ฆฌ๋””ํ•˜๊ฒŒ ๊ณจ๋ผ ๋ถ™์ธ๋‹ค
  3. ๋งค์นญ ์•ˆ ๋˜๊ณ  ๋‚จ์€ "๊ต์ฒด(replace)" ๊ตฌ๊ฐ„๋งŒ ํ‘œ์ค€ difflib์œผ๋กœ ๋‹ค๋“ฌ๋Š”๋‹ค

์ตœ๋‹จ ํŽธ์ง‘ ๊ฑฐ๋ฆฌ๋ฅผ ์ˆ˜ํ•™์ ์œผ๋กœ ๋ณด์žฅํ•˜์ง€๋Š” ์•Š๋Š”๋‹ค. ํ•˜์ง€๋งŒ O(N)์— ๊ฐ€๊น๊ฒŒ ๋น ๋ฅด๊ณ , ์‹ค๋ฌด์—์„œ ๋‚˜์˜ค๋Š” diff ๊ฒฐ๊ณผ๊ฐ€ ๋Œ€๋ถ€๋ถ„ ์ถฉ๋ถ„ํžˆ ์ž์—ฐ์Šค๋Ÿฝ๋‹ค. ์ปค๋ฐ‹ ๊ฒฝ๋กœ์ฒ˜๋Ÿผ "์ •ํ™•ํ•œ ์ตœ์†Œ ํŽธ์ง‘ ์Šคํฌ๋ฆฝํŠธ"๋ณด๋‹ค "๋น ๋ฅด๊ณ  ํ•ฉ๋ฆฌ์ ์ธ ๋ธํƒ€"๊ฐ€ ๋” ์ค‘์š”ํ•œ ์ž๋ฆฌ์— ๋งž๋Š” ์„ ํƒ์ด๋‹ค.

Myers ๊ณ„์—ด์€ ์™œ ๋”ฐ๋กœ ์žˆ๋‚˜

myersdiff.py, myersdiff_ses.py, myersdiff_dmp.py๋Š” ์ „ํ†ต์ ์ธ Myers O(ND) ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ์ˆœ์ˆ˜ ํŒŒ์ด์ฌ ๊ตฌํ˜„์ด๋‹ค. ์ด์ชฝ์€ ์ตœ๋‹จ ํŽธ์ง‘ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ˆ˜ํ•™์ ์œผ๋กœ ๋ณด์žฅํ•œ๋‹ค โ€” Git์˜ xdiff๊ฐ€ ์“ฐ๋Š” ๊ฒƒ๊ณผ ๊ฐ™์€ ๊ณ„์—ด์˜ ์•Œ๊ณ ๋ฆฌ์ฆ˜.

  • SES ๋ณ€ํ˜•: ํ‘œ์ค€์ ์ธ ์ตœ๋‹จ ํŽธ์ง‘ ์Šคํฌ๋ฆฝํŠธ ๊ณ„์‚ฐ
  • DMP ๋ณ€ํ˜•: Neil Fraser์˜ diff-match-patch ๋ฐฉ์‹๋Œ€๋กœ "middle snake" ์ „๋žต์„ ์“ฐ๋˜ ๋ฆฌ์ŠคํŠธ ์Šฌ๋ผ์ด์‹ฑ ๋Œ€์‹  ์˜คํ”„์…‹์„ ๊ณ„์† ๋„˜๊ฒจ์„œ ๊ณ„์‚ฐํ•œ๋‹ค. ๊ฒฐ๊ณผ์ ์œผ๋กœ SES์™€ ๊ฐ™์€ ํŽธ์ง‘ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋‚ด์ง€๋งŒ ๊ตฌํ˜„ ๋ฐฉ์‹์ด ๋‹ค๋ฅด๋‹ค.

O(ND) ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ์•ฝ์ ์€ ๋‘ ์ž…๋ ฅ์ด ๋งŽ์ด ๋‹ค๋ฅผ ๋•Œ ์„ฑ๋Šฅ์ด ๋‚˜๋น ์ง„๋‹ค๋Š” ๊ฒƒ์ด๋‹ค โ€” ์ตœ์•…์˜ ๊ฒฝ์šฐ 500KB ์ •๋„ ํฌ๊ธฐ์— 10% ์ •๋„๋งŒ ๋‹ฌ๋ผ๋„ ์ดˆ ๋‹จ์œ„๋กœ ๋А๋ ค์งˆ ์ˆ˜ ์žˆ๋‹ค. StreamSequenceMatcher๊ฐ€ ์ด ์ผ€์ด์Šค์—์„œ ํ›จ์”ฌ ์•ˆ์ „ํ•˜๋‹ค.

Cython ๋ฒ„์ „ (_myersdiff_ses.pyx, _myersdiff_dmp.pyx)

์œ„ ๋‘ Myers ๊ตฌํ˜„์„ ๊ทธ๋Œ€๋กœ Cython์œผ๋กœ ํฌํŒ…ํ•œ ๊ฒƒ. ์ˆœ์ˆ˜ ํŒŒ์ด์ฌ ๋Œ€๋น„ 15~26๋ฐฐ ๋น ๋ฅด๋‹ค๋Š” ๊ฑธ ๋ฒค์น˜๋งˆํฌ๋กœ ํ™•์ธํ–ˆ์ง€๋งŒ, ์ง€๊ธˆ์€ ์ปค๋ฐ‹ ๊ฒฝ๋กœ์— ์—ฐ๊ฒฐ๋ผ ์žˆ์ง€ ์•Š๋‹ค. pyproject.toml์˜ ext-modules์— ๋“ฑ๋ก๋ผ ์žˆ์–ด์„œ uv sync ์‹œ ๊ฐ™์ด ๋นŒ๋“œ๋œ๋‹ค.

์‹ค์ธก: ์–ด๋А ๊ฒŒ ์‹ค์ œ๋กœ ๋” ๋น ๋ฅธ๊ฐ€

docs/parser_benchmark.md์— ์žˆ๋Š” ๋ฒค์น˜๋งˆํฌ ๊ฒฐ๊ณผ๋ฅผ ์š”์•ฝํ•˜๋ฉด:

  • ์ž‘์€ ๋ธํƒ€ ๋ธ”๋ก(์ˆ˜๋ฐฑ ๋ฐ”์ดํŠธ) ๊ธฐ์ค€์œผ๋กœ๋Š” ํŒŒ์„œ/diff ์—”์ง„ ๊ฐ„ ์ฐจ์ด๊ฐ€ ์ฒด๊ฐ๋˜์ง€ ์•Š๋Š”๋‹ค โ€” ์˜ค์ฐจ๋ฒ”์œ„ ์•ˆ.
  • ๋ธ”๋ก์ด ์ปค์งˆ์ˆ˜๋ก(1.6KB โ†’ 92KB) ์ฐจ์ด๊ฐ€ ๋ฒŒ์–ด์ง„๋‹ค. ์ด๊ฑด diff ์—”์ง„ ์ž์ฒด๋ณด๋‹ค๋Š” ๋ธ”๋ก ํŒŒ์‹ฑ ์ชฝ ์–˜๊ธฐ์ง€๋งŒ, ๊ฐ™์€ ์›๋ฆฌ๋กœ "ํฐ ์ž…๋ ฅ์—์„œ ๋ฒŒ์–ด์ง€๋Š” ๊ฒฉ์ฐจ"๊ฐ€ diff ์—”์ง„ ์„ ํƒ์—๋„ ๊ทธ๋Œ€๋กœ ์ ์šฉ๋œ๋‹ค.
  • Cython ํฌํŒ…์€ ์ˆœ์ˆ˜ ํŒŒ์ด์ฌ ๋Œ€๋น„ 5~10๋ฐฐ ๋‹จ์ถ•์ด ํ˜„์‹ค์ ์ธ ๋ฒ”์œ„ โ€” ํŒŒ์ด์ฌ ๋ฐ”์ดํŠธ์ฝ”๋“œ ๋””์ŠคํŒจ์น˜ ์˜ค๋ฒ„ํ—ค๋“œ๋ฅผ ์—†์• ๋Š” ํšจ๊ณผ๊ฐ€ ํฌ๋‹ค.

๊ทธ๋Ÿผ ๋ญ˜ ์จ์•ผ ํ•˜๋‚˜

  • ์ง€๊ธˆ ๊ทธ๋Œ€๋กœ ์จ๋„ ๋œ๋‹ค. StreamSequenceMatcher๋Š” ์ด๋ฏธ ํ”„๋กœ๋•์…˜ ๊ฒฝ๋กœ์—์„œ ๊ฒ€์ฆ๋๊ณ , ์ผ๋ฐ˜์ ์ธ ํ…์ŠคํŠธ ํŽธ์ง‘(์ค„ ๋‹จ์œ„ ์ˆ˜์ •)์—์„œ๋Š” ์ตœ๋‹จ ํŽธ์ง‘ ๊ฑฐ๋ฆฌ์™€ ์‹ค์งˆ์ ์œผ๋กœ ์ฐจ์ด๊ฐ€ ์•ˆ ๋‚œ๋‹ค.
  • Myers ๊ณ„์—ด(ํŠนํžˆ Cython ๋ฒ„์ „)์ด ์˜๋ฏธ ์žˆ์–ด์ง€๋Š” ์‹œ์ ์€ "์ •ํ™•ํžˆ ์ตœ์†Œ ํŽธ์ง‘ ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ํ•„์š”ํ•˜๋‹ค"๊ฑฐ๋‚˜, "๋Œ€๋Ÿ‰์˜ ๋ธํƒ€๋ฅผ ๋ฐฐ์น˜๋กœ ์žฌ๊ณ„์‚ฐํ•ด์•ผ ํ•œ๋‹ค" ๊ฐ™์€ ํŠน์ˆ˜ํ•œ ์š”๊ตฌ๊ฐ€ ์ƒ๊ฒผ์„ ๋•Œ๋‹ค.
  • ์ƒˆ๋กœ diff ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ๋ถ™์ด๊ณ  ์‹ถ๋‹ค๋ฉด tools/bench_diff.py๊ฐ€ ์ด๋ฏธ ๋น„๊ต ํ”„๋ ˆ์ž„์„ ๊ฐ–์ถ”๊ณ  ์žˆ์œผ๋‹ˆ ๊ฑฐ๊ธฐ์— ์ผ€์ด์Šค๋ฅผ ์ถ”๊ฐ€ํ•ด์„œ ์‹ค์ธก๋ถ€ํ„ฐ ํ•˜๋Š” ๊ฑธ ๊ถŒํ•œ๋‹ค.

์ง์ ‘ ๋น„๊ตํ•ด๋ณด๊ธฐ

uv run tools/bench_diff.py

์‹œ๊ฐ„๊ณผ ๋ฉ”๋ชจ๋ฆฌ(peak, tracemalloc ๊ธฐ์ค€) ๋‘˜ ๋‹ค ๋น„๊ตํ•ด์ค€๋‹ค. ํŠน์ • ์—”์ง„ ํ•˜๋‚˜๋กœ ๋‘ ๋ฒ„์ „ ์‚ฌ์ด diff๋ฅผ ์ง์ ‘ ๋ณด๊ณ  ์‹ถ์œผ๋ฉด:

uv run tools/srcs_diff.py <ํŒŒ์ผ> --engine ses   # ๋˜๋Š” dmp, pydifflib, myers, difflib

Clone this wiki locally