Xterm.js: ๋ฒ„ํผ ์„ฑ๋Šฅ ํ–ฅ์ƒ

์— ๋งŒ๋“  2017๋…„ 07์›” 13์ผ  ยท  73์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: xtermjs/xterm.js

๋ฌธ์ œ

๋ฉ”๋ชจ๋ฆฌ

ํ˜„์žฌ ๋ฒ„ํผ๋Š” ํŠนํžˆ ํฐ ์Šคํฌ๋กค๋ฐฑ์ด ์„ค์ •๋œ ์—ฌ๋Ÿฌ ํ„ฐ๋ฏธ๋„์„ ์‹œ์ž‘ํ•˜๋Š” ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์˜ ๊ฒฝ์šฐ ๋„ˆ๋ฌด ๋งŽ์€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ฐจ์ง€ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด 5000๊ฐœ์˜ ์Šคํฌ๋กค๋ฐฑ์ด ์ฑ„์›Œ์ง„ 160x24 ํ„ฐ๋ฏธ๋„์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐ๋ชจ๋Š” ์•ฝ 34MB์˜ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค(https://github.com/Microsoft/vscode/issues/29840#issuecomment-314539964 ์ฐธ์กฐ). ์ด๋Š” ๋‹จ์ผ ํ„ฐ๋ฏธ๋„์ด๊ณ  1080p ๋ชจ๋‹ˆํ„ฐ๋Š” ๋” ๋„“์€ ํ„ฐ๋ฏธ๋„์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ํŠธ๋ฃจ์ปฌ๋Ÿฌ(https://github.com/sourcelair/xterm.js/issues/484)๋ฅผ ์ง€์›ํ•˜๊ธฐ ์œ„ํ•ด ๊ฐ ์บ๋ฆญํ„ฐ๋Š” 2๊ฐœ์˜ ์ถ”๊ฐ€ number ์œ ํ˜•์„ ์ €์žฅํ•ด์•ผ ํ•˜๋ฉฐ ์ด๋Š” ํ˜„์žฌ ๋ฉ”๋ชจ๋ฆฌ ์†Œ๋น„์˜ ๊ฑฐ์˜ ๋‘ ๋ฐฐ์ž…๋‹ˆ๋‹ค. ๋ฒ„ํผ์˜.

ํ–‰ ํ…์ŠคํŠธ์˜ ๋Š๋ฆฐ ๊ฐ€์ ธ์˜ค๊ธฐ

ํ•œ ์ค„์˜ ์‹ค์ œ ํ…์ŠคํŠธ๋ฅผ ์‹ ์†ํ•˜๊ฒŒ ๊ฐ€์ ธ์™€์•ผ ํ•˜๋Š” ๋˜ ๋‹ค๋ฅธ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ๋Š๋ฆฐ ์ด์œ ๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ๋ฐฐ์น˜๋˜๋Š” ๋ฐฉ์‹ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ํ–‰์—๋Š” ๊ฐ๊ฐ ๋‹จ์ผ ๋ฌธ์ž์—ด์ด ์žˆ๋Š” ๋ฌธ์ž ๋ฐฐ์—ด์ด ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋ฌธ์ž์—ด์„ ๊ตฌ์„ฑํ•œ ๋‹ค์Œ ์ฆ‰์‹œ ๊ฐ€๋น„์ง€ ์ˆ˜์ง‘์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์ด์ „์—๋Š” ํ…์ŠคํŠธ๊ฐ€ ๋ผ์ธ ๋ฒ„ํผ์—์„œ (์ˆœ์„œ๋Œ€๋กœ) ๋‹น๊ฒจ์ง€๊ณ  DOM์— ๋ Œ๋”๋ง๋˜๊ธฐ ๋•Œ๋ฌธ์— ์ด ์ž‘์—…์„ ์ „ํ˜€ ์ˆ˜ํ–‰ํ•  ํ•„์š”๊ฐ€ ์—†์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ xterm.js๋ฅผ ๋”์šฑ ๊ฐœ์„ ํ•จ์— ๋”ฐ๋ผ ์„ ํƒ ๋ฐ ๋งํฌ์™€ ๊ฐ™์€ ๊ธฐ๋Šฅ์ด ๋ชจ๋‘ ์ด ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค์ง€๋งŒ ์ด๊ฒƒ์€ ์ ์  ๋” ์œ ์šฉํ•œ ์ผ์ด ๋˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์‹œ 160x24/5000 ์Šคํฌ๋กค๋ฐฑ ์˜ˆ์ œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด Mid-2014 Macbook Pro์—์„œ ์ „์ฒด ๋ฒ„ํผ๋ฅผ ๋ณต์‚ฌํ•˜๋Š” ๋ฐ 30-60ms๊ฐ€ ๊ฑธ๋ฆฝ๋‹ˆ๋‹ค.

๋ฏธ๋ž˜๋ฅผ ์‘์›ํ•ฉ๋‹ˆ๋‹ค

๋ฏธ๋ž˜์˜ ๋˜ ๋‹ค๋ฅธ ์ž ์žฌ์ ์ธ ๋ฌธ์ œ๋Š” ๋ฒ„ํผ์— ์žˆ๋Š” ๋ฐ์ดํ„ฐ์˜ ์ผ๋ถ€ ๋˜๋Š” ์ „์ฒด๋ฅผ ๋ณต์ œํ•ด์•ผ ํ•  ์ˆ˜ ์žˆ๋Š” ์ผ๋ถ€ ๋ทฐ ๋ชจ๋ธ์„ ๋„์ž…ํ•  ๋•Œ ์ด๋Ÿฌํ•œ ์ข…๋ฅ˜์˜ ๊ฒƒ์ด ๋ฆฌํ”Œ๋กœ์šฐ๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐ ํ•„์š”ํ•˜๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค(https://github.com/sourcelair /xterm.js/issues/622) ์ ์ ˆํ•˜๊ฒŒ(https://github.com/sourcelair/xterm.js/pull/644#issuecomment-298058556) ์Šคํฌ๋ฆฐ ๋ฆฌ๋”๋ฅผ ์ œ๋Œ€๋กœ ์ง€์›ํ•˜๋Š” ๋ฐ ํ•„์š”ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค(https://github.com). /sourcelair/xterm.js/issues/731). ๋ฉ”๋ชจ๋ฆฌ์— ๊ด€ํ•ด์„œ๋Š” ์•ฝ๊ฐ„์˜ ํ”๋“ค๋ฆผ์˜ ์—ฌ์ง€๊ฐ€ ์žˆ๋Š” ๊ฒƒ์ด ํ™•์‹คํžˆ ์ข‹์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด ํ† ๋ก ์€ https://github.com/sourcelair/xterm.js/issues/484 ์—์„œ ์‹œ์ž‘๋˜์—ˆ์œผ๋ฉฐ ๋” ์ž์„ธํžˆ ์„ค๋ช…ํ•˜๊ณ  ๋ช‡ ๊ฐ€์ง€ ์ถ”๊ฐ€ ์†”๋ฃจ์…˜์„ ์ œ์•ˆํ•ฉ๋‹ˆ๋‹ค.

๋‚˜๋Š” ์‹œ๊ฐ„์ด ์žˆ๊ณ  ๋ˆˆ์— ๋„๋Š” ๊ฐœ์„ ์„ ๋ณด์ธ๋‹ค๋ฉด ์†”๋ฃจ์…˜ 3์œผ๋กœ ๊ธฐ์šธ๊ณ  ์†”๋ฃจ์…˜ 5๋กœ ์ด๋™ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋ชจ๋“  ํ”ผ๋“œ๋ฐฑ์„ ์›ํ•ฉ๋‹ˆ๋‹ค! /cc @jerch , @mofux , @rauchg , @parisk

1. ๊ฐ„๋‹จํ•œ ์†”๋ฃจ์…˜

์ด๊ฒƒ์€ ๊ธฐ๋ณธ์ ์œผ๋กœ truecolor fg ๋ฐ b๊ฐ€ ์ถ”๊ฐ€๋œ ํ˜„์žฌ ์šฐ๋ฆฌ๊ฐ€ ํ•˜๋Š” ์ผ์ž…๋‹ˆ๋‹ค.

// [0]: charIndex
// [1]: width
// [2]: attributes
// [3]: truecolor bg
// [4]: truecolor fg
type CharData = [string, number, number, number, number];

type LineData = CharData[];

์žฅ์ 

  • ๋งค์šฐ ๊ฐ„๋‹จ

๋‹จ์ 

  • ๋„ˆ๋ฌด ๋งŽ์€ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ์†Œ๋ชจ๋˜๋ฉด ์ด๋ฏธ ๋„ˆ๋ฌด ๋†’์€ ํ˜„์žฌ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์ด ๊ฑฐ์˜ ๋‘ ๋ฐฐ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

2. CharData์—์„œ ํ…์ŠคํŠธ ๊ฐ€์ ธ์˜ค๊ธฐ

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

interface ILineData {
  // This would provide fast access to the entire line which is becoming more
  // and more important as time goes on (selection and links need to construct
  // this currently). This would need to reconstruct text whenever charData
  // changes though. We cannot lazily evaluate text due to the chars not being
  // stored in CharData
  text: string;
  charData: CharData[];
}

// [0]: charIndex
// [1]: attributes
// [2]: truecolor bg
// [3]: truecolor fg
type CharData = Int32Array;

์žฅ์ 

  • ํ•„์š”ํ•  ๋•Œ๋งˆ๋‹ค ๋ผ์ธ์„ ์žฌ๊ตฌ์„ฑํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.
  • Int32Array ์‚ฌ์šฉ์œผ๋กœ ์ธํ•ด ์˜ค๋Š˜๋ณด๋‹ค ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ๋‚ฎ์Šต๋‹ˆ๋‹ค.

๋‹จ์ 

  • ๊ฐœ๋ณ„ ๋ฌธ์ž๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋Š” ์†๋„๊ฐ€ ๋Š๋ฆฌ๊ธฐ ๋•Œ๋ฌธ์— ๋‹จ์ผ ๋ฌธ์ž ๋ณ€๊ฒฝ์„ ์œ„ํ•ด ์ „์ฒด ๋ฌธ์ž์—ด์„ ๋‹ค์‹œ ์ƒ์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

3. ๋ฒ”์œ„์— ์†์„ฑ ์ €์žฅ

์†์„ฑ์„ ๊ฐ€์ ธ์™€ ๋ฒ”์œ„์™€ ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค. ์†์„ฑ์ด ์ค‘๋ณต๋  ์ˆ˜ ์—†์œผ๋ฏ€๋กœ ์ˆœ์ฐจ์ ์œผ๋กœ ๋ฐฐ์น˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

type LineData = CharData[]

// [0]: The character
// [1]: The width
type CharData = [string, number];

class CharAttributes {
  public readonly _start: [number, number];
  public readonly _end: [number, number];
  private _data: Int32Array;

  // Getters pull data from _data (woo encapsulation!)
  public get flags(): number;
  public get truecolorBg(): number;
  public get truecolorFg(): number;
}

class Buffer extends CircularList<LineData> {
  // Sorted list since items are almost always pushed to end
  private _attributes: CharAttributes[];

  public getAttributesForRows(start: number, end: number): CharAttributes[] {
    // Binary search _attributes and return all visible CharAttributes to be
    // applied by the renderer
  }
}

์žฅ์ 

  • ํŠธ๋ฃจ์ปฌ๋Ÿฌ ๋ฐ์ดํ„ฐ๋„ ์ €์žฅํ•˜์ง€๋งŒ ํ˜„์žฌ๋ณด๋‹ค ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ๋‚ฎ์Šต๋‹ˆ๋‹ค.
  • ๋ชจ๋“  ๋‹จ์ผ ์บ๋ฆญํ„ฐ์˜ ์†์„ฑ์„ ํ™•์ธํ•˜๊ณ  ์ด์ „ ์†์„ฑ๊ณผ ๋น„๊ตํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ์†์„ฑ ์ ์šฉ์„ ์ตœ์ ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋ฐฐ์—ด ๋‚ด๋ถ€์— ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๋Š” ๋ณต์žก์„ฑ์„ ์บก์Šํ™”ํ•ฉ๋‹ˆ๋‹ค( .flags ๋Œ€์‹  [0] ).

๋‹จ์ 

  • ๋‹ค๋ฅธ ๋ฒ”์œ„ ๋‚ด์—์„œ ๋ฌธ์ž ๋ฒ”์œ„์˜ ์†์„ฑ์„ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ์€ ๋” ๋ณต์žกํ•ฉ๋‹ˆ๋‹ค.

4. ์†์„ฑ์„ ์บ์‹œ์— ์ €์žฅ

์—ฌ๊ธฐ์„œ ์•„์ด๋””์–ด๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ํ•œ ํ„ฐ๋ฏธ๋„ ์„ธ์…˜์— ์Šคํƒ€์ผ์ด ๋งŽ์ง€ ์•Š๋‹ค๋Š” ์‚ฌ์‹ค์„ ํ™œ์šฉํ•˜๋Š” ๊ฒƒ์ด๋ฏ€๋กœ ํ•„์š”ํ•œ ๋งŒํผ ์ ๊ฒŒ ๋งŒ๋“ค๊ณ  ์žฌ์‚ฌ์šฉํ•ด์„œ๋Š” ์•ˆ ๋ฉ๋‹ˆ๋‹ค.

// [0]: charIndex
// [1]: width
type CharData = [string, number, CharAttributes];

type LineData = CharData[];

class CharAttributes {
  private _data: Int32Array;

  // Getters pull data from _data (woo encapsulation!)
  public get flags(): number;
  public get truecolorBg(): number;
  public get truecolorFg(): number;
}

interface ICharAttributeCache {
  // Never construct duplicate CharAttributes, figuring how the best way to
  // access both in the best and worst case is the tricky part here
  getAttributes(flags: number, fg: number, bg: number): CharAttributes;
}

์žฅ์ 

  • ํŠธ๋ฃจ์ปฌ๋Ÿฌ ๋ฐ์ดํ„ฐ๋„ ์ €์žฅํ•˜์ง€๋งŒ ์˜ค๋Š˜๋‚ ๊ณผ ์œ ์‚ฌํ•œ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰
  • ๋ฐฐ์—ด ๋‚ด๋ถ€์— ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๋Š” ๋ณต์žก์„ฑ์„ ์บก์Šํ™”ํ•ฉ๋‹ˆ๋‹ค( .flags ๋Œ€์‹  [0] ).

๋‹จ์ 

  • ๋ฒ”์œ„ ์ ‘๊ทผ ๋ฐฉ์‹๋ณด๋‹ค ์ ์€ ๋ฉ”๋ชจ๋ฆฌ ์ ˆ์•ฝ

5. 3๊ณผ 4์˜ ํ•˜์ด๋ธŒ๋ฆฌ๋“œ

type LineData = CharData[]

// [0]: The character
// [1]: The width
type CharData = [string, number];

class CharAttributes {
  private _data: Int32Array;

  // Getters pull data from _data (woo encapsulation!)
  public get flags(): number;
  public get truecolorBg(): number;
  public get truecolorFg(): number;
}

interface CharAttributeEntry {
  attributes: CharAttributes,
  start: [number, number],
  end: [number, number]
}

class Buffer extends CircularList<LineData> {
  // Sorted list since items are almost always pushed to end
  private _attributes: CharAttributeEntry[];
  private _attributeCache: ICharAttributeCache;

  public getAttributesForRows(start: number, end: number): CharAttributeEntry[] {
    // Binary search _attributes and return all visible CharAttributeEntry's to
    // be applied by the renderer
  }
}

interface ICharAttributeCache {
  // Never construct duplicate CharAttributes, figuring how the best way to
  // access both in the best and worst case is the tricky part here
  getAttributes(flags: number, fg: number, bg: number): CharAttributes;
}

์žฅ์ 

  • ์ž ์žฌ์ ์œผ๋กœ ๊ฐ€์žฅ ๋น ๋ฅด๊ณ  ๋ฉ”๋ชจ๋ฆฌ ํšจ์œจ์„ฑ์ด ๊ฐ€์žฅ ๋†’์Œ
  • ๋ฒ„ํผ์— ์Šคํƒ€์ผ์ด ์žˆ๋Š” ๋งŽ์€ ๋ธ”๋ก์ด ํฌํ•จ๋˜์–ด ์žˆ์ง€๋งŒ ๋ช‡ ๊ฐ€์ง€ ์Šคํƒ€์ผ๋งŒ ํฌํ•จ๋œ ๊ฒฝ์šฐ(์ผ๋ฐ˜์ ์ธ ๊ฒฝ์šฐ) ๋ฉ”๋ชจ๋ฆฌ ํšจ์œจ์„ฑ์ด ๋งค์šฐ ๋†’์Šต๋‹ˆ๋‹ค.
  • ๋ฐฐ์—ด ๋‚ด๋ถ€์— ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๋Š” ๋ณต์žก์„ฑ์„ ์บก์Šํ™”ํ•ฉ๋‹ˆ๋‹ค( .flags ๋Œ€์‹  [0] ).

๋‹จ์ 

  • ๋‹ค๋ฅธ ์†”๋ฃจ์…˜๋ณด๋‹ค ๋” ๋ณต์žกํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด๋ฏธ ๋ธ”๋ก๋‹น CharAttributes ํ•˜๋‚˜๋ฅผ ์œ ์ง€ํ•˜๊ณ  ์žˆ๋‹ค๋ฉด ์บ์‹œ๋ฅผ ํฌํ•จํ•  ๊ฐ€์น˜๊ฐ€ ์—†์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
  • CharAttributeEntry ๊ฐœ์ฒด์˜ ์ถ”๊ฐ€ ์˜ค๋ฒ„ํ—ค๋“œ
  • ๋‹ค๋ฅธ ๋ฒ”์œ„ ๋‚ด์—์„œ ๋ฌธ์ž ๋ฒ”์œ„์˜ ์†์„ฑ์„ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ์€ ๋” ๋ณต์žกํ•ฉ๋‹ˆ๋‹ค.

6. 2 & 3์˜ ํ•˜์ด๋ธŒ๋ฆฌ๋“œ

์ด๊ฒƒ์€ 3์˜ ์†”๋ฃจ์…˜์„ ์ทจํ•˜์ง€๋งŒ ๋ผ์ธ ํ…์ŠคํŠธ์— ๋Œ€ํ•œ ๋น ๋ฅธ ์•ก์„ธ์Šค๋ฅผ ์œ„ํ•ด ๋Š๋ฆฌ๊ฒŒ ํ‰๊ฐ€ํ•˜๋Š” ํ…์ŠคํŠธ ๋ฌธ์ž์—ด์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. CharData ์—๋„ ๋ฌธ์ž๋ฅผ ์ €์žฅํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋Š๋ฆฌ๊ฒŒ ํ‰๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

type LineData = {
  text: string,
  CharData[]
}

// [0]: The character
// [1]: The width
type CharData = [string, number];

class CharAttributes {
  public readonly _start: [number, number];
  public readonly _end: [number, number];
  private _data: Int32Array;

  // Getters pull data from _data (woo encapsulation!)
  public get flags(): number;
  public get truecolorBg(): number;
  public get truecolorFg(): number;
}

class Buffer extends CircularList<LineData> {
  // Sorted list since items are almost always pushed to end
  private _attributes: CharAttributes[];

  public getAttributesForRows(start: number, end: number): CharAttributes[] {
    // Binary search _attributes and return all visible CharAttributes to be
    // applied by the renderer
  }

  // If we construct the line, hang onto it
  public getLineText(line: number): string;
}

์žฅ์ 

  • ํŠธ๋ฃจ์ปฌ๋Ÿฌ ๋ฐ์ดํ„ฐ๋„ ์ €์žฅํ•˜์ง€๋งŒ ํ˜„์žฌ๋ณด๋‹ค ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ๋‚ฎ์Šต๋‹ˆ๋‹ค.
  • ๋ชจ๋“  ๋‹จ์ผ ์บ๋ฆญํ„ฐ์˜ ์†์„ฑ์„ ํ™•์ธํ•˜๊ณ  ์ด์ „ ์†์„ฑ๊ณผ ๋น„๊ตํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ์†์„ฑ ์ ์šฉ์„ ์ตœ์ ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋ฐฐ์—ด ๋‚ด๋ถ€์— ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๋Š” ๋ณต์žก์„ฑ์„ ์บก์Šํ™”ํ•ฉ๋‹ˆ๋‹ค( .flags ๋Œ€์‹  [0] ).
  • ์‹ค์ œ ์ค„ ๋ฌธ์ž์—ด์— ๋” ๋น ๋ฅด๊ฒŒ ์•ก์„ธ์Šค

๋‹จ์ 

  • ๋ผ์ธ ์ŠคํŠธ๋ง์— ๋งค๋‹ฌ๋ฆฌ๊ธฐ๋กœ ์ธํ•œ ์ถ”๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ
  • ๋‹ค๋ฅธ ๋ฒ”์œ„ ๋‚ด์—์„œ ๋ฌธ์ž ๋ฒ”์œ„์˜ ์†์„ฑ์„ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ์€ ๋” ๋ณต์žกํ•ฉ๋‹ˆ๋‹ค.

์ž‘๋™ํ•˜์ง€ ์•Š๋Š” ์†”๋ฃจ์…˜

  • ๋ฌธ์ž์—ด์„ Int32Array ๋‚ด๋ถ€์— int๋กœ ์ €์žฅํ•˜๋ฉด int๋ฅผ ๋ฌธ์ž๋กœ ๋‹ค์‹œ ๋ณ€ํ™˜ํ•˜๋Š” ๋ฐ ์‹œ๊ฐ„์ด ์˜ค๋ž˜ ๊ฑธ๋ฆฌ๋ฏ€๋กœ ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
areperformance typplan typproposal

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

ํ˜„์žฌ ์ƒํƒœ:

ํ›„์—:

๋ชจ๋“  73 ๋Œ“๊ธ€

ํ˜ผํ•ฉ๋  ์ˆ˜ ์žˆ๋Š” ๋˜ ๋‹ค๋ฅธ ์ ‘๊ทผ ๋ฐฉ์‹: indexeddb, websql ๋˜๋Š” ํŒŒ์ผ ์‹œ์Šคํ…œ API๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋น„ํ™œ์„ฑ ์Šคํฌ๋กค๋ฐฑ ํ•ญ๋ชฉ์„ ๋””์Šคํฌ๋กœ ํŽ˜์ด์ง€ ์•„์›ƒํ•ฉ๋‹ˆ๋‹ค ๐Ÿค”

ํ›Œ๋ฅญํ•œ ์ œ์•ˆ์ž…๋‹ˆ๋‹ค. 3. ํŠธ๋ฃจ ์ปฌ๋Ÿฌ๋„ ์ง€์›ํ•˜๋ฉด์„œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ ˆ์•ฝํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ํ˜„์žฌ๋กœ์„œ๋Š” ๊ฐ€์žฅ ์ข‹์€ ๋ฐฉ๋ฒ•์ด๋ผ๋Š” ์ ์— ๋™์˜ํ•ฉ๋‹ˆ๋‹ค.

๊ฑฐ๊ธฐ์— ๋„๋‹ฌํ•˜๊ณ  ์ƒํ™ฉ์ด ๊ณ„์†ํ•ด์„œ ์ž˜ ์ง„ํ–‰๋œ๋‹ค๋ฉด 5. ์—์„œ ์ œ์•ˆํ•œ ๋Œ€๋กœ ์ตœ์ ํ™”ํ•˜๊ฑฐ๋‚˜ ๊ทธ ๋‹น์‹œ ๋งˆ์Œ์— ๋– ์˜ค๋ฅด๋Š” ๋‹ค๋ฅธ ๋ฐฉ์‹์œผ๋กœ ์ตœ์ ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

3. ๋ฉ‹์ ธ์š”๐Ÿ‘.

@mofux , ๋””์Šคํฌ ์ €์žฅ์†Œ ์ง€์› ๊ธฐ์ˆ ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์„ ์ค„์ด๋Š” ์‚ฌ์šฉ ์‚ฌ๋ก€๊ฐ€ ๋ถ„๋ช…ํžˆ ์žˆ์ง€๋งŒ, ์ด๋Š” ์‚ฌ์šฉ์ž์—๊ฒŒ ๋””์Šคํฌ ์ €์žฅ์†Œ ์‚ฌ์šฉ ๊ถŒํ•œ์„ ์š”์ฒญํ•˜๋Š” ๋ธŒ๋ผ์šฐ์ € ํ™˜๊ฒฝ์—์„œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์„ ์ €ํ•˜์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฏธ๋ž˜ ์ง€์›์— ๊ด€ํ•˜์—ฌ:
์ƒ๊ฐํ•˜๋ฉด ํ• ์ˆ˜๋ก tty ๋ฐ์ดํ„ฐ๋ฅผ ๊ตฌ๋ฌธ ๋ถ„์„ํ•˜๊ณ , ๋ผ์ธ ๋ฒ„ํผ๋ฅผ ์œ ์ง€ํ•˜๊ณ , ๋งํฌ๋ฅผ ์—ฐ๊ฒฐํ•˜๊ณ , ๊ฒ€์ƒ‰ ํ† ํฐ์„ ์ผ์น˜์‹œํ‚ค๋Š” ๋“ฑ์˜ ํž˜๋“  ์ž‘์—…์„ ๋ชจ๋‘ ์ˆ˜ํ–‰ํ•˜๋Š” WebWorker ์žˆ๋‹ค๋Š” ์ƒ๊ฐ์ด ๋” ๋งŽ์ด ๋“ญ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ UI๋ฅผ ์ฐจ๋‹จํ•˜์ง€ ์•Š๊ณ  ๋ณ„๋„์˜ ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์Šค๋ ˆ๋“œ์—์„œ ๋ฌด๊ฑฐ์šด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด๊ฒƒ์€ ์•„๋งˆ๋„ 4.0 ๋ฆด๋ฆฌ์Šค์— ๋Œ€ํ•œ ๋ณ„๋„์˜ ๋…ผ์˜์˜ ์ผ๋ถ€์—ฌ์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค ๐Ÿ˜‰

์•ž์œผ๋กœ WebWorker์— ๋Œ€ํ•ด +100์ด์ง€๋งŒ ๋ชจ๋“  ๋ธŒ๋ผ์šฐ์ €์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ง€์›ํ•˜๋Š” ๋ธŒ๋ผ์šฐ์ €์˜ ๋ณ€๊ฒฝ ๋ชฉ๋ก ๋ฒ„์ „์ด ํ•„์š”ํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค...

Int32Array ๋ผ๊ณ  ๋งํ•˜๋ฉด ํ™˜๊ฒฝ์—์„œ ์ง€์›ํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ ์ผ๋ฐ˜ ๋ฐฐ์—ด์ด ๋ฉ๋‹ˆ๋‹ค.

@mofux ์•ž์œผ๋กœ WebWorker ์™€ ์ข‹์€ ์ƒ๊ฐ ๐Ÿ‘

@AndrienkoAleksandr ์˜ˆ, WebWorker ๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ๊ธฐ๋Šฅ ๊ฐ์ง€๋ฅผ ํ†ตํ•ด ๋Œ€์•ˆ๋„ ์ง€์›ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์™€์šฐ ๋ฆฌ์ŠคํŠธ ์ข‹๋„ค์š” :)

๋‚˜๋Š” ๋˜ํ•œ ์ผ๋ฐ˜์ ์ธ ํ„ฐ๋ฏธ๋„ ์‚ฌ์šฉ์˜ 90% ์ด์ƒ์— ๋Œ€ํ•ด ๋ฉ”๋ชจ๋ฆฌ ์†Œ๋น„๋ฅผ ํฌ๊ฒŒ ์ค„์ผ ๊ฒƒ์„ ์•ฝ์†ํ•˜๊ธฐ ๋•Œ๋ฌธ์— 3 ์— ๊ธฐ๋Œ€๋Š” ๊ฒฝํ–ฅ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋‹จ๊ณ„์—์„œ Imho ๋ฉ”๋ชจ๋ฆฌ ์ตœ์ ํ™”๊ฐ€ ์ฃผ์š” ๋ชฉํ‘œ๊ฐ€ ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด ์™ธ์—๋„ ํŠน์ • ์‚ฌ์šฉ ์‚ฌ๋ก€์— ๋Œ€ํ•œ ์ถ”๊ฐ€ ์ตœ์ ํ™”๊ฐ€ ์ ์šฉ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(๋‚ด ์ƒ๊ฐ: ncurses์™€ ๊ฐ™์€ "์บ”๋ฒ„์Šค์™€ ๊ฐ™์€ ์•ฑ"์€ ์ˆ˜๋งŽ์€ ๋‹จ์ผ ์…€ ์—…๋ฐ์ดํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์‹œ๊ฐ„์ด ์ง€๋‚จ์— ๋”ฐ๋ผ [start, end] ๋ชฉ๋ก์„ ๋‹ค์†Œ ์ €ํ•˜์‹œํ‚ฌ ๊ฒƒ์ž…๋‹ˆ๋‹ค) .

@AndrienkoAleksandr ๋„ค, ์›น ์ž‘์—…์ž ์•„์ด๋””์–ด๋„ ๋ฉ”์ธ ์Šค๋ ˆ๋“œ์—์„œ _์ผ๋ถ€_ ๋ถ€๋‹ด์„ ๋œ์–ด์ค„ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ข‹์•„ํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ๋ฌธ์ œ๋Š” (์›ํ•˜๋Š” ๋ชจ๋“  ๋Œ€์ƒ ์‹œ์Šคํ…œ์—์„œ ์ง€์›๋˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ๋‹ค๋Š” ์‚ฌ์‹ค ์™ธ์—๋„) _some_์ž…๋‹ˆ๋‹ค. JS ๋ถ€๋ถ„์€ ๋ชจ๋“  ์ตœ์ ํ™”์—์„œ ๋” ์ด์ƒ ๊ทธ๋ ‡๊ฒŒ ํฐ ๋ฌธ์ œ๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค. xterm.js๋Š” ์‹œ๊ฐ„์ด ์ง€๋‚จ์— ๋”ฐ๋ผ ๋ณด์•„์™”์Šต๋‹ˆ๋‹ค. ์‹ค์ œ ๋ฌธ์ œ๋Š” ์„ฑ๋Šฅ ์ธก๋ฉด์—์„œ ๋ธŒ๋ผ์šฐ์ €์˜ ๋ ˆ์ด์•„์›ƒ/๋ Œ๋”๋ง์ž…๋‹ˆ๋‹ค...

@mofux ์ผ๋ถ€ "์™ธ๋ถ€ ๋ฉ”๋ชจ๋ฆฌ"์— ๋Œ€ํ•œ ํŽ˜์ด์ง•์€ ์ข‹์€ ์ƒ๊ฐ์ด์ง€๋งŒ xterm.js๊ฐ€ ์žˆ๋Š” "๋Œ€ํ™”ํ˜• ํ„ฐ๋ฏธ๋„ ์œ„์ ฏ"์ด ์•„๋‹ˆ๋ผ ๋” ๋†’์€ ์ถ”์ƒํ™”์˜ ์ผ๋ถ€์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ imho ์• ๋“œ์˜จ์œผ๋กœ ๋‹ฌ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฃผ์ œ ์™ธ: ๋ฐฐ์—ด ๋Œ€ typedarrays ๋Œ€ asm.js๋กœ ๋ช‡ ๊ฐ€์ง€ ํ…Œ์ŠคํŠธ๋ฅผ ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‚ด๊ฐ€ ๋งํ•  ์ˆ˜์žˆ๋Š” ๊ฒƒ์€ - OMG, ๊ฐ„๋‹จํ•œ ๋ณ€์ˆ˜๋กœ๋“œ ๋ฐ ์„ธํŠธ์˜ ๊ฒฝ์šฐ 1 : 1,5 : 10 ์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค (FF์—์„œ๋Š” ํ›จ์”ฌ ๋”). ์ˆœ์ˆ˜ํ•œ JS ์†๋„๊ฐ€ ์ •๋ง ์•„ํ”„๊ธฐ ์‹œ์ž‘ํ•˜๋ฉด "asm ์‚ฌ์šฉ"์ด ๋„์›€์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๊ทผ๋ณธ์ ์ธ ๋ณ€ํ™”๋ฅผ ์˜๋ฏธํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด๊ฒƒ์„ ์ตœํ›„์˜ ์ˆ˜๋‹จ์œผ๋กœ ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์›น ์–ด์…ˆ๋ธ”๋ฆฌ๋Š” ์•„์ง ๋ฐฐ์†กํ•  ์ค€๋น„๊ฐ€ ๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.

์ฃผ์ œ ์™ธ: ๋ฐฐ์—ด ๋Œ€ typedarrays ๋Œ€ asm.js๋กœ ๋ช‡ ๊ฐ€์ง€ ํ…Œ์ŠคํŠธ๋ฅผ ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‚ด๊ฐ€ ๋งํ•  ์ˆ˜์žˆ๋Š” ๊ฒƒ์€ - OMG, ๊ฐ„๋‹จํ•œ ๊ฐ€๋ณ€๋กœ๋“œ ๋ฐ ์„ธํŠธ์˜ ๊ฒฝ์šฐ 1 : 1,5 : 10๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค (FF์—์„œ๋Š” ํ›จ์”ฌ ๋”)

@jerch ๋Š” ๋ฐฐ์—ด ๋Œ€ typedarrays๊ฐ€ 1:1์—์„œ 1:5

์‰ผํ‘œ๋กœ ์ข‹์€ ์บ์น˜ - ๋‚˜๋Š” 10:15:100 ์†๋„ ํ˜„๋ช…ํ•จ์„ ์˜๋ฏธํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ FF ์œ ํ˜• ๋ฐฐ์—ด์—์„œ๋งŒ ์ผ๋ฐ˜ ๋ฐฐ์—ด๋ณด๋‹ค ์•ฝ๊ฐ„ ๋น ๋ฆ…๋‹ˆ๋‹ค. asm์€ FF, ์›นํ‚ท(Safari), ๊นœ๋ฐ•์ž„/V8(Chrome, Opera)๋กœ ํ…Œ์ŠคํŠธ๋œ ๋ชจ๋“  ๋ธŒ๋ผ์šฐ์ €์—์„œ js ์–ด๋ ˆ์ด๋ณด๋‹ค 10๋ฐฐ ์ด์ƒ ๋น ๋ฆ…๋‹ˆ๋‹ค.

@jerch cool, ๋” ๋‚˜์€ ๋ฉ”๋ชจ๋ฆฌ์™€ ํ•จ๊ป˜ typedarrays์˜ 50% ์†๋„ ํ–ฅ์ƒ์€ ์ง€๊ธˆ์œผ๋กœ์„œ๋Š” ํ™•์‹คํžˆ ํˆฌ์žํ•  ๊ฐ€์น˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฉ”๋ชจ๋ฆฌ ์ ˆ์•ฝ์— ๋Œ€ํ•œ ์•„์ด๋””์–ด - ๋ชจ๋“  ๋ฌธ์ž์— ๋Œ€ํ•ด width ๋ฅผ ์ œ๊ฑฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋” ์ €๋ ดํ•œ wcwidth ๋ฒ„์ „์„ ๊ตฌํ˜„ํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

@jerch ์šฐ๋ฆฌ๋Š” ๊ทธ๊ฒƒ์— ๊ฝค ๋งŽ์ด ์ ‘๊ทผํ•ด์•ผ ํ•˜๊ณ  ๊ทธ๊ฒƒ์„ ์ง€์—ฐ ๋กœ๋“œํ•˜๊ฑฐ๋‚˜ ์–ด๋–ค ๊ฒƒ๋„ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ๋ฆฌํ”Œ๋กœ์šฐ๊ฐ€ ์˜ฌ ๋•Œ ๋ฒ„ํผ์— ์žˆ๋Š” ๋ชจ๋“  ๋ฌธ์ž์˜ ๋„ˆ๋น„๊ฐ€ ํ•„์š”ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์ด ๋น ๋ฅด๋”๋ผ๋„ ์šฐ๋ฆฌ๋Š” ์—ฌ์ „ํžˆ ๊ทธ๊ฒƒ์„ ์œ ์ง€ํ•˜๊ธฐ๋ฅผ ์›ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ง€์ •๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ 1๋กœ ๊ฐ€์ •ํ•˜๊ณ  ์„ ํƒ ์‚ฌํ•ญ์œผ๋กœ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด ๋” ๋‚˜์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

type CharData = [string, number?]; // not sure if this is valid syntax

[
  // 'a'
  ['a'],
  // 'ๆ–‡'
  ['ๆ–‡', 2],
  // after wide
  ['', 0],
  ...
]

@Tyriar ์˜ˆ - ์ด๋ฏธ ์ž‘์„ฑ
์†๋„ ํ–ฅ์ƒ์€ ์กฐํšŒ ํ…Œ์ด๋ธ”์— ๋Œ€ํ•ด 16k ๋ฐ”์ดํŠธ์˜ ๋น„์šฉ์œผ๋กœ ๋‚ด ์ปดํ“จํ„ฐ์—์„œ 10~15๋ฐฐ์ž…๋‹ˆ๋‹ค. ์—ฌ์ „ํžˆ ํ•„์š”ํ•œ ๊ฒฝ์šฐ ๋‘˜์˜ ์กฐํ•ฉ์ด ๊ฐ€๋Šฅํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

์•ž์œผ๋กœ ๋” ๋งŽ์€ ํ”Œ๋ž˜๊ทธ๋ฅผ ์ง€์›ํ•  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค: https://github.com/sourcelair/xterm.js/issues/580

๋˜ ๋‹ค๋ฅธ ์ƒ๊ฐ: ํ„ฐ๋ฏธ๋„์˜ ๋งจ ์•„๋ž˜ ๋ถ€๋ถ„( Terminal.ybase ~ Terminal.ybase + Terminal.rows )๋งŒ ๋™์ ์ž…๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ์˜ ๋Œ€๋ถ€๋ถ„์„ ๊ตฌ์„ฑํ•˜๋Š” ์Šคํฌ๋กค๋ฐฑ์€ ์™„์ „ํžˆ ์ •์ ์ž…๋‹ˆ๋‹ค. ์•„๋งˆ๋„ ์ด๊ฒƒ์„ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ตœ๊ทผ๊นŒ์ง€ ์ด๊ฒƒ์„ ๋ชฐ๋ž์ง€๋งŒ ํ–‰ ์‚ญ์ œ(DL, CSI Ps M)์™€ ๊ฐ™์€ ๊ฒƒ์กฐ์ฐจ๋„ ์Šคํฌ๋กค๋ฐฑ์„ ๋‹ค์‹œ ์•„๋ž˜๋กœ ๊ฐ€์ ธ์˜ค์ง€ ์•Š๊ณ  ์˜คํžˆ๋ ค ๋‹ค๋ฅธ ํ–‰์„ ์‚ฝ์ž…ํ•ฉ๋‹ˆ๋‹ค. ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์œ„๋กœ ์Šคํฌ๋กค(SU, CSI Ps S)ํ•˜๋ฉด Terminal.scrollTop ์˜ ํ•ญ๋ชฉ์ด ์‚ญ์ œ๋˜๊ณ  Terminal.scrollBottom ํ•ญ๋ชฉ์ด ์‚ฝ์ž…๋ฉ๋‹ˆ๋‹ค.

ํ„ฐ๋ฏธ๋„์˜ ํ•˜๋‹จ ๋™์  ๋ถ€๋ถ„์„ ๋…๋ฆฝ์ ์œผ๋กœ ๊ด€๋ฆฌํ•˜๊ณ  ์ค„์ด ๋ฐ€๋ ค ๋‚˜์˜ฌ ๋•Œ ๋’ค๋กœ ์Šคํฌ๋กคํ•˜๋ฉด ์ƒ๋‹นํ•œ ์ด๋“์„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ํ•˜๋‹จ ๋ถ€๋ถ„์€ ์†์„ฑ ์ˆ˜์ •, ๋” ๋น ๋ฅธ ์•ก์„ธ์Šค ๋“ฑ์„ ์„ ํ˜ธํ•˜๊ธฐ ์œ„ํ•ด ๋” ์žฅํ™ฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐ˜๋ฉด ์Šคํฌ๋กค๋ฐฑ์€ ์œ„์—์„œ ์ œ์•ˆํ•œ ์•„์นด์ด๋ธŒ ํ˜•์‹์— ๋” ๊ฐ€๊น์Šต๋‹ˆ๋‹ค.

๋˜ ๋‹ค๋ฅธ ์ƒ๊ฐ: CharAttributeEntry ๋ฅผ ํ–‰์œผ๋กœ ์ œํ•œํ•˜๋Š” ๊ฒƒ์ด ๋Œ€๋ถ€๋ถ„์˜ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์ด ์ž‘๋™ํ•˜๋Š” ๋ฐฉ์‹์ด๋ฏ€๋กœ ๋” ๋‚˜์€ ์•„์ด๋””์–ด์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ํ„ฐ๋ฏธ๋„ ํฌ๊ธฐ๊ฐ€ ์กฐ์ •๋˜๋ฉด ๋™์ผํ•œ ์Šคํƒ€์ผ์„ ๊ณต์œ ํ•˜์ง€ ์•Š๋Š” "๋นˆ" ํŒจ๋”ฉ์ด ์˜ค๋ฅธ์ชฝ์— ์ถ”๊ฐ€๋ฉ๋‹ˆ๋‹ค.

์˜ˆ:

screen shot 2017-08-07 at 8 51 52 pm

๋นจ๊ฐ„์ƒ‰/๋…น์ƒ‰ diff์˜ ์˜ค๋ฅธ์ชฝ์—๋Š” ์Šคํƒ€์ผ์ด ์ง€์ •๋˜์ง€ ์•Š์€ "๋นˆ" ์…€์ด ์žˆ์Šต๋‹ˆ๋‹ค.

@ํ‹ฐ๋ฆฌ์•„๋ฅด
์ด ๋ฌธ์ œ๋ฅผ ์˜์ œ๋กœ ๋˜๋Œ๋ฆด ๊ธฐํšŒ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ? ์ ์–ด๋„ ์ถœ๋ ฅ ์ง‘์•ฝ์ ์ธ ํ”„๋กœ๊ทธ๋žจ์˜ ๊ฒฝ์šฐ ํ„ฐ๋ฏธ๋„ ๋ฐ์ดํ„ฐ๋ฅผ ์œ ์ง€ํ•˜๋Š” ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์€ ๋งŽ์€ ๋ฉ”๋ชจ๋ฆฌ์™€ ์‹œ๊ฐ„์„ ์ ˆ์•ฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 2/3/4์˜ ์ผ๋ถ€ ํ•˜์ด๋ธŒ๋ฆฌ๋“œ๋Š” ์ž…๋ ฅ ๋ฌธ์ž์—ด์˜ ๋‹จ์ผ ๋ฌธ์ž๋ฅผ ๋ถ„ํ• ํ•˜๊ณ  ์ €์žฅํ•˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ์—„์ฒญ๋‚œ ์ฒ˜๋ฆฌ๋Ÿ‰ ํ–ฅ์ƒ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ์†์„ฑ์ด ๋ณ€๊ฒฝ๋œ ํ›„์—๋งŒ ์ €์žฅํ•˜๋ฉด ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ ˆ์•ฝํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค.

์˜ˆ์‹œ:
์ƒˆ๋กœ์šด ํŒŒ์„œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์†์„ฑ์„ ์–ด์ง€๋Ÿฝํžˆ์ง€ ์•Š๊ณ  ์ž…๋ ฅ ๋ฌธ์ž๋ฅผ ์ €์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ํ•ด๋‹น ๋ฌธ์ž์—ด์˜ ์ค‘๊ฐ„์— ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ํ•ด๋‹น ๋ฌธ์ž์—ด์˜ ์†์„ฑ์€ wcwidth(์˜ˆ, ์ค„ ๋ฐ”๊ฟˆ์„ ์ฐพ์œผ๋ ค๋ฉด ์—ฌ์ „ํžˆ ํ•„์š”ํ•จ) ๋ฐ ์ค„ ๋ฐ”๊ฟˆ ๋ฐ ์ค‘์ง€์™€ ํ•จ๊ป˜ ๋‹ค๋ฅธ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ ๋˜๋Š” ์†์„ฑ์— ์ €์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ฐ์ดํ„ฐ๊ฐ€ ์ˆ˜์‹ ๋  ๋•Œ ์…€ ๋ชจ๋ธ์„ ํฌ๊ธฐํ•ฉ๋‹ˆ๋‹ค.
๋ฌธ์ œ๋Š” ํ„ฐ๋ฏธ๋„ ๋ฐ์ดํ„ฐ์˜ ๋“œ๋ฆด๋‹ค์šด ํ‘œํ˜„(์˜ˆ: ๋ Œ๋”๋Ÿฌ ๋˜๋Š” ์ผ๋ถ€ ์ด์Šค์ผ€์ดํ”„ ์‹œํ€€์Šค/์‚ฌ์šฉ์ž๊ฐ€ ์ปค์„œ๋ฅผ ์ด๋™ํ•˜๋ ค๋Š” ๊ฒฝ์šฐ)์ด ์‹œ์ž‘๋˜์–ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ์ผ์ด ๋ฐœ์ƒํ•˜๋ฉด ์—ฌ์ „ํžˆ ์…€ ๊ณ„์‚ฐ์„ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•˜์ง€๋งŒ ํ„ฐ๋ฏธ๋„ cols ๋ฐ rows ๋‚ด์˜ ๋‚ด์šฉ์— ๋Œ€ํ•ด์„œ๋งŒ ์ด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์œผ๋กœ ์ถฉ๋ถ„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. (์Šคํฌ๋กค๋œ ์ฝ˜ํ…์ธ ์— ๋Œ€ํ•ด์„œ๋Š” ์•„์ง ํ™•์‹คํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ๋” ์บ์‹œ์— ์ €์žฅํ•  ์ˆ˜ ์žˆ๊ณ  ๋‹ค์‹œ ๊ทธ๋ฆฌ๋Š” ๋น„์šฉ์ด ์ €๋ ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.)

@jerch 2์ฃผ ํ›„์— ์–ธ์  ๊ฐ€ ํ”„๋ผํ•˜์—์„œ @mofux๋ฅผ ๋งŒ๋‚  ์˜ˆ์ •์ด๋ฉฐ ์ด๋ฅผ ๋‹ค๋ฃจ๋Š” ํ…์ŠคํŠธ ์†์„ฑ์ด ์ฒ˜๋ฆฌ๋˜๋Š” ๋ฐฉ์‹์— ๋Œ€ํ•œ ๋‚ด๋ถ€ ๊ฐœ์„  ์ž‘์—…์„ ์‹œ์ž‘/์‹œ์ž‘ํ•  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค ๐Ÿ˜ƒ

https://github.com/xtermjs/xterm.js/pull/1460#issuecomment -390500944์—์„œ

๋ชจ๋“  ๋ฌธ์ž๊ฐ€ ๋‘ ๋ฒˆ ํ‰๊ฐ€๋˜์–ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ๋‹ค์†Œ ๋น„์Œ‰๋‹ˆ๋‹ค.

@jerch ๋ฒ„ํผ์—์„œ ๋” ๋น ๋ฅธ ํ…์ŠคํŠธ ์•ก์„ธ์Šค์— ๋Œ€ํ•œ ์•„์ด๋””์–ด๊ฐ€ ์žˆ์œผ๋ฉด ์•Œ๋ ค์ฃผ์‹ญ์‹œ์˜ค. ํ˜„์žฌ ๋Œ€๋ถ€๋ถ„์€ ์•Œ๋‹ค์‹œํ”ผ ๋‹จ์ผ ๋ฌธ์ž์ด์ง€๋งŒ ArrayBuffer , ๋ฌธ์ž์—ด ๋“ฑ์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ €๋Š” ์šฐ๋ฆฌ๊ฐ€ ์–ด๋–ป๊ฒŒ๋“  ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๋Š” ์Šคํฌ๋กค๋ฐฑ์˜ ์ด์ ์„ ๋” ํ™œ์šฉํ•˜๋Š” ๊ฒƒ์— ๋Œ€ํ•ด ์ƒ๊ฐํ•ด์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ธ€์Ž„, ๋‚˜๋Š” ๊ณผ๊ฑฐ์— ArrayBuffers๋กœ ๋งŽ์€ ๊ฒƒ์„ ์‹คํ—˜ํ–ˆ์Šต๋‹ˆ๋‹ค.

  • ์ผ๋ฐ˜์ ์ธ ๋ฐฉ๋ฒ•์˜ ๋Ÿฐํƒ€์ž„๊ณผ ๊ด€๋ จํ•˜์—ฌ Array ๋ณด๋‹ค ์•ฝ๊ฐ„ ๋‚˜์ฉ๋‹ˆ๋‹ค(์—”์ง„ ๊ณต๊ธ‰์—…์ฒด์— ์˜ํ•ด ์ตœ์ ํ™”๋˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Œ)
  • new UintXXArray ๋Š” [] ์‚ฌ์šฉํ•œ ๋ฆฌํ„ฐ๋Ÿด ๋ฐฐ์—ด ์ƒ์„ฑ๋ณด๋‹ค ํ›จ์”ฌ ๋‚˜์ฉ๋‹ˆ๋‹ค.
  • ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋ฅผ ๋ฏธ๋ฆฌ ํ• ๋‹นํ•˜๊ณ  ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉด(์ตœ๋Œ€ 10๋ฐฐ) ์—ฌ๋Ÿฌ ๋ฒˆ ๋ณด์ƒํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์—์„œ ํ˜ผํ•ฉ ๋ฐฐ์—ด์˜ ์—ฐ๊ฒฐ ๋ชฉ๋ก ํŠน์„ฑ์ด ๋ฐฐํ›„์—์„œ ๊ณผ๋„ํ•œ ํ• ๋‹น ๋ฐ gc๋กœ ์ธํ•ด ์„ฑ๋Šฅ์„ ์ €ํ•˜์‹œํ‚ต๋‹ˆ๋‹ค.
  • ๋ฌธ์ž์—ด ๋ฐ์ดํ„ฐ์˜ ๊ฒฝ์šฐ ์•ž๋’ค ๋ณ€ํ™˜์€ ๋ชจ๋“  ์ด์ ์„ ๋จน์Šต๋‹ˆ๋‹ค - ์œ ๊ฐ์Šค๋Ÿฝ๊ฒŒ๋„ JS๋Š” Uint16Array ๋ณ€ํ™˜๊ธฐ์— ๊ธฐ๋ณธ ๋ฌธ์ž์—ด์„ ์ œ๊ณตํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค( TextEncoder ๋ถ€๋ถ„์ ์œผ๋กœ ๊ฐ€๋Šฅ).

ArrayBuffer ์— ๋Œ€ํ•œ ๋‚ด ๋ฐœ๊ฒฌ์€ ๋ณ€ํ™˜ ํŒจ๋„ํ‹ฐ๋กœ ์ธํ•ด ๋ฌธ์ž์—ด ๋ฐ์ดํ„ฐ์— ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ์ด๋ก ์ ์œผ๋กœ ํ„ฐ๋ฏธ๋„์€ node-pty์—์„œ ํ„ฐ๋ฏธ๋„ ๋ฐ์ดํ„ฐ๊นŒ์ง€ ArrayBuffer ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(์ด๋Š” ํ”„๋ก ํŠธ์—”๋“œ๋กœ ๊ฐ€๋Š” ๋„์ค‘์— ์—ฌ๋Ÿฌ ๋ณ€ํ™˜์„ ์ €์žฅํ•  ์ˆ˜ ์žˆ์Œ). ๋ Œ๋”๋ง์ด ๊ทธ๋Ÿฐ ์‹์œผ๋กœ ์ˆ˜ํ–‰๋  ์ˆ˜ ์žˆ๋Š”์ง€ ํ™•์‹คํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ํ•ญ์ƒ ์ตœ์ข… uint16_t ์—์„œ string ๋กœ์˜ ๋ณ€ํ™˜์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋งˆ์ง€๋ง‰ ๋ฌธ์ž์—ด ์ƒ์„ฑ์€ ์ €์žฅ๋œ ๋Ÿฐํƒ€์ž„์˜ ๋Œ€๋ถ€๋ถ„์„ ๋จน์–ด์น˜์šฐ๊ณ  ํ„ฐ๋ฏธ๋„์„ ๋‚ด๋ถ€์ ์œผ๋กœ ์ถ”์•…ํ•œ C-ish ์ง์Šน์œผ๋กœ ๋งŒ๋“ค ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋‚˜๋Š” ์ด ์ ‘๊ทผ ๋ฐฉ์‹์„ ํฌ๊ธฐํ–ˆ์Šต๋‹ˆ๋‹ค.

TL;DR ArrayBuffer ๋Š” ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋ฅผ ๋ฏธ๋ฆฌ ํ• ๋‹นํ•˜๊ณ  ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ๋” ์ข‹์Šต๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ๋ชจ๋“  ๊ฒฝ์šฐ์—๋Š” ์ผ๋ฐ˜ ๋ฐฐ์—ด์ด ๋” ์ข‹์Šต๋‹ˆ๋‹ค. ๋ฌธ์ž์—ด์€ ArrayBuffers์— ์••์ถ•ํ•  ๊ฐ€์น˜๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

๋‚ด๊ฐ€ ์ƒ๊ฐํ•ด ๋‚ธ ์ƒˆ๋กœ์šด ์•„์ด๋””์–ด๋Š” ๊ฐ€๋Šฅํ•œ ํ•œ ๋ฌธ์ž์—ด ์ƒ์„ฑ์„ ์ค„์ด๋ ค๋Š” ์‹œ๋„์ž…๋‹ˆ๋‹ค. ๋ถˆ์พŒํ•œ ๋ถ„ํ•  ๋ฐ ์กฐ์ธ์„ ํ”ผํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ์ƒˆ๋กœ์šด InputHandler.print ๋ฉ”์†Œ๋“œ, wcwidth ๋ฐ line stop์„ ์—ผ๋‘์— ๋‘๊ณ  ์œ„์˜ ๋‘ ๋ฒˆ์งธ ์•„์ด๋””์–ด๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•ฉ๋‹ˆ๋‹ค.

  • print ์ด์ œ ์—ฌ๋Ÿฌ ํ„ฐ๋ฏธ๋„ ๋ผ์ธ๊นŒ์ง€ ์ „์ฒด ๋ฌธ์ž์—ด์„ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.
  • ํ˜„์žฌ ์†์„ฑ๊ณผ ํ•จ๊ป˜ ํ•ด๋‹น ๋ฌธ์ž์—ด์„ ๋ณ€๊ฒฝ ์—†์ด ๊ฐ„๋‹จํ•œ ํฌ์ธํ„ฐ ๋ชฉ๋ก์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค(๋ฌธ์ž์—ด alloc ๋˜๋Š” gc ์—†์Œ, ์‚ฌ์ „ ํ• ๋‹น๋œ ๊ตฌ์กฐ์™€ ํ•จ๊ป˜ ์‚ฌ์šฉ๋˜๋Š” ๊ฒฝ์šฐ ๋ชฉ๋ก ํ• ๋‹น์„ ํ”ผํ•  ์ˆ˜ ์žˆ์Œ).
  • wcwidth(string) % cols ๋งŒํผ ์ปค์„œ ์ด๋™
  • ํŠน๋ณ„ํ•œ ๊ฒฝ์šฐ \n (ํ•˜๋“œ ์ค„ ๋ฐ”๊ฟˆ): ์ปค์„œ๋ฅผ ํ•œ ์ค„ ์•ž์œผ๋กœ ์ด๋™, ํฌ์ธํ„ฐ ๋ชฉ๋ก์˜ ์œ„์น˜๋ฅผ โ€‹โ€‹ํ•˜๋“œ ์ค„ ๋ฐ”๊ฟˆ์œผ๋กœ ํ‘œ์‹œ
  • wrapAround๋ฅผ ์‚ฌ์šฉํ•œ ํŠน๋ณ„ํ•œ ๊ฒฝ์šฐ ์ค„ ์˜ค๋ฒ„ํ”Œ๋กœ: ๋ฌธ์ž์—ด์˜ ์œ„์น˜๋ฅผ โ€‹โ€‹์†Œํ”„ํŠธ ์ค„ ๋ฐ”๊ฟˆ์œผ๋กœ ํ‘œ์‹œ
  • ํŠน๋ณ„ํ•œ ๊ฒฝ์šฐ \r : ๋งˆ์ง€๋ง‰ ์ค„ ๋‚ด์šฉ(ํ˜„์žฌ ์ปค์„œ ์œ„์น˜์—์„œ ๋งˆ์ง€๋ง‰ ์ค„ ๋ฐ”๊ฟˆ๊นŒ์ง€)์„ ์ผ๋ถ€ ์ค„ ๋ฒ„ํผ์— ๋กœ๋“œํ•˜์—ฌ ๋ฎ์–ด์”๋‹ˆ๋‹ค.
  • \r ์ผ€์ด์Šค์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  ์œ„์™€ ๊ฐ™์ด ๋ฐ์ดํ„ฐ๊ฐ€ ํ๋ฆ…๋‹ˆ๋‹ค. ์…€ ์ถ”์ƒํ™”๋‚˜ ๋ฌธ์ž์—ด ๋ถ„ํ• ์ด ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • ์•„๋ฌด๋„ ์‹ค์ œ cols x rows ํ‘œํ˜„์„ ์š”์ฒญํ•˜์ง€ ์•Š๋Š” ํ•œ ์†์„ฑ ๋ณ€๊ฒฝ์€ ๋ฌธ์ œ๊ฐ€ ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค(์ „์ฒด ๋ฌธ์ž์—ด๊ณผ ํ•จ๊ป˜ ์ €์žฅ๋˜๋Š” attr ํ”Œ๋ž˜๊ทธ๋งŒ ๋ณ€๊ฒฝํ•จ).

Btw wcwidths๋Š” ์ž์†Œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ํ•˜์œ„ ์ง‘ํ•ฉ์ด๋ฏ€๋กœ ๋ฏธ๋ž˜์— ์„œ๋กœ ๋ฐ”๊ฟ” ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด์ œ ์œ„ํ—˜ํ•œ ๋ถ€๋ถ„ 1 - ๋ˆ„๊ตฐ๊ฐ€ cols x rows ๋‚ด์—์„œ ์ปค์„œ๋ฅผ ์ด๋™ํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

  • cols ์ค„๋ฐ”๊ฟˆ์—์„œ ๋’ค๋กœ ์ด๋™ - ํ˜„์žฌ ํ„ฐ๋ฏธ๋„ ๋‚ด์šฉ์˜ ์‹œ์ž‘
  • ๋ชจ๋“  ์ค„ ๋ฐ”๊ฟˆ์€ ์‹ค์ œ ํ„ฐ๋ฏธ๋„ ์ค„์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
  • ํ•œ ํŽ˜์ด์ง€์˜ ์…€ ๋ชจ๋ธ์— ๋กœ๋“œ
  • ๊นŒ๋‹ค๋กœ์šด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜์‹ญ์‹œ์˜ค. ์†์„ฑ ๋ณ€๊ฒฝ์ด ์š”์ฒญ๋˜๋ฉด ์šด์ด ์ข‹์ง€ ์•Š์•„ ์ „์ฒด ์…€ ๋ชจ๋ธ ๋˜๋Š” ๋ฌธ์ž์—ด ๋ถ„ํ•  ๋ฐ ์‚ฝ์ž… ๋ชจ๋ธ๋กœ ํด๋ฐฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค(ํ›„์ž๋Š” ์„ฑ๋Šฅ์ด ์ €ํ•˜๋  ์ˆ˜ ์žˆ์Œ).
  • ๋ฐ์ดํ„ฐ๊ฐ€ ๋‹ค์‹œ ํ๋ฆ…๋‹ˆ๋‹ค. ์ด์ œ ํ•ด๋‹น ํŽ˜์ด์ง€์˜ ๋ฒ„ํผ์— ์ €ํ•˜๋œ ๋ฌธ์ž์—ด ๋ฐ ์†์„ฑ ๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด์ œ ์œ„ํ—˜ํ•œ ๋ถ€๋ถ„ 2 - ๋ Œ๋”๋Ÿฌ๊ฐ€ ๋ฌด์–ธ๊ฐ€๋ฅผ ๊ทธ๋ฆฌ๊ธฐ๋ฅผ ์›ํ•ฉ๋‹ˆ๋‹ค.

  • ์…€ ๋ชจ๋ธ๋กœ ๋“œ๋ฆด๋‹ค์šดํ•ด์•ผ ํ•˜๊ฑฐ๋‚˜ ์ค„ ๋ฐ”๊ฟˆ ๋ฐ ํ…์ŠคํŠธ ์†์„ฑ์ด ์žˆ๋Š” ๋ฌธ์ž์—ด ์˜คํ”„์…‹์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์—ฌ๋ถ€๋Š” ๋ Œ๋”๋Ÿฌ์— ๋”ฐ๋ผ ๋‹ค๋ฆ…๋‹ˆ๋‹ค.

์žฅ์ :

  • ๋งค์šฐ ๋น ๋ฅธ ๋ฐ์ดํ„ฐ ํ๋ฆ„
  • ๊ฐ€์žฅ ์ผ๋ฐ˜์ ์ธ InputHandler ๋ฐฉ๋ฒ•์— ์ตœ์ ํ™”๋จ - print
  • ํ„ฐ๋ฏธ๋„ ํฌ๊ธฐ ์กฐ์ • ์‹œ ๋ฆฌํ”Œ๋กœ์šฐ ๋ผ์ธ์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.

๋‹จ์ :

  • ๊ฑฐ์˜ ๋ชจ๋“  ๋‹ค๋ฅธ InputHandler ๋ฐฉ๋ฒ•์€ ์ด ํ๋ฆ„ ๋ชจ๋ธ์„ ์ค‘๋‹จํ•˜๊ณ  ์ค‘๊ฐ„ ์…€ ์ถ”์ƒํ™”๊ฐ€ ํ•„์š”ํ•˜๋‹ค๋Š” ์˜๋ฏธ์—์„œ ์œ„ํ—˜ํ•ฉ๋‹ˆ๋‹ค.
  • ๋ Œ๋”๋Ÿฌ ํ†ตํ•ฉ์ด ๋ถˆ๋ถ„๋ช…ํ•ฉ๋‹ˆ๋‹ค (์ ์–ด๋„ atm์—๊ฒŒ)
  • ์•ฑ๊ณผ ๊ฐ™์€ ์ €์ฃผ์˜ ์„ฑ๋Šฅ์ด ์ €ํ•˜๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(์ผ๋ฐ˜์ ์œผ๋กœ ๋” "์œ„ํ—˜ํ•œ" ์‹œํ€€์Šค๊ฐ€ โ€‹โ€‹ํฌํ•จ๋จ).

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

@jerch

๋ฌธ์ž์—ด์€ ArrayBuffers์— ์••์ถ•ํ•  ๊ฐ€์น˜๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

Monaco๋Š” ArrayBuffer s์— ๋ฒ„ํผ๋ฅผ ์ €์žฅํ•˜๊ณ  ๊ฝค ๊ณ ์„ฑ๋Šฅ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์•„์ง ๊ตฌํ˜„์— ๋Œ€ํ•ด ์ž์„ธํžˆ ์‚ดํŽด๋ณด์ง€๋Š” ์•Š์•˜์Šต๋‹ˆ๋‹ค.

ํŠนํžˆ ๋ถˆ์พŒํ•œ ๋ถ„ํ•  ๋ฐ ์กฐ์ธ์„ ํ”ผํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

์–ด๋Š ๊ฒƒ?

์ €๋Š” ์Šคํฌ๋กค๋ฐฑ์ด ์–ด๋–ป๊ฒŒ๋“  ๋ถˆ๋ณ€์ด๋ผ๋Š” ์ด์ ์„ ๋” ๋งŽ์ด ํ™œ์šฉํ•˜๋Š” ๊ฒƒ์— ๋Œ€ํ•ด ์ƒ๊ฐํ•ด์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค.

ํ•œ ๊ฐ€์ง€ ์•„์ด๋””์–ด๋Š” ๋ทฐํฌํŠธ ์„น์…˜์—์„œ ์Šคํฌ๋กค๋ฐฑ์„ ๋ถ„๋ฆฌํ•˜๋Š” ๊ฒƒ์ด์—ˆ์Šต๋‹ˆ๋‹ค. ์ค„์ด ์Šคํฌ๋กค๋ฐฑ์œผ๋กœ ์ด๋™ํ•˜๋ฉด ์Šคํฌ๋กค๋ฐฑ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋กœ ํ‘ธ์‹œ๋ฉ๋‹ˆ๋‹ค. 2๊ฐœ์˜ CircularList ๊ฐœ์ฒด๋ฅผ ์ƒ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜๋‚˜๋Š” ๋ผ์ธ์ด ์ ˆ๋Œ€ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๋„๋ก ์ตœ์ ํ™”๋˜๊ณ  ๋‹ค๋ฅธ ํ•˜๋‚˜๋Š” ๊ทธ ๋ฐ˜๋Œ€์ž…๋‹ˆ๋‹ค.

@Tyriar ์Šคํฌ๋กค

@ํ‹ฐ๋ฆฌ์•„๋ฅด
๋ณ€ํ™˜์„ ํ•˜๋‚˜๋กœ ์ œํ•œํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ArrayBuffer์— ๋ฌธ์ž์—ด์„ ์ €์žฅํ•˜๋Š” ๊ฒƒ์ด ํ•ฉ๋ฆฌ์ ์ž…๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์€ ๋ชจ๋“  ๊ณณ์—์„œ ๋ฌธ์ž์—ด์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ์•ฝ๊ฐ„ ๋‚ซ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ node-pty๊ฐ€ ์›์‹œ ๋ฐ์ดํ„ฐ๋„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค(๋˜ํ•œ websocket๋„ ์›์‹œ ๋ฐ์ดํ„ฐ๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Œ).

ํŠนํžˆ ๋ถˆ์พŒํ•œ ๋ถ„ํ•  ๋ฐ ์กฐ์ธ์„ ํ”ผํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

์–ด๋Š ๊ฒƒ?

์ „์ฒด ์ ‘๊ทผ ๋ฐฉ์‹์€ _minimize_ ๋ถ„ํ•  ์„ ์ „ํ˜€ ํ”ผํ•˜๋Š” ๊ฒƒ ์ž…๋‹ˆ๋‹ค. ์•„๋ฌด๋„ ๋ฒ„ํผ๋ง๋œ ๋ฐ์ดํ„ฐ๋กœ ์ปค์„œ ์ ํ”„๋ฅผ ์š”์ฒญํ•˜์ง€ ์•Š์œผ๋ฉด ๋ฌธ์ž์—ด์ด ๋ถ„ํ• ๋˜์ง€ ์•Š๊ณ  ๋ Œ๋”๋Ÿฌ๋กœ ๋ฐ”๋กœ ์ด๋™ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(์ง€์›๋˜๋Š” ๊ฒฝ์šฐ). ์…€ ๋ถ„ํ•  ๋ฐ ๋‚˜์ค‘์— ์กฐ์ธ์ด ์ „ํ˜€ ์—†์Šต๋‹ˆ๋‹ค.

@jerch ๊ธ€์Ž„, ๋ทฐํฌํŠธ๊ฐ€ ํ™•์žฅ๋˜๋ฉด ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ค„์„ ์‚ญ์ œํ•  ๋•Œ ์Šคํฌ๋กค๋ฐฑ์„ ๊ฐ€์ ธ์˜ฌ ์ˆ˜๋„ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์ด ์˜ฌ๋ฐ”๋ฅธ ํ–‰๋™์ธ์ง€ 100% ํ™•์‹ ํ•  ์ˆ˜๋Š” ์—†์Šต๋‹ˆ๋‹ค.

@Tyriar ์•„ ๋งž๋‹ค. ํ›„์ž๋„ ํ™•์‹คํ•˜์ง€ ์•Š์ง€๋งŒ ๊ธฐ๋ณธ xterm์€ ์‹ค์ œ ๋งˆ์šฐ์Šค ๋˜๋Š” ์Šคํฌ๋กค ๋ง‰๋Œ€ ์Šคํฌ๋กค์—๋งŒ ์ด๋ฅผ ํ—ˆ์šฉํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. SD/SU์กฐ์ฐจ๋„ ์Šคํฌ๋กค ๋ฒ„ํผ ์ฝ˜ํ…์ธ ๋ฅผ "ํ™œ์„ฑ" ํ„ฐ๋ฏธ๋„ ๋ทฐํฌํŠธ๋กœ ๋‹ค์‹œ ์ด๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

ArrayBuffer๊ฐ€ ์‚ฌ์šฉ๋˜๋Š” monaco ํŽธ์ง‘๊ธฐ์˜ ์†Œ์Šค๋ฅผ ์•Œ๋ ค ์ฃผ์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ? ๋‚ด๊ฐ€ ์ง์ ‘ ์ฐพ์„ ์ˆ˜ ์—†๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค : ํ™๋‹น๋ฌด:

ํ  ๊ทธ๋ƒฅ TextEncoder/Decoder ์‚ฌ์–‘์„ ๋‹ค์‹œ ์ฝ๊ณ  node-pty์—์„œ ํ”„๋ก ํŠธ์—”๋“œ๊นŒ์ง€ ArrayBuffers๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์–ด๋Š ์‹œ์ ์—์„œ ์–ด๋ ค์šด ๋ฐฉ์‹์œผ๋กœ ๋ฒˆ์—ญํ•˜์ง€ ์•Š๋Š” ํ•œ ๊ธฐ๋ณธ์ ์œผ๋กœ utf-8์— ๊ณ ์ •๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. xterm.js utf-8์„ ์ธ์‹ํ•˜๊ฒŒ ๋งŒ๋“œ์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ? Idk, ์ด๊ฒƒ์€ ๋” ๋†’์€ ์œ ๋‹ˆ์ฝ”๋“œ ๋ฌธ์ž์— ๋Œ€ํ•œ ๋งŽ์€ ์ค‘๊ฐ„ ์ฝ”๋“œ ํฌ์ธํŠธ ๊ณ„์‚ฐ์„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. Proside - ASCII ๋ฌธ์ž์— ๋Œ€ํ•œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ ˆ์•ฝํ•ฉ๋‹ˆ๋‹ค.

@rebornix monaco๊ฐ€ ๋ฒ„ํผ๋ฅผ ์ €์žฅํ•˜๋Š” ์œ„์น˜์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ๋ฅผ ์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

๋‹ค์Œ์€ ์œ ํ˜•์ด ์ง€์ •๋œ ๋ฐฐ์—ด๊ณผ ์ƒˆ ํŒŒ์„œ์— ๋Œ€ํ•œ ๋ช‡ ๊ฐ€์ง€ ์ˆซ์ž์ž…๋‹ˆ๋‹ค(์ฑ„ํƒํ•˜๊ธฐ ๋” ์‰ฌ์›€).

  • UTF-8(Uint8Array): print ์ž‘์—…์ด 190MB/s์—์„œ 290MB/s๋กœ ์ ํ”„ํ•ฉ๋‹ˆ๋‹ค.
  • UTF-16(Uint16Array): print ์ž‘์—…์ด 190MB/s์—์„œ 320MB/s๋กœ ์ ํ”„ํ•ฉ๋‹ˆ๋‹ค.

์ „๋ฐ˜์ ์œผ๋กœ UTF-16์ด ํ›จ์”ฌ ๋” ๋‚˜์€ ์„ฑ๋Šฅ์„ ๋ณด์ด์ง€๋งŒ ํŒŒ์„œ๊ฐ€ ์ด์— ์ตœ์ ํ™”๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์˜ˆ์ƒํ–ˆ๋˜ ๊ฒƒ์ž…๋‹ˆ๋‹ค. UTF-8์€ ์ค‘๊ฐ„ ์ฝ”๋“œ ํฌ์ธํŠธ ๊ณ„์‚ฐ์— ์–ด๋ ค์›€์„ ๊ฒช์Šต๋‹ˆ๋‹ค.

๋ฌธ์ž์—ด์—์„œ ํ˜•์‹ํ™”๋œ ๋ฐฐ์—ด๋กœ์˜ ๋ณ€ํ™˜์€ ๋‚ด ๋ฒค์น˜๋งˆํฌ ls -lR /usr/lib ์˜ JS ๋Ÿฐํƒ€์ž„์„ ~4% ์†Œ๋ชจํ•ฉ๋‹ˆ๋‹ค( InputHandler.parse ๋ฃจํ”„๋ฅผ ํ†ตํ•ด ์ˆ˜ํ–‰๋˜๋Š” ํ•ญ์ƒ 100ms ๋ฏธ๋งŒ). ๋‚˜๋Š” ์—ญ๋ณ€ํ™˜์„ ํ…Œ์ŠคํŠธํ•˜์ง€ ์•Š์•˜๋‹ค(์ด๊ฒƒ์€ ์•”๋ฌต์ ์œผ๋กœ atm in InputHandller.print ์—์„œ ์…€ ์ˆ˜์ค€์œผ๋กœ ์ˆ˜ํ–‰๋จ). ์ „์ฒด ๋Ÿฐํƒ€์ž„์€ ๋ฌธ์ž์—ด๋ณด๋‹ค ์•ฝ๊ฐ„ ๋‚˜์ฉ๋‹ˆ๋‹ค(ํŒŒ์„œ์— ์ €์žฅ๋œ ์‹œ๊ฐ„์€ ๋ณ€ํ™˜ ์‹œ๊ฐ„์„ ๋ณด์ƒํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค). ๋‹ค๋ฅธ ๋ถ€๋ถ„๋„ ๋ฐฐ์—ด์„ ์ธ์‹ํ•˜๋Š” ํ˜•์‹์ธ ๊ฒฝ์šฐ ๋ณ€๊ฒฝ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ํ•ด๋‹น ์Šคํฌ๋ฆฐ์ƒท( ls -lR /usr/lib ํ…Œ์ŠคํŠธ):

๋ฌธ์ž์—ด๋กœ:
grafik

Uint16Array ์‚ฌ์šฉ:
grafik

EscapeSequenceParser.parse ์ฐจ์ด์ ์— ์œ ์˜ํ•˜์‹ญ์‹œ์˜ค. ์ด๋Š” ํ˜•์‹ํ™”๋œ ๋ฐฐ์—ด์—์„œ ์ด์ต์„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(~30% ๋” ๋น ๋ฆ„). InputHandler.parse ๋Š” ๋ณ€ํ™˜์„ ์ˆ˜ํ–‰ํ•˜๋ฏ€๋กœ ํ˜•์‹ํ™”๋œ ๋ฐฐ์—ด ๋ฒ„์ „์—์„œ๋Š” ๋” ๋‚˜์ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ GC Minor๋Š” ํ˜•์‹ํ™”๋œ ๋ฐฐ์—ด์— ๋Œ€ํ•ด ๋” ๋งŽ์€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค(๋ฐฐ์—ด์„ ๋ฒ„๋ฆฌ๊ธฐ ๋•Œ๋ฌธ์—).

ํŽธ์ง‘: ์Šคํฌ๋ฆฐ์ƒท์—์„œ ๋˜ ๋‹ค๋ฅธ ์ธก๋ฉด์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. GC๋Š” ~20% ๋Ÿฐํƒ€์ž„๊ณผ ๊ด€๋ จ๋˜๊ณ  ์žฅ๊ธฐ ์‹คํ–‰ ํ”„๋ ˆ์ž„(๋นจ๊ฐ„์ƒ‰ ํ”Œ๋ž˜๊ทธ)์€ ๋ชจ๋‘ GC์™€ ๊ด€๋ จ๋ฉ๋‹ˆ๋‹ค.

๋˜ ๋‹ค๋ฅธ ๋‹ค์†Œ ๊ธ‰์ง„์ ์ธ ์•„์ด๋””์–ด:

  1. ์ž์ฒด arraybuffer ๊ธฐ๋ฐ˜ ๊ฐ€์ƒ ๋ฉ”๋ชจ๋ฆฌ ์ƒ์„ฑ, ํฐ ๊ฒƒ(>5MB)
    ์–ด๋ ˆ์ด ๋ฒ„ํผ์˜ ๊ธธ์ด๊ฐ€ int8 ์—์„œ int16 ์—์„œ int32 ๋กœ 4๊ฐœ์˜ ํˆฌ๋ช… ์Šค์œ„์น˜์˜ ๋ฐฐ์ˆ˜์ธ ๊ฒฝ์šฐ ์œ ํ˜•์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ํ• ๋‹น์ž๋Š” Uint8Array ์—์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ธ๋ฑ์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์ด ํฌ์ธํ„ฐ๋Š” ๊ฐ„๋‹จํ•œ ๋น„ํŠธ ์ด๋™์— ์˜ํ•ด Uint16Array ๋˜๋Š” Uint32Array ์œ„์น˜๋กœ ๋ณ€ํ™˜๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  2. ๋“ค์–ด์˜ค๋Š” ๋ฌธ์ž์—ด์„ UTF-16์˜ ๊ฒฝ์šฐ uint16_t ์œ ํ˜•์œผ๋กœ ๋ฉ”๋ชจ๋ฆฌ์— ์”๋‹ˆ๋‹ค.
  3. ํŒŒ์„œ๋Š” ๋ฌธ์ž์—ด ํฌ์ธํ„ฐ์—์„œ ์‹คํ–‰๋˜๊ณ  ๋ฌธ์ž์—ด ์กฐ๊ฐ ๋Œ€์‹  ์ด ๋ฉ”๋ชจ๋ฆฌ์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ InputHandler ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.
  4. ๊ฐ€์ƒ ๋ฉ”๋ชจ๋ฆฌ ๋‚ด๋ถ€์— ํ„ฐ๋ฏธ๋„ ๋ฐ์ดํ„ฐ ๋ฒ„ํผ๋ฅผ ๋„ค์ดํ‹ฐ๋ธŒ JS ๊ฐ์ฒด ๋Œ€์‹  ๊ตฌ์กฐ์ฒด์™€ ๊ฐ™์€ ์œ ํ˜•์˜ ๋ง ๋ฒ„ํผ ๋ฐฐ์—ด๋กœ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์•„๋งˆ๋„ ๋‹ค์Œ๊ณผ ๊ฐ™์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค(์—ฌ์ „ํžˆ ์…€ ๊ธฐ๋ฐ˜).
struct Cell {
    uint32_t *char_start;  // start pointer of cell content (JS with pointers hurray!)
    uint8_t length;        // length of content (8 bit here is sufficient)
    uint32_t attr;         // text attributes (might grow to hold true color someday)
    uint8_t width;         // wcwidth (maybe merge with other member, always < 4)
    .....                  // some other cell based stuff
}

์žฅ์ :

  • ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ JS ๊ฐœ์ฒด์™€ GC๋ฅผ ์ƒ๋žตํ•ฉ๋‹ˆ๋‹ค(๋ช‡ ๊ฐœ์˜ ๋กœ์ปฌ ๊ฐœ์ฒด๋งŒ ๋‚จ์Œ).
  • ํ•„์š”ํ•œ ๊ฐ€์ƒ ๋ฉ”๋ชจ๋ฆฌ์— ๋Œ€ํ•œ ๋‹จ ํ•˜๋‚˜์˜ ์ดˆ๊ธฐ ๋ฐ์ดํ„ฐ ๋ณต์‚ฌ
  • malloc ๋ฐ free ๋น„์šฉ์ด ๊ฑฐ์˜ ์—†์Œ(ํ• ๋‹น์ž/ํ• ๋‹น์ž์˜ ์˜๋ฆฌํ•จ์— ๋”ฐ๋ผ ๋‹ค๋ฆ„)
  • ๋งŽ์€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ ˆ์•ฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(JS ๊ฐœ์ฒด ๋ฉ”๋ชจ๋ฆฌ ์˜ค๋ฒ„ํ—ค๋“œ ๋ฐฉ์ง€).

๋‹จ์ :

  • Cavascript Horror Show์— ์˜ค์‹  ๊ฒƒ์„ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค :scream:
  • ๊ตฌํ˜„ํ•˜๊ธฐ ์–ด๋ ต๊ณ  ๋ชจ๋“  ๊ฒƒ์ด ๋ณ€๊ฒฝ๋จ
  • ์†๋„ ์ด์ ์€ ์‹ค์ œ๋กœ ๊ตฌํ˜„๋  ๋•Œ๊นŒ์ง€ ๋ถˆ๋ถ„๋ช…ํ•ฉ๋‹ˆ๋‹ค.

:์›ƒ๋‹ค:

๊ตฌํ˜„ํ•˜๊ธฐ ์–ด๋ ค์šด ์žฌ๋ฏธ, ๋ชจ๋“  ๊ฒƒ์ด ๋ณ€๊ฒฝ๋ฉ๋‹ˆ๋‹ค ๐Ÿ˜‰

์ด๊ฒƒ์€ Monaco๊ฐ€ ์ž‘๋™ํ•˜๋Š” ๋ฐฉ์‹์— ๋” ๊ฐ€๊น์Šต๋‹ˆ๋‹ค. ์บ๋ฆญํ„ฐ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•œ ์ „๋žต์„ ๋…ผ์˜ํ•˜๋Š” ์ด ๋ธ”๋กœ๊ทธ ๊ฒŒ์‹œ๋ฌผ์„ ๊ธฐ์–ตํ–ˆ์Šต๋‹ˆ๋‹ค. https://code.visualstudio.com/blogs/2017/02/08/syntax-highlighting-optimizations

๋„ค ๊ธฐ๋ณธ์ ์œผ๋กœ ๊ฐ™์€ ์ƒ๊ฐ์ž…๋‹ˆ๋‹ค.

monaco๊ฐ€ ๋ฒ„ํผ๋ฅผ ์ €์žฅํ•˜๋Š” ์œ„์น˜์— ๋Œ€ํ•œ ๋‚ด ๋Œ€๋‹ต์ด ๋„ˆ๋ฌด ๋Šฆ์ง€ ์•Š๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค.

Alex์™€ ์ €๋Š” Array Buffer๋ฅผ ์„ ํ˜ธํ•˜๋ฉฐ ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ ์šฐ์ˆ˜ํ•œ ์„ฑ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ArrayBuffer๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ผ๋ถ€ ์žฅ์†Œ:

V8 ๋ฌธ์ž์—ด์€ ์กฐ์ž‘ํ•˜๊ธฐ ์‰ฝ๊ธฐ ๋•Œ๋ฌธ์— ๋ฐฐ์—ด ๋ฒ„ํผ ๋Œ€์‹  ํ…์ŠคํŠธ ๋ฒ„ํผ์— ๊ฐ„๋‹จํ•œ ๋ฌธ์ž์—ด์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

  • ํŒŒ์ผ ๋กœ๋”ฉ ์ดˆ๊ธฐ์— ์ธ์ฝ”๋”ฉ/๋””์ฝ”๋”ฉ์„ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํŒŒ์ผ์€ JS ์ŠคํŠธ๋ง์œผ๋กœ ๋ณ€ํ™˜๋ฉ๋‹ˆ๋‹ค. V8์€ ๋ฌธ์ž๋ฅผ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•ด 1๋ฐ”์ดํŠธ ๋˜๋Š” 2๋ฐ”์ดํŠธ๋ฅผ ์‚ฌ์šฉํ• ์ง€ ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค.
  • ์šฐ๋ฆฌ๋Š” ํ…์ŠคํŠธ ๋ฒ„ํผ๋ฅผ ๋งค์šฐ ์ž์ฃผ ํŽธ์ง‘ํ•ฉ๋‹ˆ๋‹ค. ๋ฌธ์ž์—ด์€ ๋‹ค๋ฃจ๊ธฐ ์‰ฝ์Šต๋‹ˆ๋‹ค.
  • nodejs ๋„ค์ดํ‹ฐ๋ธŒ ๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์œผ๋ฉฐ ํ•„์š”ํ•œ ๊ฒฝ์šฐ V8 ๋‚ด๋ถ€์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ ๋ชฉ๋ก์€ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰ ๋ฐ/๋˜๋Š” ๋Ÿฐํƒ€์ž„์„ ์ค„์ด๋Š” ๋ฐ ๋„์›€์ด ๋  ์ˆ˜ ์žˆ๋Š” ํฅ๋ฏธ๋กœ์šด ๊ฐœ๋…์„ ๊ฐ„๋žตํ•˜๊ฒŒ ์š”์•ฝํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

  • FlatJS(https://github.com/lars-t-hansen/flatjs) - arraybuffer ๊ธฐ๋ฐ˜ ํž™์œผ๋กœ ์ฝ”๋”ฉํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋˜๋Š” ๋ฉ”ํƒ€ ์–ธ์–ด
  • http://2ality.com/2017/01/shared-array-buffer.html (ES2017์˜ ์ผ๋ถ€๋กœ ๋ฐœํ‘œ๋จ, ์‹ค์ œ ๋™์‹œ์„ฑ๊ณผ ์‹ค์ œ ์›์ž์„ฑ์„ ๊ฐ–์ถ˜ ๋งค์šฐ ์œ ๋งํ•œ ์•„์ด๋””์–ด ์™ธ์— Spectre๋กœ ์ธํ•ด ๋ฏธ๋ž˜๊ฐ€ ๋ถˆํ™•์‹คํ•  ์ˆ˜ ์žˆ์Œ)
  • webassembly/asm.js (ํ˜„์žฌ ์ƒํƒœ? ์•„์ง ์‚ฌ์šฉ ๊ฐ€๋Šฅ? ์–ผ๋งˆ ๋™์•ˆ ๊ฐœ๋ฐœ์„ ๋”ฐ๋ฅด์ง€ ์•Š์•˜์œผ๋ฉฐ ๋ช‡ ๋…„ ์ „ ๊ฒŒ์ž„ AI์šฉ C lib์™€ ํ•จ๊ป˜ emscripten์„ asm.js์— ์‚ฌ์šฉํ–ˆ์ง€๋งŒ ์ธ์ƒ์ ์ธ ๊ฒฐ๊ณผ๋ฅผ ์–ป์—ˆ์Œ)
  • https://github.com/AssemblyScript/assemblyscript

์—ฌ๊ธฐ์—์„œ ํ•ฉ๊ณ„๋ฅผ ๊ตฌํ•˜๋ ค๋ฉด ํ…์ŠคํŠธ ์†์„ฑ์„ "๋ณ‘ํ•ฉ"ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค.

์ฝ”๋“œ๋Š” ์ฃผ๋กœ ๋ฒ„ํผ ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ ˆ์•ฝํ•œ๋‹ค๋Š” ์•„์ด๋””์–ด์— ์˜ํ•ด ์ฃผ๋„๋ฉ๋‹ˆ๋‹ค(๋Ÿฐํƒ€์ž„์€ ๋ฌธ์ œ๊ฐ€ ๋  ๊ฒƒ์ด๋ฉฐ, ์•„์ง ํ…Œ์ŠคํŠธ๋˜์ง€๋Š” ์•Š์•˜์Šต๋‹ˆ๋‹ค). ํŠนํžˆ ์ „๊ฒฝ๊ณผ ๋ฐฐ๊ฒฝ์— ๋Œ€ํ•ด RGB๊ฐ€ ์žˆ๋Š” ํ…์ŠคํŠธ ์†์„ฑ(ํ•œ ๋ฒˆ ์ง€์›๋จ)์€ xterm.js๊ฐ€ ์…€ ๋ ˆ์ด์•„์›ƒ๋ณ„๋กœ ํ˜„์žฌ ์…€์— ์˜ํ•ด ๋งŽ์€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋จน๊ฒŒ ๋งŒ๋“ค ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด ์ฝ”๋“œ๋Š” ์†์„ฑ์— ๋Œ€ํ•œ ํฌ๊ธฐ ์กฐ์ • ๊ฐ€๋Šฅํ•œ ์ฐธ์กฐ ๊ณ„์‚ฐ ์•„ํ‹€๋ผ์Šค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ด๋ฅผ ์šฐํšŒํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ๋‹จ์ผ ํ„ฐ๋ฏธ๋„์€ ๊ฑฐ์˜ 1๋ฐฑ๋งŒ ๊ฐœ ์ด์ƒ์˜ ์…€์„ ๋ณด์œ ํ•  ์ˆ˜ ์—†์œผ๋ฏ€๋กœ ๋ชจ๋“  ์…€์ด ๋‹ค๋ฅธ ๊ฒฝ์šฐ ์•„ํ‹€๋ผ์Šค๊ฐ€ 1M * entry_size ์ฆ๊ฐ€ํ•˜๋ฏ€๋กœ ์ด๊ฒƒ์€ ์˜ต์…˜์ด ์•„๋‹™๋‹ˆ๋‹ค.

์…€ ์ž์ฒด๋Š” ์†์„ฑ ์•„ํ‹€๋ผ์Šค์˜ ์ธ๋ฑ์Šค๋ฅผ ๋ณด์œ ํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ์…€ ๋ณ€๊ฒฝ ์‹œ ์ด์ „ ์ธ๋ฑ์Šค๋ฅผ ์ฐธ์กฐ ํ•ด์ œํ•˜๊ณ  ์ƒˆ ์ธ๋ฑ์Šค๋ฅผ ์ฐธ์กฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์•„ํ‹€๋ผ์Šค ์ธ๋ฑ์Šค๋Š” ํ„ฐ๋ฏธ๋„ ๊ฐœ์ฒด์˜ ์†์„ฑ ์†์„ฑ์„ ๋Œ€์ฒดํ•˜๊ณ  SGR์—์„œ ์ž์ฒด์ ์œผ๋กœ ๋ณ€๊ฒฝ๋ฉ๋‹ˆ๋‹ค.

์•„ํ‹€๋ผ์Šค๋Š” ํ˜„์žฌ ํ…์ŠคํŠธ ์†์„ฑ๋งŒ ๋‹ค๋ฃจ์ง€๋งŒ ํ•„์š”ํ•œ ๊ฒฝ์šฐ ๋ชจ๋“  ์…€ ์†์„ฑ์œผ๋กœ ํ™•์žฅ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ˜„์žฌ ํ„ฐ๋ฏธ๋„ ๋ฒ„ํผ๊ฐ€ ์†์„ฑ ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•ด 2๊ฐœ์˜ 32๋น„ํŠธ ์ˆซ์ž(ํ˜„์žฌ ๋ฒ„ํผ ๋””์ž์ธ์—์„œ RGB๊ฐ€ ์žˆ๋Š” 4๊ฐœ)๋ฅผ ๋ณด์œ ํ•˜๋Š” ๋™์•ˆ ์•„ํ‹€๋ผ์Šค๋Š” ์ด๋ฅผ ๋‹จ ํ•˜๋‚˜์˜ 32๋น„ํŠธ ์ˆซ์ž๋กœ ์ค„์ž…๋‹ˆ๋‹ค. ์•„ํ‹€๋ผ์Šค ํ•ญ๋ชฉ๋„ ์ถ”๊ฐ€๋กœ ํฌ์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

interface TextAttributes {
    flags: number;
    foreground: number;
    background: number;
}

const enum AtlasEntry {
    FLAGS = 1,
    FOREGROUND = 2,
    BACKGROUND = 3
}

class TextAttributeAtlas {
    /** data storage */
    private data: Uint32Array;
    /** flag lookup tree, not happy with that yet */
    private flagTree: any = {};
    /** holds freed slots */
    private freedSlots: number[] = [];
    /** tracks biggest idx to shortcut new slot assignment */
    private biggestIdx: number = 0;
    constructor(size: number) {
        this.data = new Uint32Array(size * 4);
    }
    private setData(idx: number, attributes: TextAttributes): void {
        this.data[idx] = 0;
        this.data[idx + AtlasEntry.FLAGS] = attributes.flags;
        this.data[idx + AtlasEntry.FOREGROUND] = attributes.foreground;
        this.data[idx + AtlasEntry.BACKGROUND] = attributes.background;
        if (!this.flagTree[attributes.flags])
            this.flagTree[attributes.flags] = [];
        if (this.flagTree[attributes.flags].indexOf(idx) === -1)
            this.flagTree[attributes.flags].push(idx);
    }

    /**
     * convenient method to inspect attributes at slot `idx`.
     * For better performance atlas idx and AtlasEntry
     * should be used directly to avoid number conversions.
     * <strong i="10">@param</strong> {number} idx
     * <strong i="11">@return</strong> {TextAttributes}
     */
    getAttributes(idx: number): TextAttributes {
        return {
            flags: this.data[idx + AtlasEntry.FLAGS],
            foreground: this.data[idx + AtlasEntry.FOREGROUND],
            background: this.data[idx + AtlasEntry.BACKGROUND]
        };
    }

    /**
     * Returns a slot index in the atlas for the given text attributes.
     * To be called upon attributes changes, e.g. by SGR.
     * NOTE: The ref counter is set to 0 for a new slot index, thus
     * values will get overwritten if not referenced in between.
     * <strong i="12">@param</strong> {TextAttributes} attributes
     * <strong i="13">@return</strong> {number}
     */
    getSlot(attributes: TextAttributes): number {
        // find matching attributes slot
        const sameFlag = this.flagTree[attributes.flags];
        if (sameFlag) {
            for (let i = 0; i < sameFlag.length; ++i) {
                let idx = sameFlag[i];
                if (this.data[idx + AtlasEntry.FOREGROUND] === attributes.foreground
                    && this.data[idx + AtlasEntry.BACKGROUND] === attributes.background) {
                    return idx;
                }
            }
        }
        // try to insert into a previously freed slot
        const freed = this.freedSlots.pop();
        if (freed) {
            this.setData(freed, attributes);
            return freed;
        }
        // else assign new slot
        for (let i = this.biggestIdx; i < this.data.length; i += 4) {
            if (!this.data[i]) {
                this.setData(i, attributes);
                if (i > this.biggestIdx)
                    this.biggestIdx = i;
                return i;
            }
        }
        // could not find a valid slot --> resize storage
        const data = new Uint32Array(this.data.length * 2);
        for (let i = 0; i < this.data.length; ++i)
            data[i] = this.data[i];
        const idx = this.data.length;
        this.data = data;
        this.setData(idx, attributes);
        return idx;
    }

    /**
     * Increment ref counter.
     * To be called for every terminal cell, that holds `idx` as text attributes.
     * <strong i="14">@param</strong> {number} idx
     */
    ref(idx: number): void {
        this.data[idx]++;
    }

    /**
     * Decrement ref counter. Once dropped to 0 the slot will be reused.
     * To be called for every cell that gets removed or reused with another value.
     * <strong i="15">@param</strong> {number} idx
     */
    unref(idx: number): void {
        this.data[idx]--;
        if (!this.data[idx]) {
            let treePart = this.flagTree[this.data[idx + AtlasEntry.FLAGS]];
            treePart.splice(treePart.indexOf(this.data[idx]), 1);
        }
    }
}

let atlas = new TextAttributeAtlas(2);
let a1 = atlas.getSlot({flags: 12, foreground: 13, background: 14});
atlas.ref(a1);
// atlas.unref(a1);
let a2 = atlas.getSlot({flags: 12, foreground: 13, background: 15});
atlas.ref(a2);
let a3 = atlas.getSlot({flags: 13, foreground: 13, background: 16});
atlas.ref(a3);
let a4 = atlas.getSlot({flags: 13, foreground: 13, background: 16});
console.log(atlas);
console.log(a1, a2, a3, a4);
console.log('a1', atlas.getAttributes(a1));
console.log('a2', atlas.getAttributes(a2));
console.log('a3', atlas.getAttributes(a3));
console.log('a4', atlas.getAttributes(a4));

ํŽธ์ง‘ํ•˜๋‹ค:
๋Ÿฐํƒ€์ž„ ํŒจ๋„ํ‹ฐ๋Š” ๊ฑฐ์˜ 0์ž…๋‹ˆ๋‹ค. ls -lR /usr/lib ์‚ฌ์šฉํ•œ ๋ฒค์น˜๋งˆํฌ์˜ ๊ฒฝ์šฐ ~2.3์ดˆ์˜ ์ด ๋Ÿฐํƒ€์ž„์— 1๋ฐ€๋ฆฌ์ดˆ ๋ฏธ๋งŒ์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. ํฅ๋ฏธ๋กœ์šด ์ฐธ๊ณ  ์‚ฌํ•ญ - ์ด ๋ช…๋ น์€ 5MB ๋ฐ์ดํ„ฐ ์ถœ๋ ฅ์„ ์œ„ํ•ด 64๊ฐœ ๋ฏธ๋งŒ์˜ ๋‹ค๋ฅธ ํ…์ŠคํŠธ ์†์„ฑ ์Šฌ๋กฏ์„ ์„ค์ •ํ•˜๊ณ  ์™„์ „ํžˆ ๊ตฌํ˜„๋˜๋ฉด 20MB ์ด์ƒ์„ ์ ˆ์•ฝํ•ฉ๋‹ˆ๋‹ค.

๋ฒ„ํผ์— ๋Œ€ํ•œ ๋ช‡ ๊ฐ€์ง€ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ํ…Œ์ŠคํŠธํ•˜๊ธฐ ์œ„ํ•ด ํ”„๋กœํ† ํƒ€์ž… PR์„ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค(๋ณ€๊ฒฝ ์‚ฌํ•ญ์— ๋Œ€ํ•œ ์ผ๋ฐ˜์ ์ธ ์•„์ด๋””์–ด๋Š” https://github.com/xtermjs/xterm.js/pull/1528#issue-196949371 ์ฐธ์กฐ).

  • PR #1528 : ์†์„ฑ ์•„ํ‹€๋ผ์Šค
  • PR #1529 : ๋ฒ„ํผ์—์„œ wcwidth ๋ฐ charCode ์ œ๊ฑฐ
  • PR #1530 : ๋ฒ„ํผ์˜ ๋ฌธ์ž์—ด์„ ์ฝ”๋“œํฌ์ธํŠธ/์…€ ์Šคํ† ๋ฆฌ์ง€ ์ธ๋ฑ์Šค ๊ฐ’์œผ๋กœ ๊ต์ฒด

@jerch "์•„ํ‹€๋ผ์Šค"๊ฐ€ ํ•ญ์ƒ "ํ…์Šค์ฒ˜ ์•„ํ‹€๋ผ์Šค"๋ฅผ ์˜๋ฏธํ•˜๋„๋ก ์•„ํ‹€๋ผ์Šค๋ผ๋Š” ๋‹จ์–ด๋ฅผ ๋ฉ€๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ์Šคํ† ์–ด๋‚˜ ์บ์‹œ ๊ฐ™์€ ๊ฒƒ์ด ๋” ๋‚˜์„๊นŒ์š”?

์˜ค, "์บ์‹œ"๋Š” ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค.

ํ…Œ์ŠคํŠธ๋ฒ ๋“œ PR์€ ๋๋‚ฌ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ ๋Œ€๋žต์ ์ธ ์š”์•ฝ์˜ ๋ฐฐ๊ฒฝ์„ ์–ป์œผ๋ ค๋ฉด PR ๋Œ“๊ธ€๋„ ์‚ดํŽด๋ณด์‹ญ์‹œ์˜ค.

์ œ์•ˆ:

  1. ๋‹จ์ผ ํ„ฐ๋ฏธ๋„ ์…€์˜ ์Šคํƒ€์ผ์„ ์ง€์ •ํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ๋ชจ๋“  ๊ฒƒ์„ ๋‹ด๊ธฐ ์œ„ํ•ด AttributeCache ๋ฅผ ๊ตฌ์ถ•ํ•ฉ๋‹ˆ๋‹ค. ํŠธ๋ฃจ ์ปฌ๋Ÿฌ ์‚ฌ์–‘๋„ ํฌํ•จํ•  ์ˆ˜ ์žˆ๋Š” ์ดˆ๊ธฐ ์ฐธ์กฐ ์นด์šดํŒ… ๋ฒ„์ „์€ #1528์„ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค. ์—ฌ๋Ÿฌ ํ„ฐ๋ฏธ๋„ ์•ฑ์—์„œ ์ถ”๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ €์žฅํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ ๋‹ค๋ฅธ ํ„ฐ๋ฏธ๋„ ์ธ์Šคํ„ด์Šค ๊ฐ„์— ์บ์‹œ๋ฅผ ๊ณต์œ ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
  2. ์งง์€ ํ„ฐ๋ฏธ๋„ ์ฝ˜ํ…์ธ  ๋ฐ์ดํ„ฐ ๋ฌธ์ž์—ด์„ ๋ณด์œ ํ•˜๊ธฐ ์œ„ํ•ด StringStorage ๋ฅผ ๋นŒ๋“œํ•ฉ๋‹ˆ๋‹ค. #1530์˜ ๋ฒ„์ „์€ ํฌ์ธํ„ฐ ์˜๋ฏธ๋ฅผ "์˜ค๋ฒ„๋กœ๋“œ"ํ•˜์—ฌ ๋‹จ์ผ ๋ฌธ์ž ๋ฌธ์ž์—ด์„ ์ €์žฅํ•˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•ฉ๋‹ˆ๋‹ค. wcwidth ๋Š” ์—ฌ๊ธฐ๋กœ ์˜ฎ๊ฒจ์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  3. ํ˜„์žฌ CharData ๋ฅผ [number, string, number, number] ์—์„œ [number, number] ์ถ•์†Œํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ์ˆซ์ž๋Š” ๋‹ค์Œ์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ(์ธ๋ฑ์Šค ๋ฒˆํ˜ธ)์ž…๋‹ˆ๋‹ค.

    • AttributeCache ํ•ญ๋ชฉ

    • StringStorage ํ•ญ๋ชฉ

์†์„ฑ์€ ๋งŽ์ด ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์„ ๊ฒƒ์ด๋ฏ€๋กœ ๋‹จ์ผ 32๋น„ํŠธ ์ˆซ์ž๋Š” ์‹œ๊ฐ„์ด ์ง€๋‚จ์— ๋”ฐ๋ผ ๋งŽ์€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ ˆ์•ฝํ•ฉ๋‹ˆ๋‹ค. StringStorage ํฌ์ธํ„ฐ๋Š” ๋‹จ์ผ ๋ฌธ์ž์— ๋Œ€ํ•œ ์‹ค์ œ ์œ ๋‹ˆ์ฝ”๋“œ ์ฝ”๋“œํฌ์ธํŠธ์ด๋ฏ€๋กœ CharData ์˜ code ํ•ญ๋ชฉ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์‹ค์ œ ๋ฌธ์ž์—ด์€ StringStorage.getString(idx) ๋กœ ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋„ค๋ฒˆ์งธ ํ•„๋“œ wcwidth ์˜ CharData ์•ก์„ธ์Šค ํ•  ์ˆ˜ StringStorage.wcwidth(idx) (์•„์ง ๊ตฌํ˜„๋˜์ง€ ์•Š์Œ). ์น˜์šฐ๋Š”์—์„œ ๊ฑฐ์˜ ๋Ÿฐํƒ€์ž„ ๋ฒŒ๊ธˆ์ด code ๊ณผ wcwidth ์—์„œ CharData (# 1529์—์„œ ํ…Œ์ŠคํŠธ๊ฐ€).

  1. ์ถ•์†Œ๋œ CharData ๋ฅผ ๊ณ ๋ฐ€๋„ Int32Array ๊ธฐ๋ฐ˜ ๋ฒ„ํผ ๊ตฌํ˜„์œผ๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค. ์Šคํ… ํด๋ž˜์Šค(์™„์ „ํ•œ ๊ธฐ๋Šฅ๊ณผ๋Š” ๊ฑฐ๋ฆฌ๊ฐ€ ๋ฉ€์Œ)๋กœ #1530์—์„œ ํ…Œ์ŠคํŠธํ•œ ๊ฒฐ๊ณผ ์ตœ์ข… ์ด์ ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

    • ํ„ฐ๋ฏธ๋„ ๋ฒ„ํผ์˜ 80% ๋” ์ž‘์€ ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„(5.5MB์—์„œ 0.75MB๋กœ)

    • ์•ฝ๊ฐ„ ๋” ๋น ๋ฆ„(์•„์ง ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์—†์Œ, 20% - 30% ์†๋„ ํ–ฅ์ƒ ์˜ˆ์ƒ)

    • ํŽธ์ง‘: ํ›จ์”ฌ ๋น ๋ฆ„ - ls -lR /usr/lib ์Šคํฌ๋ฆฝํŠธ ๋Ÿฐํƒ€์ž„์ด 1.3์ดˆ๋กœ ๋–จ์–ด์กŒ์Šต๋‹ˆ๋‹ค(๋งˆ์Šคํ„ฐ๋Š” 2.1์ดˆ์ž„). ์ด์ „ ๋ฒ„ํผ๋Š” ์ปค์„œ ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•ด ์—ฌ์ „ํžˆ ํ™œ์„ฑํ™”๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ œ๊ฑฐ๋˜๋ฉด ๋Ÿฐํƒ€์ž„์ด 1์ดˆ ๋ฏธ๋งŒ์œผ๋กœ ๋–จ์–ด์งˆ ๊ฒƒ์œผ๋กœ ์˜ˆ์ƒ๋ฉ๋‹ˆ๋‹ค.

๋‹จ์  - 4๋‹จ๊ณ„๋Š” ๋ฒ„ํผ ์ธํ„ฐํŽ˜์ด์Šค์—์„œ ์•ฝ๊ฐ„์˜ ์žฌ์ž‘์—…์ด ํ•„์š”ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ƒ๋‹นํžˆ ๋งŽ์€ ์ž‘์—…์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด๋ด - RAM์˜ 80%๋ฅผ ์ ˆ์•ฝํ•˜๊ณ  ์—ฌ์ „ํžˆ ๋Ÿฐํƒ€์ž„ ์„ฑ๋Šฅ์„ ์–ป๋Š” ๋ฐ๋Š” ํฐ ๋ฌธ์ œ๊ฐ€ ๋˜์ง€ ์•Š์Šต๋‹ˆ๊นŒ? :์›ƒ๋‹ค:

๋‚ด๊ฐ€ ์šฐ์—ฐํžˆ ๋ฐœ๊ฒฌํ•œ ๋˜ ๋‹ค๋ฅธ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐ”๋กœ ํ˜„์žฌ ๋นˆ ์…€ ํ‘œํ˜„์ž…๋‹ˆ๋‹ค. Imho a cell์€ 3๊ฐ€์ง€ ์ƒํƒœ๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ๋น„์–ด ์žˆ์Œ : ์ดˆ๊ธฐ ์…€ ์ƒํƒœ, ์•„์ง ์•„๋ฌด๊ฒƒ๋„ ๊ธฐ๋ก๋˜์ง€ ์•Š์•˜๊ฑฐ๋‚˜ ๋‚ด์šฉ์ด ์‚ญ์ œ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋„ˆ๋น„๊ฐ€ 1์ด์ง€๋งŒ ๋‚ด์šฉ์ด ์—†์Šต๋‹ˆ๋‹ค. ํ˜„์žฌ blankLine ๋ฐ eraseChar ์—์„œ ์‚ฌ์šฉ๋˜์ง€๋งŒ ๋‚ด์šฉ์œผ๋กœ ๊ณต๋ฐฑ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.
  • null : ์‹œ๊ฐ์  ํ‘œํ˜„์„ ์œ„ํ•œ ๋„ˆ๋น„๊ฐ€ ์—†์Œ์„ ๋‚˜ํƒ€๋‚ด๋Š” ์ „์ฒด ๋„ˆ๋น„ char ๋’ค์˜ ์…€์ž…๋‹ˆ๋‹ค.
  • normal : ์…€์ด ์ผ๋ถ€ ์ฝ˜ํ…์ธ ๋ฅผ ๋ณด์œ ํ•˜๊ณ  ์‹œ๊ฐ์  ๋„ˆ๋น„๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค(1 ๋˜๋Š” 2, ์‹ค์ œ grapheme/bidi ํ•ญ๋ชฉ์„ ์ง€์›ํ•˜๋ฉด ๋” ์ปค์งˆ ์ˆ˜ ์žˆ์ง€๋งŒ ์•„์ง ํ™•์‹คํ•˜์ง€ ์•Š์Œ lol).

์—ฌ๊ธฐ์„œ ๋‚ด๊ฐ€ ๋ณผ ์ˆ˜ ์žˆ๋Š” ๋ฌธ์ œ๋Š” ๋นˆ ์…€์ด ๊ณต๋ฐฑ์ด ์‚ฝ์ž…๋œ ์ผ๋ฐ˜ ์…€๊ณผ ๊ตฌ๋ณ„๋˜์ง€ ์•Š๊ณ  ๋ฒ„ํผ ์ˆ˜์ค€(๋™์ผํ•œ ๋‚ด์šฉ, ๋™์ผํ•œ ๋„ˆ๋น„)์—์„œ ๋™์ผํ•˜๊ฒŒ ๋ณด์ž…๋‹ˆ๋‹ค. ๋‚˜๋Š” ๋ Œ๋”๋Ÿฌ/์ถœ๋ ฅ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜์ง€ ์•Š์•˜์ง€๋งŒ ์ด๊ฒƒ์ด ์ถœ๋ ฅ ํ”„๋ก ํŠธ์—์„œ ์–ด์ƒ‰ํ•œ ์ƒํ™ฉ์œผ๋กœ ์ด์–ด์งˆ ๊ฒƒ์œผ๋กœ ์˜ˆ์ƒํ•ฉ๋‹ˆ๋‹ค. ํŠนํžˆ ์ค„์˜ ์˜ค๋ฅธ์ชฝ ๋์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ๋ฒˆ๊ฑฐ๋กœ์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
15๊ฐœ์˜ ์—ด์ด ์žˆ๋Š” ํ„ฐ๋ฏธ๋„, ๋จผ์ € ์ผ๋ถ€ ๋ฌธ์ž์—ด ์ถœ๋ ฅ์ด ๋ž˜ํ•‘๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

1: 'H', 'e', 'l', 'l', 'o', ' ', 't', 'e', 'r', 'm', 'i', 'n', 'a', 'l', ' '
2: 'w', 'o', 'r', 'l', 'd', '!', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '

ls ์žˆ๋Š” ํด๋” ๋ชฉ๋ก๊ณผ ๋น„๊ต:

1: 'R', 'e', 'a', 'd', 'm', 'e', '.', 'm', 'd', ' ', ' ', ' ', ' ', ' ', ' '
2: 'f', 'i', 'l', 'e', 'A', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '

์ฒซ ๋ฒˆ์งธ ์˜ˆ๋Š” 'terminal'์ด๋ผ๋Š” ๋‹จ์–ด ๋’ค์— ์‹ค์ œ ๊ณต๋ฐฑ ์„ ํฌํ•จํ•˜๊ณ , ๋‘ ๋ฒˆ์งธ ์˜ˆ๋Š” 'Readme.md' ๋’ค์˜ ์…€์„ ๊ฑด๋“œ๋ฆฌ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ฒ„ํผ ์ˆ˜์ค€์—์„œ ํ‘œํ˜„๋˜๋Š” ๋ฐฉ์‹์€ ํ‘œ์ค€ ์ผ€์ด์Šค๊ฐ€ ํ™”๋ฉด์— ํ„ฐ๋ฏธ๋„ ์ถœ๋ ฅ์œผ๋กœ ๋ฌผ๊ฑด์„ ์ธ์‡„ํ•˜๋Š” ๋ฐ ์™„๋ฒฝํ•˜์ง€๋งŒ(์–ด์จŒ๋“  ๋ฐฉ์„ ๊ฐ€์ ธ์™€์•ผ ํ•จ), ๋งˆ์šฐ์Šค ์„ ํƒ๊ณผ ๊ฐ™์€ ์ฝ˜ํ…์ธ  ๋ฌธ์ž์—ด์„ ์ฒ˜๋ฆฌํ•˜๋ ค๋Š” ๋„๊ตฌ์˜ ๊ฒฝ์šฐ ๋˜๋Š” ๋ฆฌํ”Œ ๋กœ์šฐ ๊ด€๋ฆฌ์ž๋Š” ๋” ์ด์ƒ ๊ณต๊ฐ„์ด ์–ด๋””์—์„œ ์™”๋Š”์ง€ ๋ช…ํ™•ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ๋‹ค์Œ ์งˆ๋ฌธ์œผ๋กœ ์ด์–ด์ง‘๋‹ˆ๋‹ค. ์ค„์˜ ์‹ค์ œ ๋‚ด์šฉ ๊ธธ์ด(์™ผ์ชฝ์—์„œ ๋ฌด์–ธ๊ฐ€๋ฅผ ํฌํ•จํ•˜๋Š” ์…€์˜ ์–‘)๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋ฌด์—‡์ž…๋‹ˆ๊นŒ? ๊ฐ„๋‹จํ•œ ์ ‘๊ทผ ๋ฐฉ์‹์€ ์˜ค๋ฅธ์ชฝ์—์„œ ๋นˆ ์…€์„ ์„ธ๋Š”๋ฐ, ์œ„์˜ ์ด์ค‘ ์˜๋ฏธ๋Š” ์ด๊ฒƒ์„ ๊ฒฐ์ •ํ•˜๊ธฐ ์–ด๋ ต๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

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

Btw, ์œ„์˜ ๋ž˜ํ•‘๋œ ๋ฌธ์ž์—ด์˜ ๊ฒฝ์šฐ isWrapped ๋ฌธ์ œ๋„ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ๋ฆฌํ”Œ๋กœ์šฐ ํฌ๊ธฐ ์กฐ์ • ๋˜๋Š” ์˜ฌ๋ฐ”๋ฅธ ๋ณต์‚ฌ ๋ฐ ๋ถ™์—ฌ๋„ฃ๊ธฐ ์„ ํƒ ์ฒ˜๋ฆฌ์— ํ•„์ˆ˜์ ์ž…๋‹ˆ๋‹ค. Imho ์šฐ๋ฆฌ๋Š” ๊ทธ๊ฒƒ์„ ์ œ๊ฑฐ ํ•  ์ˆ˜ ์—†์ง€๋งŒ at๋ณด๋‹ค ๋” ์ž˜ ํ†ตํ•ฉํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

@jerch ์ธ์ƒ์ ์ธ ์ž‘ํ’ˆ! : ์Šค๋งˆ์ผ :

1 ๋‹จ์ผ ํ„ฐ๋ฏธ๋„ ์…€์˜ ์Šคํƒ€์ผ์„ ์ง€์ •ํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ๋ชจ๋“  ๊ฒƒ์„ ๋ณด์œ ํ•˜๋Š” AttributeCache๋ฅผ ๊ตฌ์ถ•ํ•ฉ๋‹ˆ๋‹ค. ํŠธ๋ฃจ ์ปฌ๋Ÿฌ ์‚ฌ์–‘๋„ ํฌํ•จํ•  ์ˆ˜ ์žˆ๋Š” ์ดˆ๊ธฐ ์ฐธ์กฐ ์นด์šดํŒ… ๋ฒ„์ „์€ #1528์„ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค. ์—ฌ๋Ÿฌ ํ„ฐ๋ฏธ๋„ ์•ฑ์—์„œ ์ถ”๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ €์žฅํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ ๋‹ค๋ฅธ ํ„ฐ๋ฏธ๋„ ์ธ์Šคํ„ด์Šค ๊ฐ„์— ์บ์‹œ๋ฅผ ๊ณต์œ ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

#1528์— ๋Œ€ํ•œ ์˜๊ฒฌ์„ ์ž‘์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.

2 ์งง์€ ํ„ฐ๋ฏธ๋„ ์ฝ˜ํ…์ธ  ๋ฐ์ดํ„ฐ ๋ฌธ์ž์—ด์„ ๋ณด๊ด€ํ•  StringStorage๋ฅผ ๊ตฌ์ถ•ํ•ฉ๋‹ˆ๋‹ค. #1530์˜ ๋ฒ„์ „์€ ํฌ์ธํ„ฐ ์˜๋ฏธ๋ฅผ "์˜ค๋ฒ„๋กœ๋“œ"ํ•˜์—ฌ ๋‹จ์ผ ๋ฌธ์ž ๋ฌธ์ž์—ด์„ ์ €์žฅํ•˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•ฉ๋‹ˆ๋‹ค. wcwidth๋ฅผ ์—ฌ๊ธฐ๋กœ ์˜ฎ๊ฒจ์•ผ ํ•ฉ๋‹ˆ๋‹ค.

#1530์— ๋Œ€ํ•œ ์˜๊ฒฌ์„ ์ž‘์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.

4 ์ถ•์†Œ๋œ CharData๋ฅผ ๋ฐ€๋„๊ฐ€ ๋†’์€ Int32Array ๊ธฐ๋ฐ˜ ๋ฒ„ํผ ๊ตฌํ˜„์œผ๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค. ์Šคํ… ํด๋ž˜์Šค(์™„์ „ํ•œ ๊ธฐ๋Šฅ๊ณผ๋Š” ๊ฑฐ๋ฆฌ๊ฐ€ ๋ฉ€์Œ)๋กœ #1530์—์„œ ํ…Œ์ŠคํŠธํ•œ ๊ฒฐ๊ณผ ์ตœ์ข… ์ด์ ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

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

๋‚ด๊ฐ€ ์šฐ์—ฐํžˆ ๋ฐœ๊ฒฌํ•œ ๋˜ ๋‹ค๋ฅธ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐ”๋กœ ํ˜„์žฌ ๋นˆ ์…€ ํ‘œํ˜„์ž…๋‹ˆ๋‹ค. Imho ์„ธํฌ๋Š” 3๊ฐœ์˜ ์ƒํƒœ๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค

๋‹ค์Œ์€ ์ด https://github.com/xtermjs/xterm.js/issues/1286 , :+1: ๊ณต๋ฐฑ ์…€๊ณผ "๋นˆ" ์…€์„ ๊ตฌ๋ณ„ํ•˜๋Š” ๋ฒ„๊ทธ์˜ ์˜ˆ์ž…๋‹ˆ๋‹ค.

Btw, ์œ„์˜ ๋ž˜ํ•‘๋œ ๋ฌธ์ž์—ด์˜ ๊ฒฝ์šฐ์—๋„ isWrapped ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ๋ฆฌํ”Œ๋กœ์šฐ ํฌ๊ธฐ ์กฐ์ • ๋˜๋Š” ์˜ฌ๋ฐ”๋ฅธ ๋ณต์‚ฌ ๋ฐ ๋ถ™์—ฌ๋„ฃ๊ธฐ ์„ ํƒ ์ฒ˜๋ฆฌ์— ํ•„์ˆ˜์ ์ž…๋‹ˆ๋‹ค. Imho ์šฐ๋ฆฌ๋Š” ๊ทธ๊ฒƒ์„ ์ œ๊ฑฐ ํ•  ์ˆ˜ ์—†์ง€๋งŒ at๋ณด๋‹ค ๋” ์ž˜ ํ†ตํ•ฉํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

CircularList์—๋Š” ๋ž˜ํ•‘๋˜์ง€ ์•Š์€ ํ–‰๋งŒ ํฌํ•จ๋˜๋ฏ€๋กœ https://github.com/xtermjs/xterm.js/issues/622 ๋ฅผ ์ฒ˜๋ฆฌํ•  ๋•Œ isWrapped ์‚ฌ๋ผ์ง€๋Š” ๊ฒƒ์„ ๋ด…๋‹ˆ๋‹ค.

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

์˜ˆ, ์ €๋Š” ๋‹น์‹ ๊ณผ ํ•จ๊ป˜ํ•ฉ๋‹ˆ๋‹ค(์ด ์™„์ „ํžˆ ๋‹ค๋ฅธ ์ ‘๊ทผ ๋ฐฉ์‹์„ ๊ฐ€์ง€๊ณ  ๋…ธ๋Š” ๊ฒƒ์€ ์—ฌ์ „ํžˆ โ€‹โ€‹์žฌ๋ฏธ์žˆ์Šต๋‹ˆ๋‹ค). 1๊ณผ 2๋Š” ์„ ํƒ๋  ์ˆ˜ ์žˆ๊ณ  3์€ 1 ๋˜๋Š” 2์— ๋”ฐ๋ผ ์ ์šฉ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 4๋Š” ์„ ํƒ ์‚ฌํ•ญ์ด๋ฉฐ ํ˜„์žฌ ๋ฒ„ํผ ๋ ˆ์ด์•„์›ƒ์„ ๊ณ ์ˆ˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฉ”๋ชจ๋ฆฌ ์ ˆ์•ฝ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  1. 1 + 2 + 3 in CircularList : 50% ์ ˆ์•ฝ(~5.5MB ์ค‘ ~2.8MB)
  2. 1 + 2 + 3 + 4 ์ค‘๊ฐ„ - ํ–‰ ๋ฐ์ดํ„ฐ๋ฅผ ์œ ํ˜•์ด ์ง€์ •๋œ ๋ฐฐ์—ด์— ๋„ฃ์ง€๋งŒ ํ–‰ ์ธ๋ฑ์Šค ์•ก์„ธ์Šค๋ฅผ ์œ ์ง€: 82%(~0.9MB) ์ ˆ์•ฝ
  3. ํฌ์ธํ„ฐ ์‚ฐ์ˆ ์ด ํฌํ•จ๋œ 1 + 2 + 3 + 4 ์™„์ „ ๋ฐ€๋„ ๋ฐฐ์—ด: 87% ์ ˆ์•ฝ(~0.7MB)

1. ๊ตฌํ˜„ํ•˜๊ธฐ๊ฐ€ ๋งค์šฐ ์‰ฝ์Šต๋‹ˆ๋‹ค. ๋” ํฐ scrollBack์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฉ”๋ชจ๋ฆฌ ๋™์ž‘์€ https://github.com/xtermjs/xterm.js/pull/1530#issuecomment -403542479์— ํ‘œ์‹œ๋œ ๊ฒƒ์ฒ˜๋Ÿผ ์—ฌ์ „ํžˆ ๋‚˜์œ ์Šค์ผ€์ผ๋ง์„ ํ‘œ์‹œํ•˜์ง€๋งŒ ๋œ ์œ ๋…ํ•œ ์ˆ˜์ค€์ž…๋‹ˆ๋‹ค.
2. ๊ตฌํ˜„ํ•˜๊ธฐ๊ฐ€ ์•ฝ๊ฐ„ ๋” ์–ด๋ ต์ง€๋งŒ(๋ผ์ธ ์ˆ˜์ค€์—์„œ ๋” ๋งŽ์€ ๊ฐ„์ ‘ ์ฐธ์กฐ๊ฐ€ ํ•„์š”ํ•จ) Buffer ์˜ ์ƒ์œ„ API๋ฅผ ๊ทธ๋Œ€๋กœ ์œ ์ง€ํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. Imho ์˜ต์…˜ - ํฐ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ €์žฅํ•˜๊ณ  ํ†ตํ•ฉํ•˜๊ธฐ ์‰ฝ์Šต๋‹ˆ๋‹ค.
3. ๊ตฌํ˜„ํ•˜๊ธฐ ์–ด๋ ค์šด ์˜ต์…˜ 2๋ณด๋‹ค 5% ๋” ๋งŽ์€ ๋ฉ”๋ชจ๋ฆฌ ์ €์žฅ์€ ๋ชจ๋“  API๋ฅผ ๋ณ€๊ฒฝํ•˜๋ฏ€๋กœ ๋ง ๊ทธ๋Œ€๋กœ ์ „์ฒด ์ฝ”๋“œ ๊ธฐ๋ฐ˜์„ ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค. ํ•™๋ฌธ์  ๊ด€์‹ฌ์ด๋‚˜ ์ง€๋ฃจํ•œ ๋น„์˜ค๋Š” ๋‚ ์„ ์œ„ํ•ด ์ž„ํ˜ธ๋ฅผ ๋” ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.

@Tyriar ์›น ์–ด์…ˆ๋ธ”๋ฆฌ ์‚ฌ์šฉ์„ ์œ„ํ•ด ๋…น์œผ๋กœ ๋ช‡ ๊ฐ€์ง€ ์ถ”๊ฐ€ ํ…Œ์ŠคํŠธ๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ณ  ํŒŒ์„œ๋ฅผ ๋‹ค์‹œ ์ž‘์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‚ด ๋…น ๊ธฐ์ˆ ์€ ์•„์ง ๋” ๊นŠ์ด ๋“ค์–ด๊ฐ€์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์— ์•ฝ๊ฐ„ "๋…น์ด ์Šฌ์—ˆ์Šต๋‹ˆ๋‹ค". ๋”ฐ๋ผ์„œ ๋‹ค์Œ์€ ์•ฝํ•œ ๋…น ์ฝ”๋“œ์˜ ๊ฒฐ๊ณผ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฒฐ๊ณผ:

  • wasm ๋ถ€๋ถ„ ๋‚ด์—์„œ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ๊ฐ€ ์•ฝ๊ฐ„ ๋” ๋น ๋ฆ…๋‹ˆ๋‹ค(5 - 10%).
  • JS์—์„œ wasm์œผ๋กœ์˜ ํ˜ธ์ถœ์€ ์•ฝ๊ฐ„์˜ ์˜ค๋ฒ„ํ—ค๋“œ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์œ„์˜ ๋ชจ๋“  ์ด์ ์„ ๋จน์Šต๋‹ˆ๋‹ค. ์‹ค์ œ๋กœ๋Š” ~20% ๋Š๋ ธ์Šต๋‹ˆ๋‹ค.
  • "๋ฐ”์ด๋„ˆ๋ฆฌ"๋Š” JS ์ƒ๋Œ€๋ณด๋‹ค ์ž‘์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค(๋ชจ๋“  ๊ฒƒ์„ ๊ตฌํ˜„ํ•˜์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์— ์‹ค์ œ๋กœ ์ธก์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค).
  • JS <--> wasm ์ „ํ™˜์„ ์‰ฝ๊ฒŒ ์ˆ˜ํ–‰ํ•˜๋ ค๋ฉด JS ์œ ํ˜•์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ ์ผ๋ถ€ bloatcode๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค(๋ฌธ์ž์—ด ๋ณ€ํ™˜๋งŒ ์ˆ˜ํ–‰).
  • ๋ธŒ๋ผ์šฐ์ € DOM ๋ฐ ์ด๋ฒคํŠธ์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— JS์—์„œ wasm์œผ๋กœ์˜ ๋ณ€ํ™˜์„ ํ”ผํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๋” ์ด์ƒ ์„ฑ๋Šฅ์ด ์ค‘์š”ํ•˜์ง€ ์•Š์€ ํ•ต์‹ฌ ๋ถ€ํ’ˆ์—๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(mem ์†Œ๋น„ ์ œ์™ธ).

์ „์ฒด ํ•ต์‹ฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋…น(๋˜๋Š” ๋‹ค๋ฅธ wasm ๊ฐ€๋Šฅ ์–ธ์–ด)์œผ๋กœ ๋‹ค์‹œ ์ž‘์„ฑํ•˜์ง€ ์•Š์œผ๋ ค๋ฉด wasm lang imho๋กœ ์ด๋™ํ•˜์—ฌ ์•„๋ฌด ๊ฒƒ๋„ ์–ป์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์š”์ฆ˜ wasm lang์˜ ์žฅ์ ์€ ๋Œ€๋ถ€๋ถ„์ด ๋ช…์‹œ์  ๋ฉ”๋ชจ๋ฆฌ ์ฒ˜๋ฆฌ๋ฅผ ์ง€์›ํ•œ๋‹ค๋Š” ์‚ฌ์‹ค(๋ฒ„ํผ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋  ์ˆ˜ ์žˆ์Œ)์ด๊ณ , ๋‹จ์ ์€ ์ฃผ๋กœ TS/JS ์ค‘์‹ฌ ํ”„๋กœ์ ํŠธ์— ์™„์ „ํžˆ ๋‹ค๋ฅธ ์–ธ์–ด๋ฅผ ๋„์ž…ํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค(์ฝ”๋“œ ์ถ”๊ฐ€์— ๋Œ€ํ•œ ๋†’์€ ์žฅ๋ฒฝ) ๊ทธ๋ฆฌ๊ณ  wasm๊ณผ JS ๋žœ๋“œ ๊ฐ„์˜ ๋ฒˆ์—ญ ๋น„์šฉ.

TL;DR
xterm.js๋Š” DOM ๋ฐ ์ด๋ฒคํŠธ์™€ ๊ฐ™์€ ์ผ๋ฐ˜์ ์ธ JS ํ•ญ๋ชฉ์— ๊ด‘๋ฒ”์œ„ํ•˜๊ฒŒ ์ ์šฉ๋˜์–ด ํ•ต์‹ฌ ๋ถ€๋ถ„์„ ๋‹ค์‹œ ์ž‘์„ฑํ•˜๋Š” ๊ฒฝ์šฐ์—๋„ ์›น ์–ด์…ˆ๋ธ”๋ฆฌ์—์„œ ๋ฌด์—‡์ด๋“  ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@jerch ์ข‹์€ ์กฐ์‚ฌ : ์Šค๋งˆ์ผ :

JS์—์„œ wasm์œผ๋กœ์˜ ํ˜ธ์ถœ์€ ์•ฝ๊ฐ„์˜ ์˜ค๋ฒ„ํ—ค๋“œ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์œ„์˜ ๋ชจ๋“  ์ด์ ์„ ๋จน์Šต๋‹ˆ๋‹ค. ์‹ค์ œ๋กœ๋Š” ~20% ๋Š๋ ธ์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋‚ด ์ž…์žฅ์„ ์•Œ๋ ค์ค€ ๋ชจ๋‚˜์ฝ”์˜ ์ฃผ์š” ๋ฌธ์ œ ์ด๊ธฐ๋„ ํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ฐ€๋Šฅํ•œ ํ•œ ArrayBuffer ์ž‘์—…ํ•˜๋Š” ๊ฒƒ์ด ์„ฑ๋Šฅ๊ณผ ๋‹จ์ˆœ์„ฑ(๊ฐ„๋‹จํ•œ ์ž„ํ”Œ, ์ง„์ž… ์žฅ๋ฒฝ) ์‚ฌ์ด์—์„œ ์ตœ์ƒ์˜ ๊ท ํ˜•์„ ์ œ๊ณตํ•ด์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

@Tyriar RGB ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๊ด€ํ•  AttributeStorage๋ฅผ ๋งŒ๋“ค๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. BST์— ๋Œ€ํ•ด์„œ๋Š” ์•„์ง ํ™•์‹คํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ํ„ฐ๋ฏธ๋„ ์„ธ์…˜์—์„œ ๋ช‡ ๊ฐ€์ง€ ์ƒ‰์ƒ ์„ค์ •๋งŒ ์žˆ๋Š” ์ผ๋ฐ˜์ ์ธ ์‚ฌ์šฉ ์‚ฌ๋ก€์˜ ๊ฒฝ์šฐ ๋Ÿฐํƒ€์ž„์— ๋” ๋‚˜๋น ์งˆ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ƒ‰์ƒ์ด ์ฃผ์–ด์ง„ ์ž„๊ณ„๊ฐ’์„ ์ดˆ๊ณผํ•˜๋ฉด ๋Ÿฐํƒ€์ž„ ๋“œ๋กญ์ธ์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ๋ฉ”๋ชจ๋ฆฌ ์†Œ๋น„๊ฐ€ ๋‹ค์‹œ ๋งŽ์ด ์ฆ๊ฐ€ํ•˜์ง€๋งŒ ์†์„ฑ์€ ๋ชจ๋“  ๋‹จ์ผ ์…€๊ณผ ํ•จ๊ป˜ ์ €์žฅ๋˜์ง€ ์•Š๊ณ  ํ•œ ๋ฒˆ๋งŒ ์ €์žฅ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์—ฌ์ „ํžˆ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ ˆ์•ฝํ•ฉ๋‹ˆ๋‹ค.
ํ˜„์žฌ fg ๋ฐ bg 256์ƒ‰ ๊ฐ’์ด 8๋น„ํŠธ๊ฐ€ ์•„๋‹Œ 9๋น„ํŠธ ๊ธฐ๋ฐ˜์ธ ์ด์œ ๋ฅผ ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๊นŒ? ์ถ”๊ฐ€ ๋น„ํŠธ๋Š” ๋ฌด์—‡์— ์‚ฌ์šฉ๋ฉ๋‹ˆ๊นŒ? ์—ฌ๊ธฐ: https://github.com/xtermjs/xterm.js/blob/6691f809069a549b4808cd2e055398d2da15db37/src/InputHandler.ts#L1596
attr ์˜ ํ˜„์žฌ ๋น„ํŠธ ๋ ˆ์ด์•„์›ƒ์„ ์•Œ๋ ค์ฃผ์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ? StringStorage ํฌ์ธํ„ฐ์— ๋Œ€ํ•œ "์ด์ค‘ ์˜๋ฏธ"์™€ ๊ฐ™์€ ์œ ์‚ฌํ•œ ์ ‘๊ทผ ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋” ์ ˆ์•ฝํ•  ์ˆ˜ ์žˆ์ง€๋งŒ attr ์˜ MSB๋Š” ํฌ์ธํ„ฐ ๊ตฌ๋ถ„์„ ์œ„ํ•ด ์˜ˆ์•ฝ๋˜๊ณ  ๋‹ค๋ฅธ ์šฉ๋„๋กœ๋Š” ์‚ฌ์šฉ๋˜์ง€ ์•Š์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๋‚˜์ค‘์— ์ถ”๊ฐ€ ์†์„ฑ ํ”Œ๋ž˜๊ทธ๋ฅผ ์ง€์›ํ•  ๊ฐ€๋Šฅ์„ฑ์„ ์ œํ•œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค( FLAGS ์ด๋ฏธ 7๋น„ํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์—). ์šฐ๋ฆฌ๋Š” ์—ฌ์ „ํžˆ ์˜ฌ ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๋Š” ๋ช‡ ๊ฐ€์ง€ ๊ธฐ๋ณธ ํ”Œ๋ž˜๊ทธ๋ฅผ ๋†“์น˜๊ณ  ์žˆ์Šต๋‹ˆ๊นŒ?

๋ฒ„ํผ๋ผ๋Š” ์šฉ์–ด์˜ 32๋น„ํŠธ attr ์ˆซ์ž๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํŒจํ‚น๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

# 256 indexed colors
32:       0 (no RGB color)
31..25:   flags (7 bits)
24..17:   fg (8 bits, see question above)
16..9:    bg
8..1:     unused

# RGB colors
32:       1 (RGB color)
31..25:   flags (7 bits)
24..1:    pointer to RGB data (address space is 2^24, which should be sufficient)

์ด๋Ÿฐ ์‹์œผ๋กœ ์ €์žฅ์†Œ๋Š” ๋‘ ๊ฐœ์˜ 32๋น„ํŠธ ์ˆซ์ž๋กœ RGB ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด์œ ํ•ด์•ผ ํ•˜๋Š” ๋ฐ˜๋ฉด ํ”Œ๋ž˜๊ทธ๋Š” attr ์ˆซ์ž์— ๋จธ๋ฌด๋ฅผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@jerch ๊ทธ๋‚˜์ €๋‚˜ ์ œ๊ฐ€ ์ด๋ฉ”์ผ์„ ๋ณด๋ƒˆ๋Š”๋ฐ ์ŠคํŒธํ•„ํ„ฐ์— ๋˜ ๋จนํ˜”๋‚˜๋ด์š” ๐Ÿ˜›

ํ˜„์žฌ fg ๋ฐ bg 256 ์ƒ‰์ƒ ๊ฐ’์ด 8๋น„ํŠธ๊ฐ€ ์•„๋‹Œ 9๋น„ํŠธ ๊ธฐ๋ฐ˜์ธ ์ด์œ ๋ฅผ ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๊นŒ? ์ถ”๊ฐ€ ๋น„ํŠธ๋Š” ๋ฌด์—‡์— ์‚ฌ์šฉ๋ฉ๋‹ˆ๊นŒ?

๊ธฐ๋ณธ fg/bg ์ƒ‰์ƒ(์–ด๋‘์šธ ์ˆ˜๋„ ๋ฐ์„ ์ˆ˜ ์žˆ์Œ)์— ์‚ฌ์šฉ๋˜๋Š” ๊ฒƒ ๊ฐ™์•„์„œ ์‹ค์ œ๋กœ๋Š” 257๊ฐ€์ง€ ์ƒ‰์ƒ์ž…๋‹ˆ๋‹ค.

https://github.com/xtermjs/xterm.js/pull/756/files

attr์˜ ํ˜„์žฌ ๋น„ํŠธ ๋ ˆ์ด์•„์›ƒ์„ ์•Œ๋ ค์ฃผ์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?

๋‚˜๋Š” ์ด๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•œ๋‹ค:

19+:     flags (see `FLAGS` enum)
18..18:  default fg flag
17..10:  256 fg
9..9:    default bg flag
8..1:    256 bg

์ด์ „ PR https://github.com/xtermjs/xterm.js/pull/756/files ์—์„œ ๋‚ด๊ฐ€ ํŠธ๋ฃจ์ปฌ๋Ÿฌ์— ๋Œ€ํ•ด ์•Œ๊ฒŒ ๋œ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

/**
 * Character data, the array's format is:
 * - string: The character.
 * - number: The width of the character.
 * - number: Flags that decorate the character.
 *
 *        truecolor fg
 *        |   inverse
 *        |   |   underline
 *        |   |   |
 *   0b 0 0 0 0 0 0 0
 *      |   |   |   |
 *      |   |   |   bold
 *      |   |   blink
 *      |   invisible
 *      truecolor bg
 *
 * - number: Foreground color. If default bit flag is set, color is the default
 *           (inherited from the DOM parent). If truecolor fg flag is true, this
 *           is a 24-bit color of the form 0xxRRGGBB, if not it's an xterm color
 *           code ranging from 0-255.
 *
 *        red
 *        |       blue
 *   0x 0 R R G G B B
 *      |     |
 *      |     green
 *      default color bit
 *
 * - number: Background color. The same as foreground color.
 */
export type CharData = [string, number, number, number, number];

๊ทธ๋ž˜์„œ ์ด๊ฒƒ์—๋Š” 2๊ฐœ์˜ ๊นƒ๋ฐœ์ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ํ•˜๋‚˜๋Š” ๊ธฐ๋ณธ ์ƒ‰์ƒ(๋ชจ๋“  ์ƒ‰์ƒ ๋น„ํŠธ๋ฅผ ๋ฌด์‹œํ• ์ง€ ์—ฌ๋ถ€)์ด๊ณ  ๋‹ค๋ฅธ ํ•˜๋‚˜๋Š” ํŠธ๋ฃจ์ปฌ๋Ÿฌ(256 ๋˜๋Š” 16mil ์ƒ‰์ƒ์„ ์ˆ˜ํ–‰ํ• ์ง€ ์—ฌ๋ถ€)์ž…๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ๋‚˜์ค‘์— ์ถ”๊ฐ€ ์†์„ฑ ํ”Œ๋ž˜๊ทธ๋ฅผ ์ง€์›ํ•  ๊ฐ€๋Šฅ์„ฑ์„ ์ œํ•œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(FLAGS๋Š” ์ด๋ฏธ 7๋น„ํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์—). ์šฐ๋ฆฌ๋Š” ์—ฌ์ „ํžˆ ์˜ฌ ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๋Š” ๋ช‡ ๊ฐ€์ง€ ๊ธฐ๋ณธ ํ”Œ๋ž˜๊ทธ๋ฅผ ๋†“์น˜๊ณ  ์žˆ์Šต๋‹ˆ๊นŒ?

์˜ˆ, ์˜ˆ๋ฅผ ๋“ค์–ด https://github.com/xtermjs/xterm.js/issues/580, https://github.com/xtermjs/xterm.js/issues/1145์™€ ๊ฐ™์ด ์ถ”๊ฐ€ ํ”Œ๋ž˜๊ทธ๋ฅผ ์œ„ํ•œ ๊ณต๊ฐ„์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๊ฐ€๋Šฅํ•˜๋ฉด ์ตœ์†Œํ•œ 3๋น„ํŠธ ์ด์ƒ์œผ๋กœ ๋‘์‹ญ์‹œ์˜ค.

attr ์ž์ฒด ๋‚ด๋ถ€์˜ ํฌ์ธํ„ฐ ๋ฐ์ดํ„ฐ ๋Œ€์‹  rgb ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•œ ์ฐธ์กฐ๋ฅผ ๋ณด์œ ํ•˜๋Š” ๋‹ค๋ฅธ ๋งต์ด ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? mapAttrIdxToRgb: { [idx: number]: RgbData

@Tyriar ์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค. ๋ฉฐ์น  ๋™์•ˆ ์˜จ๋ผ์ธ ์ƒํƒœ๊ฐ€ ์•„๋‹ˆ์—ˆ๊ณ  ์ด๋ฉ”์ผ์ด ์ŠคํŒธ ํ•„ํ„ฐ์— ์˜ํ•ด ๋จนํž๊นŒ๋ด ๋‘๋ ต์Šต๋‹ˆ๋‹ค. ๋‹ค์‹œ ๋ณด๋‚ด์ฃผ์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ? :๋ถ‰ํžˆ๋‹ค:

attrs ์ €์žฅ์†Œ์— ๋Œ€ํ•œ ๋” ์˜๋ฆฌํ•œ ์กฐํšŒ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋กœ ์•ฝ๊ฐ„ ๋†€์•˜์Šต๋‹ˆ๋‹ค. ๊ณต๊ฐ„ ๋ฐ ๊ฒ€์ƒ‰/์‚ฝ์ž… ๋Ÿฐํƒ€์ž„๊ณผ ๊ด€๋ จํ•˜์—ฌ ๊ฐ€์žฅ ์œ ๋งํ•œ ๊ฒƒ์€ ๋” ์ €๋ ดํ•œ ๋Œ€์•ˆ์œผ๋กœ ๋‚˜๋ฌด์™€ ๊ฑด๋„ˆ๋›ฐ๊ธฐ ๋ชฉ๋ก์ž…๋‹ˆ๋‹ค. ์ด๋ก ์ƒ ใ…‹ใ…‹ใ…‹ใ…‹ ์‹ค์ œ๋กœ ์–ด๋Š ์ชฝ๋„ ๋‚˜์—๊ฒŒ ๋งค์šฐ ์ด์ƒํ•ด ๋ณด์ด๋Š” ๊ฐ„๋‹จํ•œ ๋ฐฐ์—ด ๊ฒ€์ƒ‰์„ ๋Šฅ๊ฐ€ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค(์ฝ”๋“œ ์–ด๋”˜๊ฐ€์— ๋ฒ„๊ทธ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ?)
๋‚˜๋Š” ํ…Œ์ŠคํŠธ ํŒŒ์ผ์„ ์—ฌ๊ธฐ https://gist.github.com/jerch/ff65f3fb4414ff8ac84a947b3a1eec58์— ์—…๋กœ๋“œํ–ˆ์Šต๋‹ˆ๋‹ค. ์–ด๋ ˆ์ด ๋Œ€ ์™ผ์ชฝ์œผ๋กœ ๊ธฐ์šธ์–ด์ง„ ์ -๊ฒ€์ • ํŠธ๋ฆฌ, ์ตœ๋Œ€ 10M ํ•ญ๋ชฉ(๊ฑฐ์˜ ์™„์ „ํ•œ ์ฃผ์†Œ ์ง€์ • ๊ณต๊ฐ„)์„ ํ…Œ์ŠคํŠธํ•ฉ๋‹ˆ๋‹ค. ์—ฌ์ „ํžˆ ์–ด๋ ˆ์ด๋Š” LLRB์— ๋น„ํ•ด ํ›จ์”ฌ ์•ž์„œ ์žˆ์ง€๋งŒ ์†์ต๋ถ„๊ธฐ์ ์€ ์•ฝ 10M์ผ ๊ฒƒ์œผ๋กœ ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๋‚ด 7๋…„ ๋œ ๋…ธํŠธ๋ถ์—์„œ ํ…Œ์ŠคํŠธํ–ˆ์œผ๋ฉฐ ๋ˆ„๊ตฐ๊ฐ€๊ฐ€ ํ…Œ์ŠคํŠธํ•  ์ˆ˜๋„ ์žˆ๊ณ  ๋” ์ž˜ ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. impl/tests์˜ ๋ช‡ ๊ฐ€์ง€ ๋ฒ„๊ทธ๋ฅผ ์•Œ๋ ค์ฃผ์„ธ์š”.

๋‹ค์Œ์€ ๋ช‡ ๊ฐ€์ง€ ๊ฒฐ๊ณผ์ž…๋‹ˆ๋‹ค(์—ฐ์† ๋ฒˆํ˜ธ ํฌํ•จ):

prefilled             time for inserting 1000 * 1000 (summed up, ms)
items                 array        LLRB
100-10000             3.5 - 5      ~13
100000                ~12          ~15
1000000               8            ~18
10000000              20-25        21-28

๋‚˜๋ฅผ ์ •๋ง ๋†€๋ผ๊ฒŒ ํ•œ ๊ฒƒ์€ ์„ ํ˜• ๋ฐฐ์—ด ๊ฒ€์ƒ‰์ด ํ•˜์œ„ ์˜์—ญ์—์„œ ์ „ํ˜€ ์„ฑ์žฅ์„ ๋ณด์—ฌ์ฃผ์ง€ ์•Š๋Š”๋‹ค๋Š” ์‚ฌ์‹ค์ด๋ฉฐ ~4ms์—์„œ ์ตœ๋Œ€ 10k ํ•ญ๋ชฉ์ด ์•ˆ์ •์ ์ด๋ผ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค(์บ์‹œ ๊ด€๋ จ์ผ ์ˆ˜ ์žˆ์Œ). 10M ํ…Œ์ŠคํŠธ๋Š” ๋‘˜ ๋‹ค ์˜ˆ์ƒ๋ณด๋‹ค ๋” ๋‚˜์œ ๋Ÿฐํƒ€์ž„์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. ์•„๋งˆ๋„ mem ํŽ˜์ด์ง•์œผ๋กœ ์ธํ•œ ๊ฒƒ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์•„๋งˆ๋„ JS๋Š” JIT์™€ ๋ชจ๋“  opt/deopts๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ธฐ๊ณ„์—์„œ ๋ฉ€๋ฆฌ ๋–จ์–ด์ ธ ์žˆ์ง€๋งŒ ์—ฌ์ „ํžˆ ๋ณต์žก์„ฑ ๋‹จ๊ณ„๋ฅผ ์ œ๊ฑฐํ•  ์ˆ˜ ์—†๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค(LLRB๊ฐ€ ๋‹จ์ผ _n_์—์„œ ๋ฌด๊ฑฐ์›Œ ๋ณด์ด๋ฏ€๋กœ O( n) ๋Œ€ O(logn) ์œ„์ชฝ)

๋ฌด์ž‘์œ„ ๋ฐ์ดํ„ฐ์˜ Btw๋Š” ๊ทธ ์ฐจ์ด๊ฐ€ ํ›จ์”ฌ ๋” ๋‚˜์ฉ๋‹ˆ๋‹ค.

๊ธฐ๋ณธ fg/bg ์ƒ‰์ƒ(์–ด๋‘์šธ ์ˆ˜๋„ ๋ฐ์„ ์ˆ˜ ์žˆ์Œ)์— ์‚ฌ์šฉ๋˜๋Š” ๊ฒƒ ๊ฐ™์•„์„œ ์‹ค์ œ๋กœ๋Š” 257๊ฐ€์ง€ ์ƒ‰์ƒ์ž…๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ 8๊ฐœ์˜ ํŒ”๋ ˆํŠธ ์ƒ‰์ƒ ์ค‘ ํ•˜๋‚˜์—์„œ SGR 39 ๋˜๋Š” SGR 49 ๋ฅผ ๊ตฌ๋ณ„ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๊นŒ?

attr ์ž์ฒด ๋‚ด๋ถ€์˜ ํฌ์ธํ„ฐ ๋ฐ์ดํ„ฐ ๋Œ€์‹  rgb ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•œ ์ฐธ์กฐ๋ฅผ ๋ณด์œ ํ•˜๋Š” ๋‹ค๋ฅธ ๋งต์ด ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? mapAttrIdxToRgb: { [idx: ๋ฒˆํ˜ธ]: RgbData

์ด๊ฒƒ์€ ์ถ”๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๊ณผ ํ•จ๊ป˜ ๋˜ ๋‹ค๋ฅธ ๊ฐ„์ ‘ ์ฐธ์กฐ๋ฅผ ์†Œ๊ฐœํ•ฉ๋‹ˆ๋‹ค. ์œ„์˜ ํ…Œ์ŠคํŠธ๋ฅผ ํ†ตํ•ด ํ”Œ๋ž˜๊ทธ๋ฅผ ํ•ญ์ƒ attr์— ์œ ์ง€ํ•˜๋Š” ๊ฒƒ๊ณผ RGB ๋ฐ์ดํ„ฐ์™€ ํ•จ๊ป˜ ์Šคํ† ๋ฆฌ์ง€์— ์ €์žฅํ•˜๋Š” ๊ฒƒ์˜ ์ฐจ์ด์ ๋„ ํ…Œ์ŠคํŠธํ–ˆ์Šต๋‹ˆ๋‹ค. 1M ํ•ญ๋ชฉ์˜ ๊ฒฝ์šฐ ์ฐจ์ด๊ฐ€ ~0.5ms์ด๋ฏ€๋กœ ์ด ๋ณต์žกํ•œ ์†์„ฑ ์„ค์ •์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ๋Œ€์‹  RGB๊ฐ€ ์„ค์ •๋˜๋ฉด ํ”Œ๋ž˜๊ทธ๋ฅผ ์ €์žฅ์†Œ์— ๋ณต์‚ฌํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜๋„ ์ง์ ‘ ์†์„ฑ ๋Œ€ ํฌ์ธํ„ฐ ์‚ฌ์ด์˜ 32๋น„ํŠธ ๊ตฌ๋ณ„์„ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด RGB๊ฐ€ ์•„๋‹Œ ์…€์— ๋Œ€ํ•œ ์ €์žฅ์ด ์ „ํ˜€ ๋ฐฉ์ง€๋˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

๋˜ํ•œ fg/bg์— ๋Œ€ํ•œ ๊ธฐ๋ณธ 8๊ฐœ์˜ ํŒ”๋ ˆํŠธ ์ƒ‰์ƒ์ด ํ˜„์žฌ ๋ฒ„ํผ์—์„œ ์ถฉ๋ถ„ํžˆ ํ‘œํ˜„๋˜์ง€ ์•Š๋Š”๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์ด๋ก ์ ์œผ๋กœ ํ„ฐ๋ฏธ๋„์€ ๋‹ค์Œ ์ƒ‰์ƒ ๋ชจ๋“œ๋ฅผ ์ง€์›ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  1. SGR 39 + SGR 49 fg/bg์˜ ๊ธฐ๋ณธ ์ƒ‰์ƒ(์‚ฌ์šฉ์ž ์ •์˜ ๊ฐ€๋Šฅ)
  2. SGR 30-37 + SGR 40-47 fg/bg์šฉ 8๊ฐ€์ง€ ๋‚ฎ์€ ์ƒ‰์ƒ ํŒ”๋ ˆํŠธ(์‚ฌ์šฉ์ž ์ •์˜ ๊ฐ€๋Šฅ)
  3. SGR 90-97 + SGR 100-107 fg/bg์šฉ 8๊ฐ€์ง€ ํ•˜์ด ์ปฌ๋Ÿฌ ํŒ”๋ ˆํŠธ(์‚ฌ์šฉ์ž ์ •์˜ ๊ฐ€๋Šฅ)
  4. SGR 38;5;n + SGR 48;5;n fg/bg๋ฅผ ์œ„ํ•œ 256๊ฐœ์˜ ์ธ๋ฑ์Šค ํŒ”๋ ˆํŠธ(์‚ฌ์šฉ์ž ์ •์˜ ๊ฐ€๋Šฅ)
  5. SGR 38;2;r;g;b + SGR 48;2;r;g;b fg/bg์šฉ RGB(์‚ฌ์šฉ์ž ์ •์˜ ๋ถˆ๊ฐ€)

์˜ต์…˜ 2.) ๋ฐ 3.)์„ ๋‹จ์ผ ๋ฐ”์ดํŠธ๋กœ ๋ณ‘ํ•ฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(๋‹จ์ผ 16์ƒ‰ fg/bg ํŒ”๋ ˆํŠธ๋กœ ์ฒ˜๋ฆฌ). 4.)๋Š” 2๋ฐ”์ดํŠธ, 5.)๋Š” ๋งˆ์ง€๋ง‰์œผ๋กœ 6๋ฐ”์ดํŠธ๋ฅผ ๋” ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ƒ‰์ƒ ๋ชจ๋“œ๋ฅผ ๋‚˜ํƒ€๋‚ด๊ธฐ ์œ„ํ•ด์„œ๋Š” ์—ฌ์ „ํžˆ ์•ฝ๊ฐ„์˜ ๋น„ํŠธ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
์ด๋ฅผ ๋ฒ„ํผ ์ˆ˜์ค€์— ๋ฐ˜์˜ํ•˜๋ ค๋ฉด ๋‹ค์Œ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

bits        for
2           fg color mode (0: default, 1: 16 palette, 2: 256, 3: RGB)
2           bg color mode (0: default, 1: 16 palette, 2: 256, 3: RGB)
8           fg color for 16 palette and 256
8           bg color for 16 palette and 256
10          flags (currently 7, 3 more reserved for future usage)
----
30

๋”ฐ๋ผ์„œ 32๋น„ํŠธ ์ˆซ์ž์˜ 30๋น„ํŠธ๊ฐ€ ํ•„์š”ํ•˜๊ณ  2๋น„ํŠธ๋Š” ๋‹ค๋ฅธ ์šฉ๋„๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 32๋ฒˆ์งธ ๋น„ํŠธ๋Š” ๋น„ RGB ์…€์— ๋Œ€ํ•œ ์ €์žฅ์„ ์ƒ๋žตํ•˜๋Š” ํฌ์ธํ„ฐ ๋Œ€ ์ง์ ‘ ์†์„ฑ ํ”Œ๋ž˜๊ทธ๋ฅผ ๋ณด์œ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋˜ํ•œ ๊ตฌํ˜„ ์„ธ๋ถ€ ์‚ฌํ•ญ์„ ์™ธ๋ถ€์— ๋…ธ์ถœํ•˜์ง€ ์•Š๋„๋ก attr ์•ก์„ธ์Šค๋ฅผ ํŽธ๋ฆฌํ•œ ํด๋ž˜์Šค๋กœ ๋งˆ๋ฌด๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค(์œ„์˜ ํ…Œ์ŠคํŠธ ํŒŒ์ผ ์ฐธ์กฐ, ์ด๋ฅผ ๋‹ฌ์„ฑํ•˜๊ธฐ ์œ„ํ•œ ์ดˆ๊ธฐ ๋ฒ„์ „์˜ TextAttributes ํด๋ž˜์Šค๊ฐ€ ์žˆ์Œ).

์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค. ๋ฉฐ์น  ๋™์•ˆ ์˜จ๋ผ์ธ ์ƒํƒœ๊ฐ€ ์•„๋‹ˆ์–ด์„œ ์ŠคํŒธ ํ•„ํ„ฐ์— ์ด๋ฉ”์ผ์ด ๊ฑธ๋ฆฐ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๋‹ค์‹œ ๋ณด๋‚ด์ฃผ์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?

ํ™”๋‚ด๋‹ค

์˜ค btw ๋ฐฐ์—ด ๋Œ€ llrb ๊ฒ€์ƒ‰์— ๋Œ€ํ•œ ์œ„์˜ ์ˆซ์ž๋Š” ์“ฐ๋ ˆ๊ธฐ์ž…๋‹ˆ๋‹ค. ์ตœ์ ํ™” ํ”„๋กœ๊ทธ๋žจ์ด for ๋ฃจํ”„์—์„œ ์ด์ƒํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜์—ฌ ๋ง์ณ ์กŒ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์•ฝ๊ฐ„ ๋‹ค๋ฅธ ํ…Œ์ŠคํŠธ ์„ค์ •์„ ์‚ฌ์šฉํ•˜๋ฉด ํ›จ์”ฌ ๋” ์ผ์ฐ ์„ฑ์žฅํ•˜๋Š” O(n) ๋Œ€ O(log n)์„ ๋ช…ํ™•ํ•˜๊ฒŒ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค(1000๊ฐœ์˜ ์š”์†Œ๊ฐ€ ๋ฏธ๋ฆฌ ์ฑ„์›Œ์ง„ ์ƒํƒœ์—์„œ ํŠธ๋ฆฌ๋กœ ์ด๋ฏธ ๋” ๋น ๋ฆ„).

ํ˜„์žฌ ์ƒํƒœ:

ํ›„์—:

์ƒ๋‹นํžˆ ๊ฐ„๋‹จํ•œ ์ตœ์ ํ™” ์ค‘ ํ•˜๋‚˜๋Š” ๋ฐฐ์—ด ๋ฐฐ์—ด์„ ๋‹จ์ผ ๋ฐฐ์—ด๋กœ ๋ณ‘ํ•ฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ฆ‰, BufferLine of _N_ ์—ด ๋Œ€์‹  _data _N_ CharData ์…€์˜ ๋ฐฐ์—ด์ด ์žˆ๊ณ  ์—ฌ๊ธฐ์„œ ๊ฐ CharData ๋Š” 4๊ฐœ์˜ ๋ฐฐ์—ด์ž…๋‹ˆ๋‹ค. _4*N_ ์š”์†Œ์˜ ๋ฐฐ์—ด์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ _N_ ๋ฐฐ์—ด์˜ ๊ฐœ์ฒด ์˜ค๋ฒ„ํ—ค๋“œ๋ฅผ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ์บ์‹œ ์ง€์—ญ์„ฑ์„ ํ–ฅ์ƒ์‹œํ‚ค๋ฏ€๋กœ ๋” ๋นจ๋ผ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋‹จ์ ์€ ์•ฝ๊ฐ„ ๋” ๋ณต์žกํ•˜๊ณ  ๋ชป์ƒ๊ธด ์ฝ”๋“œ์ด์ง€๋งŒ ๊ทธ๋งŒํ•œ ๊ฐ€์น˜๊ฐ€ ์žˆ๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

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

๊ณต๊ฐ„์„ ์ค„์ด๋Š” ๊ฒƒ ์™ธ์—๋„ ์…€๋‹น ๋‹ค์–‘ํ•œ ์š”์†Œ ์ˆ˜์˜ ์ด์ ์€ ์œ ์—ฐ์„ฑ์ด ์ฆ๊ฐ€ํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ถ”๊ฐ€ ์†์„ฑ(์˜ˆ: 24๋น„ํŠธ ์ƒ‰์ƒ), ํŠน์ • ์…€ ๋˜๋Š” ๋ฒ”์œ„์— ๋Œ€ํ•œ ์ฃผ์„, ๊ธ€๋ฆฌํ”„ ๋˜๋Š”
์ค‘์ฒฉ๋œ DOM ์š”์†Œ

@PerBothner ๋‹น์‹ ์˜ ์•„์ด๋””์–ด์— ๋Œ€ํ•œ Thx! ์˜ˆ, ์ด๋ฏธ ํฌ์ธํ„ฐ ์‚ฐ์ˆ ๋กœ ๋‹จ์ผ ๋ฐ€์ง‘ ๋ฐฐ์—ด ๋ ˆ์ด์•„์›ƒ์„ ํ…Œ์ŠคํŠธํ–ˆ์œผ๋ฉฐ ์ตœ๊ณ ์˜ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋ฅ ์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. ํฌ๊ธฐ ์กฐ์ •๊ณผ ๊ด€๋ จํ•˜์—ฌ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ ์ „์ฒด ๋ฉ”๋ชจ๋ฆฌ ์ฒญํฌ๋ฅผ ๋‹ค์‹œ ์ž‘์„ฑ(๋ณต์‚ฌ)ํ•˜๊ฑฐ๋‚˜ ๋” ํฐ ์ฒญํฌ๋กœ ๋น ๋ฅด๊ฒŒ ๋ณต์‚ฌํ•˜๊ณ  ๋ถ€๋ถ„์„ ์žฌ์ •๋ ฌํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๊ฝค ํŠน๊ธ‰์ž…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  imho๋Š” mem ์ ˆ์•ฝ์— ์˜ํ•ด ์ •๋‹นํ™”๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค(์œ„์— ๋‚˜์—ด๋œ ์ผ๋ถ€ ํ”Œ๋ ˆ์ด๊ทธ๋ผ์šด๋“œ PR์—์„œ ํ…Œ์ŠคํŠธ, ์ ˆ์•ฝ์€ ์ƒˆ๋กœ์šด ๋ฒ„ํผ ๋ผ์ธ ๊ตฌํ˜„๊ณผ ๋น„๊ตํ•˜์—ฌ ์•ฝ 10% ์ •๋„์˜€์Šต๋‹ˆ๋‹ค).

๋‘ ๋ฒˆ์งธ ์˜๊ฒฌ์— ๋Œ€ํ•ด - ๋ž˜ํ•‘๋œ ์ค„์„ ๋” ์‰ฝ๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ์ด๋ฏธ ๋…ผ์˜ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ง€๊ธˆ์€ ์ƒˆ๋กœ์šด ๋ฒ„ํผ ๋ ˆ์ด์•„์›ƒ์— ๋Œ€ํ•ด ํ–‰ X ์—ด ์ ‘๊ทผ ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•˜๊ณ  ๋จผ์ € ์™„๋ฃŒํ•˜๊ธฐ๋กœ ๊ฒฐ์ •ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋ฆฌํ”Œ๋กœ์šฐ ํฌ๊ธฐ ์กฐ์ • ๊ตฌํ˜„์„ ์ˆ˜ํ–‰ํ•˜๋ฉด ์ด ๋ฌธ์ œ๋ฅผ ๋‹ค์‹œ ํ•ด๊ฒฐํ•ด์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

๋ฒ„ํผ์— ์ถ”๊ฐ€ ํ•ญ๋ชฉ ์ถ”๊ฐ€: ํ˜„์žฌ ๋Œ€๋ถ€๋ถ„์˜ ๋‹ค๋ฅธ ํ„ฐ๋ฏธ๋„์ด ์ˆ˜ํ–‰ํ•˜๋Š” ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์ปค์„œ ์ง„ํ–‰์€ ๋ฐ์ดํ„ฐ๊ฐ€ ์–ด๋–ป๊ฒŒ ๋ฐฐ์น˜๋˜์–ด์•ผ ํ•˜๋Š”์ง€ pty/termios์˜ ์•„์ด๋””์–ด์™€ ํ˜ธํ™˜๋˜๋„๋ก ๋ณด์žฅํ•˜๋Š” wcwidth ์˜ํ•ด ๊ฒฐ์ •๋ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ์„œ๋กœ๊ฒŒ์ดํŠธ ์Œ ๋ฐ ๋ฌธ์ž ๊ฒฐํ•ฉ๊ณผ ๊ฐ™์€ ๊ฒƒ๋งŒ ๋ฒ„ํผ ์ˆ˜์ค€์—์„œ ์ฒ˜๋ฆฌํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ๋‹ค๋ฅธ "์ƒ์œ„ ์ˆ˜์ค€" ๊ฒฐํ•ฉ ๊ทœ์น™์€ ๋ Œ๋”๋Ÿฌ์˜ ์บ๋ฆญํ„ฐ ๊ฒฐํ•ฉ์ž๊ฐ€ ์ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(ํ˜„์žฌ ํ•ฉ์ž์— ๋Œ€ํ•ด https://github.com/xtermjs/xterm-addon-ligatures์—์„œ ์‚ฌ์šฉ). ์ดˆ๊ธฐ ๋ฒ„ํผ ์ˆ˜์ค€์—์„œ ์œ ๋‹ˆ์ฝ”๋“œ ์ž์†Œ๋ฅผ ์ง€์›ํ•˜๊ธฐ ์œ„ํ•ด PR์„ ์—ด์—ˆ์ง€๋งŒ ๋Œ€๋ถ€๋ถ„์˜ pty ๋ฐฑ์—”๋“œ์—๋Š” ์ด์— ๋Œ€ํ•œ ๊ฐœ๋…์ด ์—†๊ธฐ ๋•Œ๋ฌธ์—(์ „ํ˜€ ์กด์žฌํ•ฉ๋‹ˆ๊นŒ?) ์ด์ƒํ•œ char ๋Œ€๊ธฐ์—…์œผ๋กœ ๋๋‚  ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ทธ ๋‹จ๊ณ„์—์„œ๋Š” ์ด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์—†๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. . ์‹ค์ œ BIDI ์ง€์›๋„ ๋งˆ์ฐฌ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค. ์ปค์„œ/์…€ ์›€์ง์ž„์„ ๊ทธ๋Œ€๋กœ ์œ ์ง€ํ•˜๋ ค๋ฉด ๋ Œ๋”๋Ÿฌ ๋‹จ๊ณ„์—์„œ grapheme๊ณผ BIDI๊ฐ€ ๋” ์ž˜ ์ˆ˜ํ–‰๋œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

์…€์— ์—ฐ๊ฒฐ๋œ DOM ๋…ธ๋“œ์— ๋Œ€ํ•œ ์ง€์›์€ ์ •๋ง ํฅ๋ฏธ๋กญ๊ฒŒ ๋“ค๋ฆฝ๋‹ˆ๋‹ค. ์ €๋Š” ๊ทธ ์•„์ด๋””์–ด๊ฐ€ ์ข‹์Šต๋‹ˆ๋‹ค. ํ˜„์žฌ ๋‹ค๋ฅธ ๋ Œ๋”๋Ÿฌ ๋ฐฑ์—”๋“œ(DOM, ์บ”๋ฒ„์Šค 2D ๋ฐ ์ƒˆ๋กœ์šด ๋น›๋‚˜๋Š” webgl ๋ Œ๋”๋Ÿฌ)๊ฐ€ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ง์ ‘์ ์ธ ์ ‘๊ทผ ๋ฐฉ์‹์œผ๋กœ๋Š” ๋ถˆ๊ฐ€๋Šฅํ•˜์ง€๋งŒ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ง€์›๋˜์ง€ ์•Š๋Š” ์œ„์น˜์— ์˜ค๋ฒ„๋ ˆ์ด๋ฅผ ๋ฐฐ์น˜ํ•˜์—ฌ ๋ชจ๋“  ๋ Œ๋”๋Ÿฌ์— ๋Œ€ํ•ด ์ด๊ฒƒ์ด ์—ฌ์ „ํžˆ ๋‹ฌ์„ฑ๋  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค(DOM ๋ Œ๋”๋Ÿฌ๋งŒ ์ง์ ‘ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค). ์šฐ๋ฆฌ๋Š” ๋ฌผ๊ฑด๊ณผ ๊ทธ ํฌ๊ธฐ์™€ ๋ Œ๋”๋Ÿฌ๊ฐ€ ๋”๋Ÿฌ์šด ์ž‘์—…์„ ํ•  ์ˆ˜ ์žˆ์Œ์„ ์•Œ๋ฆฌ๊ธฐ ์œ„ํ•ด ๋ฒ„ํผ ์ˆ˜์ค€์—์„œ ์ผ์ข…์˜ API๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๋‚˜๋Š” ์ด๊ฒƒ์„ ๋ณ„๋„์˜ ๋ฌธ์ œ๋กœ ๋…ผ์˜/์ถ”์ ํ•ด์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

์ž์„ธํ•œ ๋‹ต๋ณ€ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

_"ํฌ๊ธฐ ์กฐ์ •๊ณผ ๊ด€๋ จํ•˜์—ฌ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ ์ „์ฒด ๋ฉ”๋ชจ๋ฆฌ ์ฒญํฌ๋ฅผ ๋‹ค์‹œ ์ž‘์„ฑ(๋ณต์‚ฌ)ํ•˜๊ฑฐ๋‚˜ ๋” ํฐ ์ฒญํฌ๋กœ ๋น ๋ฅด๊ฒŒ ๋ณต์‚ฌํ•˜๊ณ  ๋ถ€๋ถ„์„ ์žฌ์ •๋ ฌํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค."_

ํฌ๊ธฐ ์กฐ์ • ์‹œ _N_ ์š”์†Œ๊ฐ€ ์•„๋‹Œ _4*N_ ์š”์†Œ๋ฅผ ๋ณต์‚ฌํ•ด์•ผ ํ•œ๋‹ค๋Š” ๋œป์ž…๋‹ˆ๊นŒ?

๋ฐฐ์—ด์ด ๋…ผ๋ฆฌ์ (๋ž˜ํ•‘๋˜์ง€ ์•Š์€) ํ–‰์— ๋Œ€ํ•œ ๋ชจ๋“  ์…€์„ ํฌํ•จํ•˜๋Š” ๊ฒƒ์ด ํ•ฉ๋ฆฌ์ ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด 180์ž ํ–‰๊ณผ 80์—ด ๋„ˆ๋น„์˜ ํ„ฐ๋ฏธ๋„์„ ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ 3๊ฐœ์˜ BufferLine ์ธ์Šคํ„ด์Šค๊ฐ€ ๋ชจ๋‘ ๋™์ผํ•œ _4*180_-element _data ๋ฒ„ํผ๋ฅผ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๊ฐ BufferLine ์—๋Š” ์‹œ์ž‘ ์˜คํ”„์…‹๋„ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.

๊ธ€์Ž„, ๋‚˜๋Š” [cols] x [rows] x [needed single cell space] ์˜ํ•ด ๊ตฌ์ถ•๋œ ํ•˜๋‚˜์˜ ํฐ ๋ฐฐ์—ด์— ๋ชจ๋“  ๊ฒƒ์„ ๊ฐ€์ง€๊ณ  ์žˆ์—ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๊ธฐ๋ณธ์ ์œผ๋กœ ์—ฌ์ „ํžˆ ์ฃผ์–ด์ง„ ๋†’์ด์™€ ๋„ˆ๋น„๋กœ "์บ”๋ฒ„์Šค"๋กœ ์ž‘๋™ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์ •์ƒ์ ์ธ ์ž…๋ ฅ ํ๋ฆ„์— ๋Œ€ํ•ด ์‹ค์ œ๋กœ ๋ฉ”๋ชจ๋ฆฌ ํšจ์œจ์ ์ด๊ณ  ๋น ๋ฅด์ง€๋งŒ insertCell / deleteCell ๊ฐ€ ํ˜ธ์ถœ๋˜์ž๋งˆ์ž(ํฌ๊ธฐ ์กฐ์ •์œผ๋กœ ์ˆ˜ํ–‰๋จ) ์ž‘์—…์ด ๋ฐœ์ƒํ•˜๋Š” ์œ„์น˜ ๋’ค์— ์žˆ๋Š” ์ „์ฒด ๋ฉ”๋ชจ๋ฆฌ ์˜ฎ๊ฒจ์•ผ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ž‘์€ ์Šคํฌ๋กค๋ฐฑ(<10k)์˜ ๊ฒฝ์šฐ ์ด๊ฒƒ๋„ ๋ฌธ์ œ๊ฐ€ ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์‹ค์ œ๋กœ >100k ๋ผ์ธ์— ๋Œ€ํ•œ ์‡ผ์Šคํ† ํผ์ž…๋‹ˆ๋‹ค.
ํ˜„์žฌ ํ˜•์‹ํ™”๋œ ๋ฐฐ์—ด impl์€ ์—ฌ์ „ํžˆ โ€‹โ€‹์ด๋Ÿฌํ•œ ์ด๋™์„ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•˜์ง€๋งŒ ๋ฉ”๋ชจ๋ฆฌ ๋‚ด์šฉ์„ ์ค„ ๋๊นŒ์ง€ ์ด๋™ํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋˜๋ฏ€๋กœ ๋…์„ฑ์ด ๋œํ•ฉ๋‹ˆ๋‹ค.
๋น„์šฉ์ด ๋งŽ์ด ๋“œ๋Š” ์ด๋™์„ ํ”ผํ•˜๊ธฐ ์œ„ํ•ด ๋‹ค๋ฅธ ๋ ˆ์ด์•„์›ƒ์— ๋Œ€ํ•ด ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค. ๋ง๋„ ์•ˆ๋˜๋Š” ๋ฉ”๋ชจ๋ฆฌ ์ด๋™์„ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•œ ๊ธฐ๋ณธ ํ•„๋“œ๋Š” ์‹ค์ œ๋กœ ์Šคํฌ๋กค๋ฐฑ์„ "ํ•ซ ํ„ฐ๋ฏธ๋„ ํ–‰"(๊ฐ€์žฅ ์ตœ๊ทผ terminal.rows )์—์„œ ๋ถ„๋ฆฌํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ปค์„œ ์ ํ”„ ๋ฐ ์‚ฝ์ž…/์‚ญ์ œ์— ์˜ํ•ด ๋ณ€๊ฒฝ๋ฉ๋‹ˆ๋‹ค.

์—ฌ๋Ÿฌ ๋ฒ„ํผ ๋ผ์ธ ๊ฐ์ฒด๊ฐ€ ๊ธฐ๋ณธ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ณต์œ ํ•˜๋Š” ๊ฒƒ์€ ๋ž˜ํ•‘ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ํฅ๋ฏธ๋กœ์šด ์•„์ด๋””์–ด์ž…๋‹ˆ๋‹ค. ๋ช…์‹œ์ ์ธ ์ฐธ์กฐ ์ฒ˜๋ฆฌ ๋“ฑ์„ ๋„์ž…ํ•˜์ง€ ์•Š๊ณ  ์ด๊ฒƒ์ด ์–ด๋–ป๊ฒŒ ์•ˆ์ •์ ์œผ๋กœ ์ž‘๋™ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์•„์ง ํ™•์‹คํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ๋ฒ„์ „์—์„œ๋Š” ๋ช…์‹œ์  ๋ฉ”๋ชจ๋ฆฌ ์ฒ˜๋ฆฌ๋กœ ๋ชจ๋“  ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋ ค๊ณ  ํ–ˆ์ง€๋งŒ ref ์นด์šดํ„ฐ๋Š” ์‹ค์ œ ์‡ผ์Šคํ† ํผ์˜€์œผ๋ฉฐ GC ๋žœ๋“œ์—์„œ ์ž˜๋ชป๋˜์—ˆ๋‹ค๊ณ  ๋Š๊ผˆ์Šต๋‹ˆ๋‹ค. (ํ”„๋ฆฌ๋ฏธํ‹ฐ๋ธŒ๋Š” #1633 ์ฐธ์กฐ)

ํŽธ์ง‘: Btw ๋ช…์‹œ์  ๋ฉ”๋ชจ๋ฆฌ ์ฒ˜๋ฆฌ๋Š” ํ˜„์žฌ์˜ "๋ผ์ธ๋‹น ๋ฉ”๋ชจ๋ฆฌ" ์ ‘๊ทผ ๋ฐฉ์‹๊ณผ ๋™๋“ฑํ–ˆ์Šต๋‹ˆ๋‹ค. ๋” ๋‚˜์€ ์บ์‹œ ์ง€์—ญ์„ฑ์œผ๋กœ ์ธํ•ด ๋” ๋‚˜์€ ์„ฑ๋Šฅ์„ ๊ธฐ๋Œ€ํ–ˆ๋Š”๋ฐ, ์•ฝ๊ฐ„ ๋” ๋งŽ์€ ๊ฒฝํ—˜์น˜๊ฐ€ ๋จนํžŒ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. JS ์ถ”์ƒํ™”์—์„œ mem ์ฒ˜๋ฆฌ.

์…€์— ์—ฐ๊ฒฐ๋œ DOM ๋…ธ๋“œ์— ๋Œ€ํ•œ ์ง€์›์€ ์ •๋ง ํฅ๋ฏธ๋กญ๊ฒŒ ๋“ค๋ฆฝ๋‹ˆ๋‹ค. ์ €๋Š” ๊ทธ ์•„์ด๋””์–ด๊ฐ€ ์ข‹์Šต๋‹ˆ๋‹ค. ํ˜„์žฌ ๋‹ค๋ฅธ ๋ Œ๋”๋Ÿฌ ๋ฐฑ์—”๋“œ(DOM, ์บ”๋ฒ„์Šค 2D ๋ฐ ์ƒˆ๋กœ์šด ๋น›๋‚˜๋Š” webgl ๋ Œ๋”๋Ÿฌ)๊ฐ€ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ง์ ‘์ ์ธ ์ ‘๊ทผ ๋ฐฉ์‹์œผ๋กœ๋Š” ๋ถˆ๊ฐ€๋Šฅํ•˜์ง€๋งŒ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ง€์›๋˜์ง€ ์•Š๋Š” ์œ„์น˜์— ์˜ค๋ฒ„๋ ˆ์ด๋ฅผ ๋ฐฐ์น˜ํ•˜์—ฌ ๋ชจ๋“  ๋ Œ๋”๋Ÿฌ์— ๋Œ€ํ•ด ์ด๊ฒƒ์ด ์—ฌ์ „ํžˆ ๋‹ฌ์„ฑ๋  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค(DOM ๋ Œ๋”๋Ÿฌ๋งŒ ์ง์ ‘ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค).

์ฃผ์ œ์—์„œ ์กฐ๊ธˆ ๋ฒ—์–ด๋‚˜์ง€๋งŒ ๊ฒฐ๊ตญ ์บ”๋ฒ„์Šค ๋ Œ๋” ๋ ˆ์ด์–ด์™€ ์œ ์‚ฌํ•˜๊ฒŒ ์ž‘๋™ํ•˜๋Š” ๋ทฐํฌํŠธ ๋‚ด์˜ ์…€๊ณผ ์—ฐ๊ฒฐ๋œ DOM ๋…ธ๋“œ๋ฅผ ๊ฐ–๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡๊ฒŒ ํ•˜๋ฉด ์†Œ๋น„์ž๋Š” HTML๊ณผ CSS๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์…€์„ "์žฅ์‹"ํ•  ์ˆ˜ ์žˆ๊ณ  ์บ”๋ฒ„์Šค API์— ๋“ค์–ด๊ฐˆ ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

๋ฐฐ์—ด์ด ๋…ผ๋ฆฌ์ (๋ž˜ํ•‘๋˜์ง€ ์•Š์€) ํ–‰์— ๋Œ€ํ•œ ๋ชจ๋“  ์…€์„ ํฌํ•จํ•˜๋Š” ๊ฒƒ์ด ํ•ฉ๋ฆฌ์ ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด 180์ž ํ–‰๊ณผ 80์—ด ๋„ˆ๋น„์˜ ํ„ฐ๋ฏธ๋„์„ ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ 3๊ฐœ์˜ BufferLine ์ธ์Šคํ„ด์Šค๊ฐ€ ๋ชจ๋‘ ๋™์ผํ•œ 4*180 ์š”์†Œ _data ๋ฒ„ํผ๋ฅผ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๊ฐ BufferLine์—๋Š” ์‹œ์ž‘ ์˜คํ”„์…‹๋„ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.

์œ„์—์„œ ์–ธ๊ธ‰ํ•œ ๋ฆฌํ”Œ๋กœ์šฐ์— ๋Œ€ํ•œ ๊ณ„ํš์€ https://github.com/xtermjs/xterm.js/issues/622#issuecomment -375403572์— ์บก์ฒ˜๋˜์–ด

์กฐ๋ฐ€ํ•œ ๋ฐฐ์—ด ์ ‘๊ทผ ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์šฐ๋ฆฌ๊ฐ€ ๋ณผ ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ผ ์ˆ˜ ์žˆ์ง€๋งŒ ์ด๋Ÿฌํ•œ ๋ฐฐ์—ด์—์„œ ์ค„ ๋ฐ”๊ฟˆ๋˜์ง€ ์•Š์€ ์ค„ ๋ฐ”๊ฟˆ์„ ๊ด€๋ฆฌํ•˜๋Š” ๋ฐ ์ถ”๊ฐ€ ์˜ค๋ฒ„ํ—ค๋“œ์™€ ํ–‰์ด ์Šคํฌ๋กค๋ฐฑ ๋ฒ„ํผ ๊ทธ๋Ÿผ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  #791์ด ์™„๋ฃŒ๋˜๊ณ  #622๋ฅผ ๋ณผ ๋•Œ๊นŒ์ง€ ์ด๋Ÿฌํ•œ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์กฐ์‚ฌํ•ด์„œ๋Š” ์•ˆ ๋œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

PR #1796์„ ์‚ฌ์šฉํ•˜๋ฉด ํŒŒ์„œ๋Š” ๋‹ค๋ฅธ ์ž…๋ ฅ ์ธ์ฝ”๋”ฉ์— ๋Œ€ํ•œ ์„œ๋ฒ„์˜ ์ถ”๊ฐ€ ์ตœ์ ํ™”๋ฅผ ์œ„ํ•œ ๋ฌธ์„ ์—ฌ๋Š” ํ˜•์‹ํ™”๋œ ๋ฐฐ์—ด ์ง€์›์„ ๋ฐ›์Šต๋‹ˆ๋‹ค.

์ง€๊ธˆ์€ JS ๋ฌธ์ž์—ด๋กœ ์•ž๋’ค๋กœ ์‰ฝ๊ฒŒ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— Uint16Array ์‚ฌ์šฉํ•˜๊ธฐ๋กœ ๊ฒฐ์ •ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ๊ฒŒ์ž„์„ UCS2/UTF16์œผ๋กœ ์ œํ•œํ•˜๋Š” ๋ฐ˜๋ฉด ํ˜„์žฌ ๋ฒ„์ „์˜ ํŒŒ์„œ๋Š” UTF32๋„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(UTF8์€ ์ง€์›๋˜์ง€ ์•Š์Œ). ์œ ํ˜•์ด ์ง€์ •๋œ ๋ฐฐ์—ด ๊ธฐ๋ฐ˜ ํ„ฐ๋ฏธ๋„ ๋ฒ„ํผ๋Š” ํ˜„์žฌ UTF32์šฉ์œผ๋กœ ๋ ˆ์ด์•„์›ƒ๋˜์–ด ์žˆ์œผ๋ฉฐ UTF16 --> UTF32 ๋ณ€ํ™˜์€ InputHandler.print ์—์„œ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์—์„œ ๋ช‡ ๊ฐ€์ง€ ๋ฐฉํ–ฅ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

  • ๋ชจ๋“  UTF16์„ ๋งŒ๋“œ์‹ญ์‹œ์˜ค. ๋”ฐ๋ผ์„œ ํ„ฐ๋ฏธ๋„ ๋ฒ„ํผ๋„ UTF16์œผ๋กœ ๋ฐ”๊พธ์‹ญ์‹œ์˜ค.
    ์˜ˆ, ์—ฌ๊ธฐ์—์„œ ์–ด๋Š ๊ธธ์„ ํƒํ• ์ง€ ์•„์ง ์ •ํ•˜์ง€ ์•Š์•˜์ง€๋งŒ ์—ฌ๋Ÿฌ ๋ฒ„ํผ ๋ ˆ์ด์•„์›ƒ์„ ํ…Œ์ŠคํŠธํ•˜๊ณ  32๋น„ํŠธ ์ˆซ์ž๋Š” ์‹ค์ œ ๋ฌธ์ž ์ฝ”๋“œ + wcwidth + ๊ฐ€๋Šฅํ•œ ๊ฒฐํ•ฉ ์˜ค๋ฒ„ํ”Œ๋กœ(์™„์ „ํžˆ ๋‹ค๋ฅด๊ฒŒ ์ฒ˜๋ฆฌ๋จ)๋ฅผ ์ €์žฅํ•  ์ˆ˜ ์žˆ๋Š” ์ถฉ๋ถ„ํ•œ ๊ณต๊ฐ„์„ ์ œ๊ณตํ•˜์ง€๋งŒ 16๋น„ํŠธ๋Š” ๊ทธ๋ ‡๊ฒŒ ํ•  ์ˆ˜ ์—†๋‹ค๋Š” ๊ฒฐ๋ก ์— ๋„๋‹ฌํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ท€์ค‘ํ•œ charcode ๋น„ํŠธ๋ฅผ ํฌ์ƒํ•˜์ง€ ์•Š๊ณ . wcwidth๋Š” ์œ ๋‹ˆ์ฝ”๋“œ ์ฝ”๋“œ ํฌ์ธํŠธ์—์„œ ์ž‘๋™ํ•˜๊ธฐ ๋•Œ๋ฌธ์— UTF16 ๋ฒ„ํผ๋ฅผ ์‚ฌ์šฉํ•˜๋”๋ผ๋„ ์—ฌ์ „ํžˆ UTF32 ๋ณ€ํ™˜์„ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ UTF16 ๊ธฐ๋ฐ˜ ๋ฒ„ํผ๋Š” ๋‚ฎ์€ ๋ฌธ์ž ์ฝ”๋“œ์— ๋Œ€ํ•ด ๋” ๋งŽ์€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ ˆ์•ฝํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ์‹ค์ œ๋กœ BMP ํ‰๋ฉด ๋ฌธ์ž ์ฝ”๋“œ๋ณด๋‹ค ๋†’์€ ๊ฒฝ์šฐ๋Š” ๊ฑฐ์˜ ๋ฐœ์ƒํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์•„์ง ์กฐ์‚ฌ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
  • ํŒŒ์„œ๋ฅผ UTF32๋กœ ๋งŒ๋“ค๊ธฐ
    ์•„์ฃผ ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค. ๋ชจ๋“  ์œ ํ˜•์ด ์ง€์ •๋œ ๋ฐฐ์—ด์„ 32๋น„ํŠธ ๋ณ€ํ˜•์œผ๋กœ ๋ฐ”๊พธ๋ฉด ๋ฉ๋‹ˆ๋‹ค. ๋‹จ์  - UTF16์—์„œ UTF32๋กœ์˜ ๋ณ€ํ™˜์€ ์‚ฌ์ „์— ์ˆ˜ํ–‰๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, ๋ฌธ์ž ์ฝ”๋“œ > 255๋กœ ๊ตฌ์„ฑ๋˜์ง€ ์•Š๋Š” ์ด์Šค์ผ€์ดํ”„ ์‹œํ€€์Šค๋„ ํฌํ•จํ•˜์—ฌ ์ „์ฒด ์ž…๋ ฅ์ด ๋ณ€ํ™˜๋ฉ๋‹ˆ๋‹ค.
  • wcwidth UTF16 ํ˜ธํ™˜ ๊ฐ€๋Šฅ
    ์˜ˆ, UTF16์ด ํ„ฐ๋ฏธ๋„ ๋ฒ„ํผ์— ๋” ์ ํ•ฉํ•œ ๊ฒƒ์œผ๋กœ ํŒ๋ช…๋˜๋ฉด ์ด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

UTF8 ์ •๋ณด: ํŒŒ์„œ๋Š” ํ˜„์žฌ ๊ธฐ๋ณธ UTF8 ์‹œํ€€์Šค๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์ฃผ๋กœ ์ค‘๊ฐ„ ๋ฌธ์ž๊ฐ€ C1 ์ œ์–ด ๋ฌธ์ž์™€ ์ถฉ๋Œํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋˜ํ•œ UTF8์€ ์ถ”๊ฐ€ ์ค‘๊ฐ„ ์ƒํƒœ์™€ ํ•จ๊ป˜ ์ ์ ˆํ•œ ์ŠคํŠธ๋ฆผ ์ฒ˜๋ฆฌ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๋ถˆ์พŒํ•˜๊ณ  imho๊ฐ€ ํŒŒ์„œ์— ์ถ”๊ฐ€๋˜์–ด์„œ๋Š” ์•ˆ ๋ฉ๋‹ˆ๋‹ค. UTF8์€ ์‚ฌ์ „์— ๋” ์ž˜ ์ฒ˜๋ฆฌ๋  ๊ฒƒ์ด๋ฉฐ ์•„๋งˆ๋„ ๋ชจ๋“  ๊ณณ์—์„œ ๋ณด๋‹ค ์‰ฌ์šด ์ฝ”๋“œ ํฌ์ธํŠธ ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•ด UTF32๋กœ์˜ ๋ณ€ํ™˜ ๊ถŒํ•œ์ด ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ฐ€๋Šฅํ•œ UTF8 ์ž…๋ ฅ ์ธ์ฝ”๋”ฉ ๋ฐ ๋‚ด๋ถ€ ๋ฒ„ํผ ๋ ˆ์ด์•„์›ƒ๊ณผ ๊ด€๋ จํ•˜์—ฌ ๋Œ€๋žต์ ์ธ ํ…Œ์ŠคํŠธ๋ฅผ ์ˆ˜ํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ „์ฒด ๋Ÿฐํƒ€์ž„์— ๋Œ€ํ•œ ์บ”๋ฒ„์Šค ๋ Œ๋”๋Ÿฌ์˜ ํ›จ์”ฌ ๋” ๋†’์€ ์˜ํ–ฅ์„ ๋ฐฐ์ œํ•˜๊ธฐ ์œ„ํ•ด ๊ณง ์ถœ์‹œ๋  webgl ๋ Œ๋”๋Ÿฌ๋กœ ์ด๋ฅผ ์ˆ˜ํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‚ด ls -lR /usr/lib ๋ฒค์น˜๋งˆํฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ํ˜„์žฌ ๋งˆ์Šคํ„ฐ + webgl ๋ Œ๋”๋Ÿฌ:
    grafik

  • ๋†€์ดํ„ฐ ๋ถ„๊ธฐ๋Š” #1796, #1811 ๋ฐ webgl ๋ Œ๋”๋Ÿฌ์˜ ์ผ๋ถ€๋ฅผ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค.
    grafik

ํ”Œ๋ ˆ์ด๊ทธ๋ผ์šด๋“œ ๋ธŒ๋žœ์น˜๋Š” ๊ตฌ๋ฌธ ๋ถ„์„ ๋ฐ ์ €์žฅ์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์ „์— UTF8์—์„œ UTF32๋กœ ์ดˆ๊ธฐ ๋ณ€ํ™˜์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค(๋ณ€ํ™˜ ์ถ”๊ฐ€ ~ 30ms). ์†๋„ ํ–ฅ์ƒ์€ ์ฃผ๋กœ ์ž…๋ ฅ ํ๋ฆ„ ์ค‘ 2๊ฐ€์ง€ ํ•ซ ๊ธฐ๋Šฅ์ธ EscapeSequenceParser.parse (120ms ๋Œ€ 35ms) ๋ฐ InputHandler.print (350ms ๋Œ€ 75ms)์— ์˜ํ•ด ์–ป์Šต๋‹ˆ๋‹ค. ๋‘˜ ๋‹ค .charCodeAt ํ˜ธ์ถœ์„ ์ €์žฅํ•˜์—ฌ ํ˜•์‹ํ™”๋œ ๋ฐฐ์—ด ์Šค์œ„์น˜์—์„œ ๋งŽ์€ ์ด์ ์„ ์–ป์Šต๋‹ˆ๋‹ค.
๋˜ํ•œ ์ด ๊ฒฐ๊ณผ๋ฅผ UTF16 ์ค‘๊ฐ„ ์œ ํ˜• ๋ฐฐ์—ด๊ณผ ๋น„๊ตํ–ˆ์Šต๋‹ˆ๋‹ค. EscapeSequenceParser.parse ๋Š” ์•ฝ๊ฐ„ ๋” ๋น ๋ฅด์ง€๋งŒ(~ 25ms) InputHandler.print ๋Š” wcwidth ์—์„œ ํ•„์š”ํ•œ ๋Œ€๋ฆฌ ์Œ ๋ฐ ์ฝ”๋“œ ํฌ์ธํŠธ ์กฐํšŒ๋กœ ์ธํ•ด ๋’ค์ณ์ง‘๋‹ˆ๋‹ค
๋˜ํ•œ ๋‚˜๋Š” ์ด๋ฏธ ์‹œ์Šคํ…œ์ด ls ๋ฐ์ดํ„ฐ๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๋Š” ํ•œ๊ณ„์— ์ด๋ฅด๋ €์Šต๋‹ˆ๋‹ค(SSD๊ฐ€ ์žˆ๋Š” i7) - ํš๋“ํ•œ ์†๋„ ํ–ฅ์ƒ์€ ์‹คํ–‰์„ ๋” ๋น ๋ฅด๊ฒŒ ๋งŒ๋“œ๋Š” ๋Œ€์‹  ์œ ํœด ์‹œ๊ฐ„์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

์š”์•ฝ:
Imho ์šฐ๋ฆฌ๊ฐ€ ์–ป์„ ์ˆ˜ ์žˆ๋Š” ๊ฐ€์žฅ ๋น ๋ฅธ ์ž…๋ ฅ ์ฒ˜๋ฆฌ๋Š” ๋ฒ„ํผ ํ‘œํ˜„์„ ์œ„ํ•œ UTF8 ์ „์†ก + UTF32์˜ ํ˜ผํ•ฉ์ž…๋‹ˆ๋‹ค. UTF8 ์ „์†ก์€ ์ผ๋ฐ˜์ ์ธ ํ„ฐ๋ฏธ๋„ ์ž…๋ ฅ์— ๋Œ€ํ•ด ์ตœ๊ณ ์˜ ๋ฐ”์ดํŠธ ํŒฉ๋ฅ ์„ ๊ฐ€์ง€๋ฉฐ ์ตœ๋Œ€ Terminal.write ๋ฒ„ํผ์˜ ์—ฌ๋Ÿฌ ๋ ˆ์ด์–ด๋ฅผ ํ†ตํ•ด pty์—์„œ ๋ง๋„ ์•ˆ๋˜๋Š” ๋ณ€ํ™˜์„ ์ œ๊ฑฐํ•˜์ง€๋งŒ UTF32 ๊ธฐ๋ฐ˜ ๋ฒ„ํผ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๋งค์šฐ ๋น ๋ฅด๊ฒŒ ์ €์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ›„์ž๋Š” UTF16๋ณด๋‹ค ์•ฝ๊ฐ„ ๋” ๋†’์€ ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์„ ์ œ๊ณตํ•˜๋Š” ๋ฐ˜๋ฉด UTF16์€ ๋” ๋งŽ์€ ๊ฐ„์ ‘ ์ฐธ์กฐ๊ฐ€ ํฌํ•จ๋œ ๋” ๋ณต์žกํ•œ ๋ฌธ์ž ์ฒ˜๋ฆฌ๋กœ ์ธํ•ด ์•ฝ๊ฐ„ ๋Š๋ฆฝ๋‹ˆ๋‹ค.

๊ฒฐ๋ก :
์ง€๊ธˆ์€ UTF32 ๊ธฐ๋ฐ˜ ๋ฒ„ํผ ๋ ˆ์ด์•„์›ƒ์„ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ UTF8 ์ž…๋ ฅ ์ธ์ฝ”๋”ฉ์œผ๋กœ ์ „ํ™˜ํ•˜๋Š” ๊ฒƒ์„ ๊ณ ๋ คํ•ด์•ผ ํ•˜์ง€๋งŒ ํ†ตํ•ฉ์ž์— ๋Œ€ํ•œ API ๋ณ€๊ฒฝ ๋ฐ ์˜๋ฏธ์— ๋Œ€ํ•ด ์ข€ ๋” ์ƒ๊ฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค(electron์˜ ipc ๋ฉ”์ปค๋‹ˆ์ฆ˜์ด BASE64 ์ธ์ฝ”๋”ฉ ๋ฐ JSON ๋ž˜ํ•‘ ์—†์ด ๋ฐ”์ด๋„ˆ๋ฆฌ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์—†๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ž„).

ํ–ฅํ›„ ํŠธ๋ฃจ ์ปฌ๋Ÿฌ ์ง€์›์„ ์œ„ํ•œ ๋ฒ„ํผ ๋ ˆ์ด์•„์›ƒ:

ํ˜„์žฌ ํ˜•์‹ํ™”๋œ ๋ฐฐ์—ด ๊ธฐ๋ฐ˜ ๋ฒ„ํผ ๋ ˆ์ด์•„์›ƒ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค(ํ•˜๋‚˜์˜ ์…€).

|    uint32_t    |    uint32_t    |    uint32_t    |
|      attrs     |    codepoint   |     wcwidth    |

์—ฌ๊ธฐ์„œ attrs ์—๋Š” ํ•„์š”ํ•œ ๋ชจ๋“  ํ”Œ๋ž˜๊ทธ + 9๋น„ํŠธ ๊ธฐ๋ฐ˜ FG ๋ฐ BG ์ƒ‰์ƒ์ด ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. codepoint ๋Š” 21๋น„ํŠธ(UTF32์˜ ๊ฒฝ์šฐ ์ตœ๋Œ€ 0x10FFFF) + 1๋น„ํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฌธ์ž๋ฅผ ๊ฒฐํ•ฉํ•˜๊ณ  wcwidth 2๋น„ํŠธ(0-2 ๋ฒ”์œ„)๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

์•„์ด๋””์–ด๋Š” ์ถ”๊ฐ€ RGB ๊ฐ’์„ ์œ„ํ•œ ๊ณต๊ฐ„์„ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ๋น„ํŠธ๋ฅผ ๋” ๋‚˜์€ ํŒฉ๋ฅ ๋กœ ์žฌ๋ฐฐ์—ดํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

  • wcwidth ๋ฅผ codepoint ์˜ ์‚ฌ์šฉ๋˜์ง€ ์•Š์€ ์ƒ์œ„ โ€‹โ€‹๋น„ํŠธ์— ๋„ฃ์Šต๋‹ˆ๋‹ค.
  • ์†์„ฑ์„ 32๋น„ํŠธ์˜ FG ๋ฐ BG ๊ทธ๋ฃน์œผ๋กœ ๋ถ„ํ• ํ•˜๊ณ  ํ”Œ๋ž˜๊ทธ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๋น„ํŠธ์— ๋ฐฐํฌํ•ฉ๋‹ˆ๋‹ค.
|             uint32_t             |        uint32_t         |        uint32_t         |
|              content             |            FG           |            BG           |
| comb(1) wcwidth(2) codepoint(21) | flags(8) R(8) G(8) B(8) | flags(8) R(8) G(8) B(8) |

์ด ์ ‘๊ทผ ๋ฐฉ์‹์˜ ์žฅ์ ์€ ํ•˜๋‚˜์˜ ์ธ๋ฑ์Šค ์•ก์„ธ์Šค ๋ฐ ์ตœ๋Œ€๊ฐ’์œผ๋กœ ๋ชจ๋“  ๊ฐ’์— ๋น„๊ต์  ์ €๋ ดํ•˜๊ฒŒ ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. 2๋น„ํŠธ ์—ฐ์‚ฐ(๋ฐ/๋˜๋Š” + ์‹œํ”„ํŠธ).

๋ฉ”๋ชจ๋ฆฌ ํ’‹ํ”„๋ฆฐํŠธ๋Š” ํ˜„์žฌ ๋ณ€ํ˜•์— ๋Œ€ํ•ด ์•ˆ์ •์ ์ด์ง€๋งŒ ์—ฌ์ „ํžˆ ์…€๋‹น 12๋ฐ”์ดํŠธ๋กœ ์ƒ๋‹นํžˆ ๋†’์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ UTF16 ๋ฐ attr ๊ฐ„์ ‘์œผ๋กœ ์ „ํ™˜ํ•˜์—ฌ ์ผ๋ถ€ ๋Ÿฐํƒ€์ž„์„ ํฌ์ƒํ•˜์—ฌ ์ถ”๊ฐ€๋กœ ์ตœ์ ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

|        uint16_t        |              uint16_t               |
|    BMP codepoint(16)   | comb(1) wcwidth(2) attr pointer(13) |

์ด์ œ ์šฐ๋ฆฌ๋Š” ์…€๋‹น 4๋ฐ”์ดํŠธ + ์†์„ฑ์„ ์œ„ํ•œ ์•ฝ๊ฐ„์˜ ๊ณต๊ฐ„์œผ๋กœ ์ค„์—ˆ์Šต๋‹ˆ๋‹ค. ์ด์ œ ์†์„ฑ์€ ๋‹ค๋ฅธ ์…€์—๋„ ์žฌํ™œ์šฉ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์•ผ ๋ฏธ์…˜ ์™„์ˆ˜! - ์Œ, ์ž ์‹œ๋งŒ...

๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์„ ๋น„๊ตํ•˜๋ฉด ๋‘ ๋ฒˆ์งธ ์ ‘๊ทผ ๋ฐฉ์‹์ด ํ™•์‹คํžˆ ์œ ๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ๋Ÿฐํƒ€์ž„์˜ ๊ฒฝ์šฐ ๋Ÿฐํƒ€์ž„์„ ํฌ๊ฒŒ ์ฆ๊ฐ€์‹œํ‚ค๋Š” ์„ธ ๊ฐ€์ง€ ์ฃผ์š” ์š”์ธ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

  • attr ๊ฐ„์ ‘ ์ฐธ์กฐ
    attr ํฌ์ธํ„ฐ๋Š” ๋‹ค๋ฅธ ๋ฐ์ดํ„ฐ ์ปจํ…Œ์ด๋„ˆ์— ๋Œ€ํ•œ ํ•˜๋‚˜์˜ ์ถ”๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ ์กฐํšŒ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
  • ์†์„ฑ ์ผ์น˜
    ๋‘ ๋ฒˆ์งธ ์ ‘๊ทผ ๋ฐฉ์‹์œผ๋กœ ๊ณต๊ฐ„์„ ์‹ค์ œ๋กœ ์ ˆ์•ฝํ•˜๋ ค๋ฉด ์ฃผ์–ด์ง„ ์†์„ฑ์„ ์ด๋ฏธ ์ €์žฅ๋œ ์†์„ฑ๊ณผ ์ผ์น˜์‹œ์ผœ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์„ฑ๊ฐ€์‹  ์ž‘์—…์ž…๋‹ˆ๋‹ค. ๋‹จ์ˆœํžˆ ๊ธฐ์กด์˜ ๋ชจ๋“  ๊ฐ’์„ ์‚ดํŽด๋ณด๋Š” ์ง์ ‘์ ์ธ ์ ‘๊ทผ ๋ฐฉ์‹์€ ์ €์žฅ๋œ n๊ฐœ์˜ ์†์„ฑ์— ๋Œ€ํ•ด O(n)์— ์žˆ์Šต๋‹ˆ๋‹ค. ๋‚ด RB ํŠธ๋ฆฌ ์‹คํ—˜์€ ์—ฌ์ „ํžˆ โ€‹โ€‹O(log n)์— ์žˆ๋Š” ๋™์•ˆ ๋ฉ”๋ชจ๋ฆฌ ์ด์ ์ด ๊ฑฐ์˜ ์—†์ด ์ข…๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. O(1)์„ ์‚ฌ์šฉํ•œ 32๋น„ํŠธ ์ ‘๊ทผ ๋ฐฉ์‹์˜ ์ธ๋ฑ์Šค ์•ก์„ธ์Šค. ๋˜ํ•œ ํŠธ๋ฆฌ๋Š” ์ €์žฅ๋œ ๋ช‡ ๊ฐ€์ง€ ์š”์†Œ์— ๋Œ€ํ•ด ๋” ๋‚˜์œ ๋Ÿฐํƒ€์ž„์„ ๊ฐ–์Šต๋‹ˆ๋‹ค(๋‚ด RB ํŠธ๋ฆฌ impl๋กœ ์•ฝ 100๊ฐœ ํ•ญ๋ชฉ ์ •๋„๋ฅผ ์ง€๋ถˆํ•ฉ๋‹ˆ๋‹ค).
  • UTF16 ์„œ๋กœ๊ฒŒ์ดํŠธ ํŽ˜์–ด๋ง
    16๋น„ํŠธ ํ˜•์‹ ๋ฐฐ์—ด์„ ์‚ฌ์šฉํ•˜๋ฉด ์ฝ”๋“œํฌ์ธํŠธ์— ๋Œ€ํ•ด UTF16์œผ๋กœ ์ €ํ•˜๋˜์–ด์•ผ ํ•˜๋ฉฐ, ์ด๋Š” ๋Ÿฐํƒ€์ž„ ํŒจ๋„ํ‹ฐ๋„ ๋„์ž…ํ–ˆ์Šต๋‹ˆ๋‹ค(์œ„ ์ฃผ์„์— ์„ค๋ช…๋จ). BMP๋ณด๋‹ค ๋†’์€ ์ฝ”๋“œ ํฌ์ธํŠธ๋Š” ๊ฑฐ์˜ ๋ฐœ์ƒํ•˜์ง€ ์•Š์ง€๋งŒ ์ฝ”๋“œ ํฌ์ธํŠธ๊ฐ€ ๋Œ€๋ฆฌ ์Œ์„ ํ˜•์„ฑํ•˜๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•˜๋Š” ๊ฒƒ๋งŒ์œผ๋กœ๋„ ~ 50ms๊ฐ€ ์ถ”๊ฐ€๋ฉ๋‹ˆ๋‹ค.

๋‘ ๋ฒˆ์งธ ์ ‘๊ทผ ๋ฐฉ์‹์˜ ์„น์‹œํ•จ์€ ์ถ”๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ ์ ˆ์•ฝ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ˆ˜์ •๋œ BufferLine ๊ตฌํ˜„์„ ์‚ฌ์šฉํ•˜์—ฌ ๋†€์ดํ„ฐ ๋ถ„๊ธฐ(์œ„ ์ฃผ์„ ์ฐธ์กฐ)๋กœ ํ…Œ์ŠคํŠธํ–ˆ์Šต๋‹ˆ๋‹ค.

grafik

์˜ˆ, ํŒŒ์„œ์—์„œ UTF8 + ํ˜•์‹ํ™”๋œ ๋ฐฐ์—ด๋กœ ๋ณ€๊ฒฝํ•˜๊ธฐ ์ „์— ์‹œ์ž‘ํ•œ ์œ„์น˜๋กœ ๋Œ์•„๊ฐ‘๋‹ˆ๋‹ค. ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์€ ~ 1.5MB์—์„œ ~ 0.7MB๋กœ ๋–จ์–ด์กŒ์Šต๋‹ˆ๋‹ค(87์…€ ๋ฐ 1000์ค„ ์Šคํฌ๋กค๋ฐฑ์ด ์žˆ๋Š” ๋ฐ๋ชจ ์•ฑ).

์—ฌ๊ธฐ์„œ๋ถ€ํ„ฐ๋Š” ๋ฉ”๋ชจ๋ฆฌ ์ ˆ์•ฝ๊ณผ ์†๋„์˜ ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ์ด๋ฏธ js ๋ฐฐ์—ด์—์„œ ์œ ํ˜•์ด ์ง€์ •๋œ ๋ฐฐ์—ด๋กœ ์ „ํ™˜ํ•˜์—ฌ ๋งŽ์€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ ˆ์•ฝํ–ˆ์œผ๋ฏ€๋กœ(C++ ํž™์˜ ๊ฒฝ์šฐ ~ 5.6MB์—์„œ ~ 1.5MB๋กœ ๊ฐ์†Œํ•˜๊ณ  ์œ ๋…ํ•œ JS ํž™ ๋™์ž‘ ๋ฐ GC๋ฅผ ์ฐจ๋‹จํ•จ) ๋” ๋น ๋ฅธ ๋ณ€ํ˜•์œผ๋กœ ์—ฌ๊ธฐ์— ๊ฐ€์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ์ด ๋‹ค์‹œ ์‹œ๊ธ‰ํ•œ ๋ฌธ์ œ๊ฐ€ ๋˜๋”๋ผ๋„ ์—ฌ๊ธฐ์˜ ๋‘ ๋ฒˆ์งธ ์ ‘๊ทผ ๋ฐฉ์‹์—์„œ ์„ค๋ช…ํ•œ ๋Œ€๋กœ ๋” ์ปดํŒฉํŠธํ•œ ๋ฒ„ํผ ๋ ˆ์ด์•„์›ƒ์œผ๋กœ ์ „ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

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

๊ทธ๋Ÿผ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ , ๋‚˜๋Š” ๋‹น์‹ ์˜ ์—ฐ์Šต์—์„œ ์ฝ๊ณ  ๋ฐฐ์šฐ๋Š” ๊ฒƒ์„ ์ •๋ง๋กœ ์ฆ๊ธฐ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์•„์ฃผ ์ž์„ธํ•˜๊ฒŒ ๊ณต์œ ํ•ด ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค!

@mofux ์˜ˆ
๊ทธ๋ฆฌ๊ณ  32๋น„ํŠธ ๋ ˆ์ด์•„์›ƒ์€ ๋Œ€๋ถ€๋ถ„ ํ”Œ๋žซ ๋ฉ”๋ชจ๋ฆฌ(๋ฌธ์ž ๊ฒฐํ•ฉ์—๋งŒ ๊ฐ„์ ‘ ์ฐธ์กฐ๊ฐ€ ํ•„์š”ํ•จ)์ด๊ธฐ ๋•Œ๋ฌธ์— ๋” ๋งŽ์€ ์ตœ์ ํ™”๊ฐ€ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค(๋˜ํ•œ #1811์˜ ์ผ๋ถ€, ๋ Œ๋”๋Ÿฌ์— ๋Œ€ํ•ด ์•„์ง ํ…Œ์ŠคํŠธ๋˜์ง€ ์•Š์Œ).

attr ๊ฐœ์ฒด์— ๋Œ€ํ•œ ๊ฐ„์ ‘ ์ง€์ •์˜ ํ•œ ๊ฐ€์ง€ ํฐ ์ด์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ํ›จ์”ฌ ๋” ํ™•์žฅ ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ฃผ์„, ๊ธ€๋ฆฌํ”„ ๋˜๋Š” ์‚ฌ์šฉ์ž ์ •์˜ ํŽ˜์ธํŒ… ๊ทœ์น™์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋งํฌ ์ •๋ณด๋ฅผ ๋” ๊น”๋”ํ•˜๊ณ  ํšจ์œจ์ ์ธ ๋ฐฉ๋ฒ•์œผ๋กœ ์ €์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์•„๋งˆ๋„ ์…€์„ ๋ Œ๋”๋งํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ๊ณ  ์‚ฌ์šฉ์ž ์ •์˜ ์†์„ฑ์„ ๊ฑธ ์ˆ˜ ์žˆ๋Š” ICellPainter ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•œ ๊ฐ€์ง€ ์•„์ด๋””์–ด๋Š” BufferLine๋‹น ๋‘ ๊ฐœ์˜ ๋ฐฐ์—ด(Uint32Array ๋ฐ ICellPainter ๋ฐฐ์—ด)์„ ์‚ฌ์šฉํ•˜๊ณ  ๊ฐ ์…€์— ๋Œ€ํ•ด ๊ฐ๊ฐ ํ•˜๋‚˜์˜ ์š”์†Œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ˜„์žฌ ICellPainter๋Š” ํŒŒ์„œ ์ƒํƒœ์˜ ์†์„ฑ์ด๋ฏ€๋กœ ์ƒ‰์ƒ/์†์„ฑ ์ƒํƒœ๊ฐ€ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๋Š” ํ•œ ๋™์ผํ•œ ICellPainter๋ฅผ ์žฌ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ์…€์— ํŠน์ˆ˜ ์†์„ฑ์„ ์ถ”๊ฐ€ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ ๋จผ์ € ICellPainter๋ฅผ ๋ณต์ œํ•ฉ๋‹ˆ๋‹ค(๊ณต์œ ๋  ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ).

๊ฐ€์žฅ ์ผ๋ฐ˜์ ์ธ ์ƒ‰์ƒ/์†์„ฑ ์กฐํ•ฉ์— ๋Œ€ํ•ด ICellPainter๋ฅผ ๋ฏธ๋ฆฌ ํ• ๋‹นํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ตœ์†Œํ•œ ๊ธฐ๋ณธ ์ƒ‰์ƒ/์†์„ฑ์— ํ•ด๋‹นํ•˜๋Š” ๊ณ ์œ ํ•œ ๊ฐœ์ฒด๊ฐ€ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์Šคํƒ€์ผ ๋ณ€๊ฒฝ(์˜ˆ: ๊ธฐ๋ณธ ์ „๊ฒฝ/๋ฐฐ๊ฒฝ ์ƒ‰์ƒ ๋ณ€๊ฒฝ)์€ ๊ฐ ์…€์„ ์—…๋ฐ์ดํŠธํ•  ํ•„์š” ์—†์ด ํ•ด๋‹น ICellPainter ์ธ์Šคํ„ด์Šค๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฐ€๋Šฅํ•œ ์ตœ์ ํ™”๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋‹จ์ผ ๋„ˆ๋น„ ๋ฐ ์ด์ค‘ ๋„ˆ๋น„ ๋ฌธ์ž(๋˜๋Š” ๋„ˆ๋น„๊ฐ€ 0์ธ ๋ฌธ์ž)์— ๋Œ€ํ•ด ๋‹ค๋ฅธ ICellPainter ์ธ์Šคํ„ด์Šค๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. (์ด๋Š” ๊ฐ Uint32Array ์š”์†Œ์— 2๋น„ํŠธ๋ฅผ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.) Uint32Array์—๋Š” 11๊ฐœ์˜ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์†์„ฑ ๋น„ํŠธ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค(BMP ๋ฌธ์ž์— ๋Œ€ํ•ด ์ตœ์ ํ™”ํ•˜๋ฉด ๋” ๋งŽ์ด). ์ด๋“ค์€ ๊ฐ€์žฅ ์ผ๋ฐ˜์ ์ธ ICellPainter ์ธ์Šคํ„ด์Šค๋ฅผ ์ธ๋ฑ์‹ฑํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ€์žฅ ์ผ๋ฐ˜์ /์œ ์šฉํ•œ ์ƒ‰์ƒ/์†์„ฑ ์กฐํ•ฉ์„ ์ธ์ฝ”๋”ฉํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด ICellPainter ๋ฐฐ์—ด์€ ๋Š๋ฆฌ๊ฒŒ ํ• ๋‹น๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฆ‰, ๋ผ์ธ์˜ ์ผ๋ถ€ ์…€์— "๋œ ์ผ๋ฐ˜์ ์ธ" ICellPainter๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ์—๋งŒ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

BMP๊ฐ€ ์•„๋‹Œ ๋ฌธ์ž์— ๋Œ€ํ•œ _combined ๋ฐฐ์—ด์„ ์ œ๊ฑฐํ•˜๊ณ  ICellPainter์— ์ €์žฅํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. (์ด๋ฅผ ์œ„ํ•ด์„œ๋Š” BMP๊ฐ€ ์•„๋‹Œ ๊ฐ ์บ๋ฆญํ„ฐ์— ๋Œ€ํ•ด ๊ณ ์œ ํ•œ ICellPainter๊ฐ€ ํ•„์š”ํ•˜๋ฏ€๋กœ ์—ฌ๊ธฐ์—๋Š” ์ ˆ์ถฉ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.)

@PerBothner ์˜ˆ ๊ฐ„์ ‘ ์ฐธ์กฐ๋Š” ๋” ๋‹ค์žฌ๋‹ค๋Šฅํ•˜๋ฏ€๋กœ ๋“œ๋ฌธ ์ถ”๊ฐ€ ๊ธฐ๋Šฅ์— ๋” ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด๋“œ๋“ค์€ ํ”ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์• ์ดˆ์— ์ตœ์ ํ™”๋ฅผ ํ•˜์ง€ ์•Š์œผ๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

๋‚ด๊ฐ€ ์—ฌ๋Ÿฌ ํ…Œ์ŠคํŠธ๋ฒ ๋“œ์—์„œ ์‹œ๋„ํ•œ ๊ฒƒ์— ๋Œ€ํ•œ ๋ช‡ ๊ฐ€์ง€ ๋ฉ”๋ชจ:

  • ์…€ ๋ฌธ์ž์—ด ๋‚ด์šฉ
    ๋‚˜๋Š” C++์—์„œ ์™€์„œ C++์—์„œ์™€ ๊ฐ™์ด ๋ฌธ์ œ๋ฅผ ๋ณด๋ ค๊ณ  ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋‚ด์šฉ์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ๋กœ ์‹œ์ž‘ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๋‹จ์ˆœํ•œ ๋ฌธ์ž์—ด ํฌ์ธํ„ฐ์˜€์ง€๋งŒ ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ ๋‹จ์ผ ๋ฌธ์ž ๋ฌธ์ž์—ด์„ ๊ฐ€๋ฆฌํ‚ต๋‹ˆ๋‹ค. ๋‚ญ๋น„์•ผ. ๋”ฐ๋ผ์„œ ๋‚ด ์ฒซ ๋ฒˆ์งธ ์ตœ์ ํ™”๋Š” ์ฃผ์†Œ ๋Œ€์‹  ์ฝ”๋“œ ํฌ์ธํŠธ๋ฅผ ์ง์ ‘ ์ €์žฅํ•˜์—ฌ ๋ฌธ์ž์—ด ์ถ”์ƒํ™”๋ฅผ ์ œ๊ฑฐํ•˜๋Š” ๊ฒƒ์ด์—ˆ์Šต๋‹ˆ๋‹ค(JS๋ณด๋‹ค C/C++์—์„œ ํ›จ์”ฌ ์‰ฝ์Šต๋‹ˆ๋‹ค). ์ด๊ฒƒ์€ ์…€๋‹น 12๋ฐ”์ดํŠธ๋ฅผ ์ ˆ์•ฝํ•˜๋ฉด์„œ ์ฝ๊ธฐ/์“ฐ๊ธฐ ์•ก์„ธ์Šค๋ฅผ ๊ฑฐ์˜ ๋‘ ๋ฐฐ๋กœ ๋Š˜๋ ธ์Šต๋‹ˆ๋‹ค(8๋ฐ”์ดํŠธ ํฌ์ธํ„ฐ + ๋ฌธ์ž์—ด์˜ 4๋ฐ”์ดํŠธ, 64๋น„ํŠธ์™€ 32๋น„ํŠธ wchar_t). ์ฐธ๊ณ  - ์—ฌ๊ธฐ์„œ ์†๋„ ํ–ฅ์ƒ์˜ ์ ˆ๋ฐ˜์€ ์บ์‹œ์™€ ๊ด€๋ จ๋ฉ๋‹ˆ๋‹ค(์ž„์˜์˜ ๋ฌธ์ž์—ด ์œ„์น˜๋กœ ์ธํ•œ ์บ์‹œ ๋ˆ„๋ฝ). ์ด๊ฒƒ์€ codepoint ์— ๊ฒฐํ•ฉ๋œ ๋น„ํŠธ ์„ธํŠธ๊ฐ€ ์žˆ์„ ๋•Œ ์ธ๋ฑ์‹ฑํ•œ ๋ฉ”๋ชจ๋ฆฌ ๋ฉ์–ด๋ฆฌ์ธ ์…€ ์ฝ˜ํ…์ธ  ๊ฒฐํ•ฉ์— ๋Œ€ํ•œ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์œผ๋กœ ๋ช…ํ™•ํ•ด์กŒ์Šต๋‹ˆ๋‹ค(valgrind๋กœ ํ…Œ์ŠคํŠธํ•œ ๋” ๋‚˜์€ ์บ์‹œ ์ง€์—ญ์„ฑ์œผ๋กœ ์ธํ•ด ์•ก์„ธ์Šค๊ฐ€ ๋” ๋น ๋ฆ„). JS๋กœ ์ด์›”๋œ ์†๋„ ํ–ฅ์ƒ์€ ํ•„์š”ํ•œ ๋ฌธ์ž์—ด์—์„œ ์ˆซ์ž๋กœ์˜ ๋ณ€ํ™˜(์—ฌ์ „ํžˆ ๋” ๋น ๋ฆ„)์œผ๋กœ ์ธํ•ด ๊ทธ๋‹ค์ง€ ํฌ์ง€ ์•Š์•˜์ง€๋งŒ ๋ฉ”๋ชจ๋ฆฌ ์ ˆ์•ฝ์€ ํ›จ์”ฌ ๋” ์ปธ์Šต๋‹ˆ๋‹ค(JS ์œ ํ˜•์— ๋Œ€ํ•œ ์ผ๋ถ€ ์ถ”๊ฐ€ ๊ด€๋ฆฌ ๊ณต๊ฐ„์œผ๋กœ ์ธํ•ด). ๋ฌธ์ œ๋Š” JS์˜ ํฐ ๋ฐ˜ํŒจํ„ด์ธ ๋ช…์‹œ์  ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ์™€ ๊ฒฐํ•ฉ๋œ ์ „์ฒด StringStorage ์˜€์Šต๋‹ˆ๋‹ค. ์ด์— ๋Œ€ํ•œ ๋น ๋ฅธ ์ˆ˜์ •์€ ์ •๋ฆฌ๋ฅผ GC์— ์œ„์ž„ํ•˜๋Š” _combined ๊ฐœ์ฒด์˜€์Šต๋‹ˆ๋‹ค. ์—ฌ์ „ํžˆ ๋ณ€๊ฒฝ๋  ์ˆ˜ ์žˆ์œผ๋ฉฐ btw๋Š” ์ž„์˜์˜ ์…€ ๊ด€๋ จ ๋ฌธ์ž์—ด ๋‚ด์šฉ์„ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค(์ž์†Œ์ž๋ฅผ ์—ผ๋‘์— ๋‘๊ณ  ์ด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ–ˆ์ง€๋งŒ ๋ฐฑ์—”๋“œ์—์„œ ์ง€์›ํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ๊ณง ๋ณผ ์ˆ˜ ์—†์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค). ๋”ฐ๋ผ์„œ ์…€ ๋‹จ์œ„๋กœ ์ถ”๊ฐ€ ๋ฌธ์ž์—ด ๋‚ด์šฉ์„ ์ €์žฅํ•˜๋Š” ๊ณณ์ž…๋‹ˆ๋‹ค.
  • ์†์„ฑ
    ์†์„ฑ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ชจ๋“  ํ„ฐ๋ฏธ๋„ ์ธ์Šคํ„ด์Šค์—์„œ ์‚ฌ์šฉ๋œ ๋ชจ๋“  ์†์„ฑ์— ๋Œ€ํ•ด ์ „์—ญ AttributeStorage ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ "ํฌ๊ฒŒ ์ƒ๊ฐ"ํ•˜๊ธฐ ์‹œ์ž‘ํ–ˆ์Šต๋‹ˆ๋‹ค(https://github.com/jerch/xterm.js/tree/AttributeStorage ์ฐธ์กฐ). ๋ฉ”๋ชจ๋ฆฌ ์ธก๋ฉด์—์„œ ์ด๊ฒƒ์€ ๊ฝค ์ข‹์€ ๊ฒฐ๊ณผ๋ฅผ ์–ป์—ˆ์Šต๋‹ˆ๋‹ค. ์ฃผ๋กœ ppl์ด ํŠธ๋ฃจ ์ปฌ๋Ÿฌ ์ง€์›์ด ์žˆ๋Š” ๊ฒฝ์šฐ์—๋„ ์ž‘์€ ์†์„ฑ ์„ธํŠธ๋งŒ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์„ฑ๋Šฅ์€ ๊ทธ๋‹ค์ง€ ์ข‹์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ์ฃผ๋กœ ref ์นด์šดํŒ…(๋ชจ๋“  ์…€์ด ์ด ์™ธ๋ถ€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋‘ ๋ฒˆ ์—ฟ๋ด์•ผ ํ•จ) ๋ฐ attr ์ผ์น˜ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ref๋ฅผ JS์— ์ ์šฉํ•˜๋ ค๊ณ  ํ–ˆ์„ ๋•Œ ์ž˜๋ชป๋œ ๋Š๋‚Œ์ด ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค. ๋ฐ”๋กœ "STOP" ๋ฒ„ํŠผ์„ ๋ˆŒ๋ €๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค. ๊ทธ ์‚ฌ์ด์— ์ด๋ฏธ ํ˜•์‹ํ™”๋œ ๋ฐฐ์—ด๋กœ ์ „ํ™˜ํ•˜์—ฌ ์ˆ˜๋งŽ์€ ๋ฉ”๋ชจ๋ฆฌ ๋ฐ GC ํ˜ธ์ถœ์„ ์ ˆ์•ฝํ–ˆ์œผ๋ฉฐ ๋”ฐ๋ผ์„œ ์•ฝ๊ฐ„ ๋” ๋น„์‹ผ ํ”Œ๋žซ ๋ฉ”๋ชจ๋ฆฌ ๋ ˆ์ด์•„์›ƒ์ด ์†๋„ ์ด์ ์„ ๋ณด์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    ๋‚ด๊ฐ€ ํ…Œ์ŠคํŠธํ•œ yday(๋งˆ์ง€๋ง‰ ์ฝ”๋ฉ˜ํŠธ)๋Š” https://github.com/jerch/xterm.js/tree/AttributeStorage ์˜ ํŠธ๋ฆฌ๊ฐ€ ์žˆ๋Š” attrs์— ๋Œ€ํ•œ ๋ผ์ธ ์ˆ˜์ค€์˜ ๋‘ ๋ฒˆ์งธ ์œ ํ˜• ๋ฐฐ์—ด๋กœ ๋งค์นญ์„ ์œ„ํ•ด (๋‹น์‹ ์˜ ICellPainter ์•„์ด๋””์–ด์™€ ๊ฑฐ์˜ ๋น„์Šทํ•ฉ๋‹ˆ๋‹ค) ). ๊ฒฐ๊ณผ๊ฐ€ ์ข‹์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ํ˜„์žฌ๋กœ์„œ๋Š” ํ‰ํ‰ํ•œ 32๋น„ํŠธ ๋ ˆ์ด์•„์›ƒ์— ๊ธฐ๋Œ€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์ด์ œ ์ด ํ‰ํ‰ํ•œ 32๋น„ํŠธ ๋ ˆ์ด์•„์›ƒ์€ ์ผ๋ฐ˜์ ์ธ ๊ฒƒ๋“ค์— ์ตœ์ ํ™”๋œ ๊ฒƒ์œผ๋กœ ๋ฐํ˜€์กŒ์œผ๋ฉฐ ์ผ๋ฐ˜์ ์ด์ง€ ์•Š์€ ์ถ”๊ฐ€ ๊ธฐ๋Šฅ์€ ๋ถˆ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ์ง„์‹ค. ๊ธ€์Ž„, ์šฐ๋ฆฌ๋Š” ์—ฌ์ „ํžˆ ๋งˆ์ปค๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค(์ด๋“ค์— ์ต์ˆ™ํ•˜์ง€ ์•Š์•„์„œ ๊ทธ๋“ค์ด ๋ฌด์—‡์„ ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์ง€๊ธˆ ๋‹น์žฅ์€ ๋งํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค). ๊ทธ๋ฆฌ๊ณ  yepp - ๋ฒ„ํผ์— ์—ฌ์ „ํžˆ ์—ฌ์œ  ๋น„ํŠธ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค(์ด๋Š” ๋ฏธ๋ž˜์˜ ํ•„์š”๋ฅผ ์œ„ํ•ด ์ข‹์€ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํŠน๋ณ„ ๋Œ€์šฐ๋ฅผ ์œ„ํ•œ ๊นƒ๋ฐœ ๋“ฑ).

์ €์—๊ฒŒ๋Š” attrs ์Šคํ† ๋ฆฌ์ง€๊ฐ€ ์žˆ๋Š” 16๋น„ํŠธ ๋ ˆ์ด์•„์›ƒ์ด ๊ทธ๋ ‡๊ฒŒ ๋‚˜์œ ์„ฑ๋Šฅ์„ ๋ฐœํœ˜ํ•˜๋Š” ๊ฒƒ์ด ์œ ๊ฐ์ž…๋‹ˆ๋‹ค. ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์„ ์ ˆ๋ฐ˜์œผ๋กœ ์ค„์ด๋Š” ๊ฒƒ์€ ์—ฌ์ „ํžˆ โ€‹โ€‹ํฐ ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค(ํŠนํžˆ ppl์ด ์Šคํฌ๋กค ๋ผ์ธ >10k๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์‹œ์ž‘ํ•  ๋•Œ). ๊ทธ๋Ÿฌ๋‚˜ ๋Ÿฐํƒ€์ž„ ํŒจ๋„ํ‹ฐ์™€ ์ฝ”๋“œ ๋ณต์žก์„ฑ์ด ๋” ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. ์ƒ์œ„ mem์€ atm imho๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

ICellPainter ์•„์ด๋””์–ด์— ๋Œ€ํ•ด ์ž์„ธํžˆ ์„ค๋ช…ํ•ด ์ฃผ์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ? ์ง€๊ธˆ๊นŒ์ง€ ์ค‘์š”ํ•œ ๊ธฐ๋Šฅ์„ ๋†“์ณค์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

DomTerm์— ๋Œ€ํ•œ ์ œ ๋ชฉํ‘œ๋Š” ๊ธฐ์กด ํ„ฐ๋ฏธ๋„ ์—๋ฎฌ๋ ˆ์ดํ„ฐ์—์„œ ํ™œ์„ฑํ™”๋œ ๊ฒƒ๋ณด๋‹ค ๋” ํ’๋ถ€ํ•œ ์ƒํ˜ธ ์ž‘์šฉ์„ ํ™œ์„ฑํ™”ํ•˜๊ณ  ์žฅ๋ คํ•˜๋Š” ๊ฒƒ์ด์—ˆ์Šต๋‹ˆ๋‹ค. ์›น ๊ธฐ์ˆ ์„ ์‚ฌ์šฉํ•˜๋ฉด ๋งŽ์€ ํฅ๋ฏธ๋กœ์šด ์ผ์„ ํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ๋น ๋ฅธ ๊ธฐ์กด ํ„ฐ๋ฏธ๋„ ์—๋ฎฌ๋ ˆ์ดํ„ฐ์—๋งŒ ์ง‘์ค‘ํ•˜๋Š” ๊ฒƒ์€ ๋ถ€๋„๋Ÿฌ์šด ์ผ์ž…๋‹ˆ๋‹ค. ํŠนํžˆ xterm.js์˜ ๋งŽ์€ ์‚ฌ์šฉ ์‚ฌ๋ก€(์˜ˆ: IDE์šฉ REPL)๋Š” ๋‹จ์ˆœํ•œ ํ…์ŠคํŠธ ์ด์ƒ์˜ ์ด์ ์„ ์–ป์„ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ํŠนํžˆ ๊ทธ๋ ‡์Šต๋‹ˆ๋‹ค. Xterm.js๋Š” ์†๋„ ์ธก๋ฉด์—์„œ ์ž˜ ์ž‘๋™ํ•˜์ง€๋งŒ(์†๋„์— ๋Œ€ํ•ด ๋ถˆํ‰ํ•˜๋Š” ์‚ฌ๋žŒ์ด ์žˆ์Šต๋‹ˆ๊นŒ?), ๊ธฐ๋Šฅ์—์„œ๋Š” ๊ทธ๋ ‡์ง€ ์•Š์Šต๋‹ˆ๋‹ค(์˜ˆ๋ฅผ ๋“ค์–ด ์‚ฌ๋žŒ๋“ค ์ด ํŠธ๋ฃจ์ปฌ๋Ÿฌ ๋ฐ ๋‚ด์žฅ ๊ทธ๋ž˜ํ”ฝ ๋ˆ„๋ฝ์— ๋Œ€ํ•ด ๋ถˆํ‰ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค). ์œ ์—ฐ์„ฑ์— ์กฐ๊ธˆ ๋” ์ง‘์ค‘ํ•˜๊ณ  ์„ฑ๋Šฅ์—๋Š” ์•ฝ๊ฐ„ ๋œ ์ง‘์ค‘ํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€์น˜๊ฐ€ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

_"ICellPainter ์•„์ด๋””์–ด์— ๋Œ€ํ•ด ์ž์„ธํžˆ ์„ค๋ช…ํ•ด ์ฃผ์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?"_

์ผ๋ฐ˜์ ์œผ๋กœ ICellPainter๋Š” Uint32Array์—์„œ ๊ฐ€์ ธ์˜จ ๋ฌธ์ž ์ฝ”๋“œ/๊ฐ’์„ ์ œ์™ธํ•œ ๋ชจ๋“  ์…€๋ณ„ ๋ฐ์ดํ„ฐ๋ฅผ ์บก์Šํ™”ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” "์ผ๋ฐ˜" ๋ฌธ์ž ์…€์˜ ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค. ํฌํ•จ๋œ ์ด๋ฏธ์ง€ ๋ฐ ๊ธฐํƒ€ "์ƒ์ž"์˜ ๊ฒฝ์šฐ ๋ฌธ์ž ์ฝ”๋“œ/๊ฐ’์ด ์˜๋ฏธ๊ฐ€ ์—†์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

interface ICellPainter {
    drawOnCanvas(ctx: CanvasRenderingContext2D, code: number, x: number, y: number);
    // transitional - to avoid allocating IGlyphIdentifier we should replace
    //  uses by pair of ICellPainter and code.  Also, a painter may do custom rendering,
    // such that there is no 'code' or IGlyphIdentifier.
    asGlyph(code: number): IGlyphIdentifier;
    width(): number; // in pixels for flexibility?
    height(): number;
    clone(): ICellPainter;
}

์…€์„ ICellPainter์— ๋งคํ•‘ํ•˜๋Š” ๊ฒƒ์€ ๋‹ค์–‘ํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ถ„๋ช…ํ•œ ๊ฒƒ์€ ๊ฐ BufferLine์— ICellPainter ๋ฐฐ์—ด์ด ์žˆ์ง€๋งŒ ์…€๋‹น 8๋ฐ”์ดํŠธ ํฌ์ธํ„ฐ(์ตœ์†Œํ•œ)๊ฐ€ ํ•„์š”ํ•˜๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ•œ ๊ฐ€์ง€ ๊ฐ€๋Šฅ์„ฑ์€ _combined ๋ฐฐ์—ด์„ ICellPainter ๋ฐฐ์—ด๊ณผ ๊ฒฐํ•ฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. IS_COMBINED_BIT_MASK๊ฐ€ ์„ค์ •๋˜๋ฉด ICellPainter๋„ ๊ฒฐํ•ฉ๋œ ๋ฌธ์ž์—ด์„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. ๋˜ ๋‹ค๋ฅธ ๊ฐ€๋Šฅํ•œ ์ตœ์ ํ™”๋Š” Uint32Array์—์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋น„ํŠธ๋ฅผ ๋ฐฐ์—ด์— ๋Œ€ํ•œ ์ธ๋ฑ์Šค๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์•ฝ๊ฐ„์˜ ๋ณต์žก์„ฑ๊ณผ ๊ฐ„์ ‘ ์ฐธ์กฐ๊ฐ€ ์ถ”๊ฐ€๋˜์ง€๋งŒ ๊ณต๊ฐ„์ด ์ ˆ์•ฝ๋ฉ๋‹ˆ๋‹ค.

๋‚˜๋Š” ์šฐ๋ฆฌ๊ฐ€ monaco-editor๊ฐ€ ํ•˜๋Š” ๋ฐฉ์‹๋Œ€๋กœ ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๋„๋ก ๊ถŒ์žฅํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์ •๋ณด๋ฅผ ๋ฒ„ํผ์— ์ €์žฅํ•˜๋Š” ๋Œ€์‹  decorations ๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ–‰ / ์—ด ๋ฒ”์œ„์— ๋Œ€ํ•œ ์žฅ์‹์„ ๋งŒ๋“ค๊ณ  ํ•ด๋‹น ๋ฒ”์œ„์— ๊ณ ์ •๋ฉ๋‹ˆ๋‹ค.

// decorations are buffer-dependant (we need to know which buffer to decorate)
const decoration = buffer.createDecoration({
  type: 'link',
  data: 'https://www.google.com',
  range: { startRow: 2, startColumn: 5, endRow: 2, endColumn: 25 }
});

๋‚˜์ค‘์— ๋ Œ๋”๋Ÿฌ๋Š” ์ด๋Ÿฌํ•œ ์žฅ์‹์„ ์„ ํƒํ•˜์—ฌ ๊ทธ๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

monaco-editor API๊ฐ€ ์–ด๋–ป๊ฒŒ ๋ณด์ด๋Š”์ง€ ๋ณด์—ฌ์ฃผ๋Š” ์ด ์ž‘์€ ์˜ˆ๋ฅผ ํ™•์ธํ•˜์‹ญ์‹œ์˜ค.
https://microsoft.github.io/monaco-editor/playground.html#interacting -with-the-editor-line-and-inline-decorations

ํ„ฐ๋ฏธ๋„ ๋‚ด๋ถ€์—์„œ ๊ทธ๋ฆผ์„ ๋ Œ๋”๋งํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™์€ ๊ฒฝ์šฐ monaco๋Š” ๋‹ค์Œ ์˜ˆ์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋Š” ๋ณด๊ธฐ ์˜์—ญ ๊ฐœ๋…์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค(๋‹ค๋ฅธ ๊ฐœ๋… ์ค‘์—์„œ).
https://microsoft.github.io/monaco-editor/playground.html#interacting -with-the-editor-listening-to-mouse-events

์„ค๋ช…๊ณผ ์Šค์ผ€์น˜์—…์„ ์œ„ํ•ด

์šฐ๋ฆฌ๋Š” ๊ฒฐ๊ตญ ๋ฏธ๋ž˜์— ์ž…๋ ฅ ์ฒด์ธ + ๋ฒ„ํผ๋ฅผ ์›น ์ž‘์—…์ž๋กœ ์ด๋™ํ•  ๊ณ„ํš์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋ฒ„ํผ๋Š” ์ถ”์ƒ ์ˆ˜์ค€์—์„œ ์ž‘๋™ํ•˜๋„๋ก ๋˜์–ด ์žˆ์œผ๋ฉฐ ํ”ฝ์…€ ๋ฉ”ํŠธ๋ฆญ์ด๋‚˜ DOM ๋…ธ๋“œ์™€ ๊ฐ™์€ ๋ Œ๋”๋ง/ํ‘œํ˜„ ๊ด€๋ จ ํ•ญ๋ชฉ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. DomTerm์€ ๊ณ ๋„๋กœ ์‚ฌ์šฉ์ž ์ •์˜ํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด์— ๋Œ€ํ•œ ์š”๊ตฌ ์‚ฌํ•ญ์ด ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•˜์ง€๋งŒ ํ–ฅ์ƒ๋œ ๋‚ด๋ถ€ ๋งˆ์ปค API๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ด๋ฅผ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•˜๋ฉฐ ์—ฌ๊ธฐ์—์„œ monaco/vscode(thx for th ํฌ์ธํ„ฐ @mofux)์—์„œ ๋ฐฐ์šธ ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.
์ €๋Š” ์ฝ”์–ด ๋ฒ„ํผ๋ฅผ ๋น„์ผ์ƒ์ ์ธ ๊ฒƒ์œผ๋กœ ์œ ์ง€ํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ์ƒˆ๋กœ์šด ๋ฌธ์ œ๋กœ ๊ฐ€๋Šฅํ•œ ๋งˆ์ปค ์ „๋žต์— ๋Œ€ํ•ด ๋…ผ์˜ํ•ด์•ผ ํ• ๊นŒ์š”?

16๋น„ํŠธ ๋ ˆ์ด์•„์›ƒ ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ๊ฐ€ ์—ฌ์ „ํžˆ ๋งŒ์กฑ์Šค๋Ÿฝ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ตœ์ข… ๊ฒฐ์ •์ด ์•„์ง ์‹œ๊ธ‰ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์—(3.11 ์ด์ „์—๋Š” ์ด ์ค‘ ์–ด๋Š ๊ฒƒ๋„ ๋ณผ ์ˆ˜ ์—†์Œ) ๋ช‡ ๊ฐ€์ง€ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์œผ๋กœ ๊ณ„์† ํ…Œ์ŠคํŠธํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค(32๋น„ํŠธ ๋ณ€ํ˜•๋ณด๋‹ค ์—ฌ์ „ํžˆ ๋” ํฅ๋ฏธ๋กœ์šด ์†”๋ฃจ์…˜์ž…๋‹ˆ๋‹ค).

|             uint32_t             |        uint32_t         |        uint32_t         |
|              content             |            FG           |            BG           |
| comb(1) wcwidth(2) codepoint(21) | flags(8) R(8) G(8) B(8) | flags(8) R(8) G(8) B(8) |

๋‚˜๋Š” ๋˜ํ•œ ์‹œ์ž‘ํ•˜๊ธฐ ์œ„ํ•ด ์ด๊ฒƒ์— ๊ฐ€๊นŒ์šด ๊ฒƒ์œผ๋กœ ๊ฐ€์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๋‚˜์ค‘์— ๋‹ค๋ฅธ ์˜ต์…˜์„ ํƒ์ƒ‰ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ์ด๊ฒƒ์ด ์•„๋งˆ๋„ ์‹œ์ž‘ํ•˜๊ณ  ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ์‰ฌ์šธ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ ํ„ฐ๋ฏธ๋„ ์„ธ์…˜์—๋Š” ๊ณ ์œ ํ•œ ์†์„ฑ์ด ๋งŽ์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์†์„ฑ ๊ฐ„์ ‘ ์ฐธ์กฐ๋Š” ํ™•์‹คํžˆ IMO๋ฅผ ์•ฝ์†ํ•ฉ๋‹ˆ๋‹ค.

๋‚˜๋Š” ์šฐ๋ฆฌ๊ฐ€ monaco-editor๊ฐ€ ํ•˜๋Š” ๋ฐฉ์‹๋Œ€๋กœ ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๋„๋ก ๊ถŒ์žฅํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์ •๋ณด๋ฅผ ๋ฒ„ํผ์— ์ €์žฅํ•˜๋Š” ๋Œ€์‹  ์žฅ์‹์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ–‰ / ์—ด ๋ฒ”์œ„์— ๋Œ€ํ•œ ์žฅ์‹์„ ๋งŒ๋“ค๊ณ  ํ•ด๋‹น ๋ฒ”์œ„์— ๊ณ ์ •๋ฉ๋‹ˆ๋‹ค.

์ด๋Ÿฐ ์ผ์ด ์ผ์–ด๋‚˜๋Š” ๊ฒƒ์„ ๋ณด๊ณ  ์‹ถ์€ ๊ณณ์ž…๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๋ผ์ธ์„ ๋”ฐ๋ผ ๋‚ด๊ฐ€ ๊ฐ€์ง„ ํ•œ ๊ฐ€์ง€ ์•„์ด๋””์–ด๋Š” ์ž„๋ฒ ๋”๊ฐ€ DOM ์š”์†Œ๋ฅผ ๋ฒ”์œ„์— ์ฒจ๋ถ€ํ•˜์—ฌ ์‚ฌ์šฉ์ž ์ •์˜ ํ•ญ๋ชฉ์„ ๊ทธ๋ฆด ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ๊ฒƒ์ด์—ˆ์Šต๋‹ˆ๋‹ค. ์ด ์ž‘์—…์œผ๋กœ ๋‹ฌ์„ฑํ•˜๊ณ  ์‹ถ์€ ์ˆœ๊ฐ„์— ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ๋Š” 3๊ฐ€์ง€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ์ด ๋ฐฉ๋ฒ•์œผ๋กœ ๋งํฌ์— ๋ฐ‘์ค„์„ ๊ทธ๋ฆฝ๋‹ˆ๋‹ค.
  • * ๋˜๋Š” ๊ธฐํƒ€์™€ ๊ฐ™์€ ํ–‰์— ๋งˆ์ปค ํ—ˆ์šฉ
  • ํ–‰์ด "๊นœ๋ฐ•์ด๋Š”" ๊ฒƒ์„ ํ—ˆ์šฉํ•˜์—ฌ ์–ด๋–ค ์ผ์ด ๋ฐœ์ƒํ–ˆ์Œ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

์ด ๋ชจ๋“  ๊ฒƒ์€ ์˜ค๋ฒ„๋ ˆ์ด๋กœ ๋‹ฌ์„ฑํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ์ด๋Š” ๋งค์šฐ ์ ‘๊ทผํ•˜๊ธฐ ์‰ฌ์šด API ์œ ํ˜•(DOM ๋…ธ๋“œ ๋…ธ์ถœ)์ด๋ฉฐ ๋ Œ๋”๋Ÿฌ ์œ ํ˜•์— ๊ด€๊ณ„์—†์ด ์ž‘๋™ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ž„๋ฒ ๋”๊ฐ€ ๋ฐฐ๊ฒฝ์ƒ‰๊ณผ ์ „๊ฒฝ์ƒ‰์„ ๊ทธ๋ฆฌ๋Š” ๋ฐฉ์‹์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ์‚ฌ์—…์— ๋›ฐ์–ด๋“ค๊ณ  ์‹ถ์€์ง€ ์ž˜ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค.


@jerch ๋‚˜๋Š” ์ด๊ฒƒ์„ 3.11.0 ์ด์ •ํ‘œ์— ๋„ฃ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋•Œ์— ๊ณ„ํš๋œ JS ๋ฐฐ์—ด ๊ตฌํ˜„์„ ์ œ๊ฑฐํ•  ๋•Œ ์ด ๋ฌธ์ œ๊ฐ€ ์™„๋ฃŒ๋œ ๊ฒƒ์œผ๋กœ ๊ฐ„์ฃผํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. https://github.com/xtermjs/xterm.js/pull/1796 ๋„ ๊ทธ๋•Œ ๋ณ‘ํ•ฉ๋  ์˜ˆ์ •์ด์ง€๋งŒ, ์ด ๋ฌธ์ œ๋Š” ํ•ญ์ƒ ๋ฒ„ํผ์˜ ๋ฉ”๋ชจ๋ฆฌ ๋ ˆ์ด์•„์›ƒ์„ ๊ฐœ์„ ํ•˜๊ธฐ ์œ„ํ•œ ๊ฒƒ์ด์—ˆ์Šต๋‹ˆ๋‹ค.

๋˜ํ•œ, ์ด ๋‚˜์ค‘ ๋…ผ์˜์˜ ๋Œ€๋ถ€๋ถ„์€ https://github.com/xtermjs/xterm.js/issues/484 ๋ฐ https://github.com/xtermjs/xterm.js/issues/1852 ์—์„œ ๋” ๋‚˜์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. (์žฅ์‹ ๋ฌธ์ œ๊ฐ€ ์—†์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ƒ์„ฑ๋จ).

@Tyriar Woot - ๋งˆ์นจ๋‚ด ๋‹ซํ˜”์Šต๋‹ˆ๋‹ค :sweat_smile:

๐ŸŽ‰ ๐Ÿ•บ ๐Ÿพ

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰