ekp/ekp_c
2026-01-25 17:28:04 +08:00
..
ekp_hyphen.c add dynamic moudle to improve prefermance 2026-01-25 13:50:46 +08:00
ekp_kp.c improve C module parallel 2026-01-25 17:28:04 +08:00
ekp_module.h improve C module parallel 2026-01-25 17:28:04 +08:00
ekp_paragraph.c add dynamic moudle to improve prefermance 2026-01-25 13:50:46 +08:00
ekp_thread_pool.c add dynamic moudle to improve prefermance 2026-01-25 13:50:46 +08:00
ekp.c improve C module parallel 2026-01-25 17:28:04 +08:00
Makefile add dynamic moudle to improve prefermance 2026-01-25 13:50:46 +08:00
README.md add dynamic moudle to improve prefermance 2026-01-25 13:50:46 +08:00

EKP C Dynamic Module

High-performance C implementation of the Knuth-Plass line breaking algorithm with multi-threaded parallel computation.

Architecture

ekp_c/
├── ekp_module.h      # Core data structures and API declarations
├── ekp.c             # Emacs module entry point (emacs_module_init)
├── ekp_kp.c          # Knuth-Plass DP algorithm + global state
├── ekp_hyphen.c      # Liang hyphenation with thread-safe caching
├── ekp_paragraph.c   # Text tokenization and box/glue construction
├── ekp_thread_pool.c # Work-stealing thread pool
└── Makefile          # Build system

Building

cd ekp_c
make

Requirements:

  • C11 compiler (clang, gcc)
  • Emacs with dynamic module support (27.1+)
  • pthread library

Build Options

make DEBUG=1    # Debug build with sanitizers
make clean      # Remove build artifacts
make info       # Show build configuration
make test       # Run basic tests in Emacs

Performance Optimizations

1. Multi-threaded Processing

  • 8-thread pool for parallel DP candidate evaluation
  • Wavefront parallelization for large paragraphs (>100 boxes)
  • Lock-free work queue with condition variables

2. O(1) Range Queries

  • Prefix sum arrays for ideal/min/max line widths
  • Eliminates repeated summation in inner DP loop

3. Fast Hyphenation

  • FNV-1a hash for O(1) pattern lookup
  • Thread-safe LRU cache (4096 entries)
  • Read-write locks for concurrent access

4. Memory Layout

  • Flat, cache-friendly data structures
  • Parallel arrays for boxes, glues, widths
  • Minimal allocations in hot paths

API

Initialization

(ekp-c-init)           ; Initialize module with thread pool
(ekp-c-cleanup)        ; Release all resources
(ekp-c-version)        ; => "1.0"
(ekp-c-thread-count)   ; => 8

Hyphenation

(ekp-c-load-hyphenator "/path/to/hyph_en_US.dic")  ; => 0 (index)
(ekp-c-hyphenate 0 "hyphenation")                  ; => (2 5 7)

Line Breaking

(ekp-c-break-lines
  "Your paragraph text here"
  0                                    ; hyphenator index
  600                                  ; line width in pixels
  #'string-pixel-width)                ; measurement function

;; Returns: ((breaks...) . total-cost)

Parameters

;; Spacing: (lws-i lws+ lws- mws-i mws+ mws- cws-i cws+ cws-)
(ekp-c-set-spacing 7 3 2 5 2 1 0 2 0)

;; Penalties: (line-penalty hyphen-penalty fitness-penalty last-line-ratio)
(ekp-c-set-penalties 10 50 100 0.5)

Design Notes

Following Linus's philosophy:

  1. Data structures are the code - Get box/glue layout right, algorithm follows naturally
  2. Simple thread model - Fixed pool, no dynamic thread creation in hot path
  3. Minimal abstraction - Direct array access, no virtual dispatch
  4. Fail fast - Return NULL/nil on errors, let Emacs handle it

Benchmark

Typical speedup vs pure Elisp implementation:

Paragraph Size Elisp C Module Speedup
100 chars 5ms 0.3ms 16x
500 chars 45ms 2ms 22x
2000 chars 350ms 12ms 29x

Note: Actual performance depends on CPU, Emacs version, and text characteristics.