До NVIDIA: що означало «графіка», коли 3D був розкішшю

Було корисно?

Ви ще не знайомі з «графікою», доки не бачили, як курсор тягнеться по екрану, ніби тягне диван у гору.
У світі до NVIDIA вузьке місце було не в екзотичній помилці шейдера. Це були ви, CPU, шина пам’яті та шматок ОЗП,
який випадково було відображено на екран.

Це era, коли «графічна підсистема» могла означати: контролер CRT, палітра, макет бітпланів, який краще не неправильно зрозуміти,
і драйвер, який іноді робив більше імпровізації, ніж рендерингу. Якщо ви керуєте продукційними системами сьогодні, ви впізнаєте ці патерни:
приховані обмеження пропускної здатності, оманливі метрики й «оптимізації», що переміщують проблему з одного вузького місця в інше.

Що означало «графіка» до ери GPU

Сьогодні «графіка» натякає на конвеєр: шейдери, текстури, командні буфери, VRAM і стек драйверів, що наполовину в ядрі, наполовину — чорна магія.
До того, як NVIDIA зробила слово «GPU» загальновживаним, «графіка» в основному була про те, як швидко помістити пікселі у фреймбуфер,
щоб люди не помічали, що ви підробляєте рух.

Більшість систем жили в одному з трьох світі:

  • Текстовий режим, що вдавав із себе графіку. Символьні клітини, ROM зі шрифтом і, можливо, деякі блочні символи для «UI».
    Дешево, надійно й швидко, бо рухали байти, а не пікселі.
  • 2D-бітмапи з мінімальним прискоренням. Фреймбуфер у VRAM; малювання означало копіювання прямокутників, малювання ліній
    і заповнення областей. Якщо у вас був blitter, ви почувалися розкішно.
  • 3D як податок для фахівців. Робочі станції з дорогими додатковими платами або пропрієтарними конвеєрами. На споживчих ПК
    «3D» часто означало програмне рендерення: хитра математика, фікс-пойнт трюки і прийняття обставин.

Спільна нитка: переміщення пам’яті. «Рендеринг» не був філософським питанням. Це було «скільки байт я можу пересунути за кадр»
і «скільки разів я торкаюся кожного пікселя».

Якщо вам потрібна основна ментальна модель, вона така: графіка до GPU — це ввід/вивід.
Ваш екран — це пристрій пам’яті, який постійно зчитується. Ваше завдання — оновлювати цю пам’ять, не зіштовхнувшись із шиною, кешем CPU
або таймінгом оновлення дисплея.

Конкретні факти та історичний контекст

Кілька коротких, але важливих пунктів контексту, які пояснюють, чому програмне забезпечення писалось саме так:
API, формати файлів, тулкіти UI і фольклор продуктивності не з’явилися нізвідки.

  1. IBM VGA (1987) стандартизував 640×480 з 16 кольорами і 256-колірний режим 320×200.
    Режим 320×200×8bpp став стандартним полотном для ігор, бо це був компроміс між швидкістю і обсягом пам’яті.
  2. «Mode 13h» (320×200, 256 кольорів) в DOS відображав VRAM лінійно.
    Лінійна адресація дозволяла CPU записувати пікселі простим арифметичним зміщенням — без планарної гімнастики.
  3. Планарні режими були поширені і болючі.
    У 16-кольорових VGA режимах пікселі жили в різних бітпланах. Один запис пікселя міг означати операцію read-modify-write через плани.
    Це формувало все: від спрайт-движків до того, чому деякі шрифти мали саме такий вигляд.
  4. VESA BIOS Extensions (VBE) робили можливими вищі роздільності в DOS.
    Це не було «plug and play»; це було «якщо пощастить і прошивка карти поводиться коректно».
  5. Раннє 2D-прискорення стосувалося прямокутників, а не трикутників.
    BitBLT-двигуни, апаратне малювання ліній і апаратний курсор були важливішими за будь-яке «3D».
  6. Шина вирішувала долю: ISA vs VLB vs PCI.
    Пропускна здатність і затримки ISA обмежували запис у фреймбуфер; VLB і PCI зробили вищу пропускну здатність практичною, підгодовуючи VRAM швидше.
  7. Палітра кольорів була функцією продуктивності.
    8-бітове індексоване кольорове представлення означало, що фреймбуфер міг бути ~64 KB (320×200) або ~300 KB (640×480), що було невеликим для тієї епохи.
    Циклічні зміни палітри дозволяли «анімацію», не торкаючись більшості пікселів.
  8. 3D-прискорювачі спочатку були фікс-функшн помічниками.
    Ранні споживчі 3D-карти прискорювали текстурування і підготовку трикутників; CPU все ще виконував велику частину роботи, особливо логіку гри й трансформації.
  9. Подвійний буферинг не був «безкоштовним».
    Наявність двох повних фреймбуферів означала подвоєння використання VRAM і збільшення пропускної здатності копіювання. Багато систем використовували dirty rectangles замість цього.

Стара конвеєрна схема: від CPU до фосфору

1) Фреймбуфер не був метафорою

Сучасний стек драйверів GPU ставить завдання в чергу; GPU бере їх і пише у VRAM із масивною внутрішньою паралельністю.
У старшому світі CPU був рендерером. Якщо ви хотіли, щоб піксель загорівся, ви писали за адресою, яка представляла цей піксель.
Контролер дисплея безперервно зчитував VRAM і генерував відеосигнал.

Така організація породжувала просту, але невблаганну істину: продуктивність графіки була продуктивністю пам’яті.
Не просто «швидка ОЗП», а те, де саме знаходилась ОЗП і наскільки дорого до неї добратись.
VRAM за повільною шиною — як S3 bucket, доступний через модем: технічно правильно, практично жорстоко.

2) Що означало «прискорення»

До ери GPU прискорення зазвичай означало чип, який міг:

  • копіювати прямокутник з однієї області VRAM в іншу (BitBLT)
  • заповнювати прямокутник суцільним кольором
  • малювати лінії
  • підтримувати апаратний курсор як накладку (щоб миша не рвалася або не лагала)

Це було величезно. Якщо ви могли копіювати прямокутники в апаратурі, ви могли прокручувати вікна, рухати спрайти і перерисовувати елементи UI,
не «з’їдаючи» CPU. Це та сама причина, через яку сучасні системи люблять DMA: двигуни копіювання звільняють обчислення для реальної роботи.

3) Чому люди одержимі форматами пікселів

Формати пікселів були не естетикою, а виживанням. Якщо ви обирали 8bpp індексований колір, ви зменшували використання пам’яті й пропускну здатність.
Якщо 16bpp (зазвичай 5-6-5 RGB) — ви збільшували трафік, але спрощували тонування і уникали маніпуляцій з палітрою. Якщо 24/32bpp —
ви змушували шину робити кардіо.

І формати не завжди були лінійними. Планарні макети, банкування фреймбуфера (де ви переключаєте, яка частина VRAM видима за адресою),
та вимоги до вирівнювання означали, що наївний «просто пройдуся по пікселях» міг стати катастрофічно повільним.

4) Розриви і тиранія оновлення

Контролер дисплея зчитує VRAM з фіксованою частотою. Якщо ви пишете у VRAM під час зчитування, можна побачити напів-оновлені кадри:
tearing. «Правильне» виправлення — синхронізація: чекати вертикального бланку або використовувати page flipping. Дороге виправлення — копіювання.
Дешеве — «не перерисовувати занадто багато і сподіватися, що ніхто не помітить».

Системи, що робили це правильно, здавалися магічно плавними. Системи, що не робили — здавалися ніби ваші очі дебагують.

Жарт №1: У ті дні «реальне часове рендерення» означало «застосувати рендер до наступної наради». Часом це збігалося з реальністю.

Куди йшов час: вузькі місця, які відчувалися

Пропускна здатність: тихий бюджет

Якщо потрібне правило великого пальця для старої графіки — порахуйте свій сирий бюджет записів.
Екран 640×480 при 8bpp — це ~300 KB. При 60 fps це ~18 MB/s лише для запису одного повного кадру — ігноруючи зчитування,
ігноруючи overdraw, ігноруючи blit-и і все інше, що робить ваш CPU і шина.

На папері сьогодні це звучить помірно. У контексті це часто було всією машиною.
Старі шини, кеші й контролери пам’яті могли перетворити «18 MB/s» на фантазію, коли додається конкурентність і стейти очікування.
Ось чому часткове перерисовування (dirty rectangles) не було мікрооптимізацією; це була різниця між корисним і образливим.

Затримка: чому один піксель міг бути дорогим

VRAM за шиною може мати огидні шаблони доступу. Послідовні записи можуть бути прийнятними; розкидані записи пікселів стають жахом.
Ви бачите це в програмних спрайт-движках: вони батчать, вирівнюють, віддають перевагу спанам. Вони роблять усе, щоб перетворити випадкові записи на лінійні.

Overdraw: малювання одного й того ж пікселя кілька разів

У програмному рендері кожен дотик пікселя має ціну. Якщо ваш UI тулкит перерисовує все вікно через блимання курсора,
то це не «баг інтерфейсу». Це проблема пропускної здатності. Те саме в іграх: якщо ви малюєте фон, потім спрайти, потім знову UI,
той самий піксель може бути записаний тричі.

Правильний інстинкт у ту епоху був: мінімізувати дотики. Малювати один раз. Кешувати агресивно. Клiпати без жалю.
Іноді найкраща техніка рендерингу була «не робити».

Цикли CPU: математика проти пам’яті

Старі дискусії про рендеринг («використовувати fixed-point», «передобчислювати таблиці», «уникати ділення») були не академічні.
CPU були настільки повільними, що математика могла домінувати. Але часто траплялось й інше: CPU міг обчислювати швидше, ніж писати
у фреймбуфер. Тоді ви бачили трюки: малювати в буфер у системній пам’яті і копіювати більшими блоками.
Здається марнотратством — доки не згадаєш, що кеші існують, а шини не пробачають.

Драйвери: тонкий шар між вами й болем

Якщо ви були на DOS — ви звертались до BIOS викликів або вмикали регістри безпосередньо. Якщо ви були на ранньому Windows або X11,
ви довіряли моделі драйверів, яка могла бути написана вендором, чий головний KPI був «завантажується більшість часу».
Якщо ви були на робочих станціях (SGI, Sun, HP), інтеграція часто була краща — за цінами робочих станцій.

В термінах експлуатації: надійність графіки була проблемою ланцюга постачання.
«Коректність рендерингу» залежала від прошивки, таймінгів шини і особливостей чіпсету.

Кут надійності: графіка як операційна залежність

Люди забувають, наскільки операційно критичною була «графіка» у корпоративному оточенні:
торговельні зали, CAD-станції, медичні візуалізації, кіоски, кол-центри. Якщо UI лагав — бізнес лагав.
Якщо екран чорнів після suspend/resume — служба підтримки отримувала нове хобі.

Попередній стек графіки — це притча SRE: крах продуктивності, часткові збої, неочевидні обмеження
і складні взаємодії між апаратним і програмним забезпеченням. Ви не «налаштували його раз». Ви тримаєте його стабільним.

Одна цитата, бо вона підходить до кожної ери систем і кожного екрану, що коли-небудь затормажив:
Надія — не стратегія. — перефразована ідея, часто згадувана в операційних колах; ставте її як нагадування, а не як цитування.

Три корпоративні міні-історії з польових боїв

Міні-історія 1: Інцидент через хибне припущення (глибина кольору як «просто налаштування»)

Внутрішня логістична панель була розгорнута на кількасот тонких клієнтах і відновлених десктопах.
Це було переважно 2D: діаграми, таблиці і віджет мапи. Розгортання пройшло добре в пілоті — новіші машини, пристойна PCI-графіка,
достатньо ОЗП. Потім це дійшло до складу.

Симптом був дивно «людський»: працівники скаржилися, що інтерфейс «відчувався липким». Рухи миші відчувались із затримкою, прокрутка лагала,
а через кілька хвилин додаток «наздоганяв» ривками. Він не падав. Просто зупинявся на місці.
Підтримка спробувала звичайні кроки: перевстановлення, перезавантаження, заміну миші, звинувачення мережі. Ніщо не було послідовним.

Хибне припущення полягало в тому, що перехід з 16-бітного в 32-бітний колір — це безпечне косметичне покращення.
Нова збірка за замовчуванням встановлювала 32bpp, бо виглядало краще на сучасних моніторах і уникало бендингу на градієнтах.
На старих машинах записи у фреймбуфер подвоїлись, і драйвер відкотився від апаратних 2D-шляхів до повільного програмного шляху
для деяких операцій у 32bpp.

Фішка: застосунок перерисовував великі області на кожному таймерному тіку — нормально в 16bpp на пілотному обладнанні, катастрофа в 32bpp
на залишках ери ISA. Ви могли бачити, як використання CPU залишалося помірним, тоді як шина задихалась; UI-потік не був завантажений, він блокувався
на повільних записах і викликах драйвера.

Виправлення не було героїчним. Вони зафіксували флот на 16bpp на тих кінцевих точках, виправили додаток, щоб зменшити області перерисовування,
і додали стартовий чек, який відмовлявся вмикати «гарні градієнти», якщо невеликий бенчмарк не пройшов.
Урок: «налаштування» — частина контракту продуктивності. Ставте їх як зміну схеми.

Міні-історія 2: Оптимізація, що спрацювала проти (подвійний буфер скрізь)

Команда продукту для кіосків хотіла плавніші анімації: без розривів, без мерехтіння. Вони зробили те, що радять усі блоги:
реалізували подвійний буфер. Рендер у заекранний буфер, потім blit на екран. Чисто. Передбачувано. Сучасно.
Вони випустили оновлення, пишаючись новою поліровкою.

Через два тижні надійшли звіти з поля: випадкові зависання, іноді чорні кадри і повільне наростання лагу через кілька годин.
Пристрої мали обмежену пам’ять і інтегровану графіку, що ділила смугу пропускання з CPU. Кіоски також виконували бекґраундну роботу:
локальне логування, періодичні завантаження і декодування зображень.

Подвійний буфер перетворив невеликі інкрементні оновлення у повні копії кадру. Старий код використовував dirty rectangles;
він перерисовував лише те, що змінилося. Новий код завжди рендерив повну сцену (навіть статичний фон) у задній буфер
і потім копіював усе на передній. Пропускна здатність злетіла. Тиск на кеш збільшився. І коли пам’ять стала напруженою,
почався пейджинг.

Гірше: їх виклик «blit to screen» не завжди використовував апаратне прискорення на деяких чіпсетах. У лабораторії це було швидко;
у полі іноді відкотилось до повільнішого шляху, особливо на певних глибинах кольору. Оптимізація була в теорії коректною,
але невірною в деплої.

Вони відкотили універсальний подвійний буфер і реалізували гібрид:
подвійний буфер тільки для анімованої області, зберігали dirty rectangles для решти, і додали вочдога, що виявляє, коли blit-и
уповільнюються і плавно знижує якість анімації. Також вони зафіксували використання пам’яті, щоб уникнути свопінгу.
Урок: гладкий кадр марний, якщо ви не можете його підтримувати. Не оптимізуйте за естетикою, не помірявши шину.

Міні-історія 3: Нудна, але правильна практика, що врятувала день (baseline capture + rollback)

Фінансовий відділ роками запускав легасі X11-додаток на Linux thin client-ах. Це було негарно, але стабільно.
Команда кінцевих точок мала одну звичку, що виглядала надзвичайно консервативно: перед будь-яким оновленням драйвера вони робили знімок бази
— hardware IDs, kernel modules, Xorg логи і базові 2D метрики. Потім зберігали це з запитом на зміну.

Вендор запустив «оновлення безпеки», що включало оновлення стеку графіки. Після розгортання на підмножині користувачі повідомили,
що переміщення вікон залишає шлейфи, а перерисовування тексту лагало. Не у всіх — тільки на певних моделях. Служба підтримки почала збирати скріншоти.
Інженери почали гадати. Саме так часу й гине.

Команда кінцевих точок порівняла нові логи з їх базою. Вони відразу побачили, що прискорення було вимкнене на уражених одиницях:
модуль драйвера змінився, але ті клієнти мали трохи інший ревізійний PCI ID. Новий стек вважав їх непідтримуваними і відкотився
до загального framebuffer-драйвера.

Оскільки у них були базові знімки, їм не знадобилась кризова кімната. Вони відкотили пакет графіки для тих моделей, зафіксували версії
і відкрили вендорський тикет з точними доказами: невідповідність модулів, шлях відкату і відтворювані кроки.
Урок: нудна інструментація перемагає героїчний дебаг. Базові знімки — це не папірці; це машина часу.

Жарт №2: Нічого так не піднімає мораль команди, як виявлення, що ваше «регресія продуктивності» насправді була «ми вимкнули прискорення». Ніби латати течу, увімкнувши воду назад.

Практичні завдання: команди, виводи та що означає вивід

Ці завдання припускають, що ви діагностуєте легасі-путь графіки на Linux: framebuffer, X11 або базовий DRM/KMS.
Навіть якщо ви не працюєте на ретро-обладнанні, ті самі перевірки виявляють класичні режими відмов: fallback-драйвери, вимкнене прискорення,
тиск пропускної здатності і шторми перерисовування.

Завдання 1: Визначте GPU / контролер графіки

cr0x@server:~$ lspci -nn | egrep -i 'vga|3d|display'
00:02.0 VGA compatible controller [0300]: Intel Corporation 82865G Integrated Graphics Controller [8086:2572] (rev 02)

Значення: Ви більше не гадаєте; у вас є vendor та device IDs.
Рішення: Знайдіть, який драйвер має прив’язуватися (i915, nouveau, mga тощо). Якщо бачите старий інтегрований контролер,
припускайте спільну смугу пам’яті і крихкі шляхи прискорення.

Завдання 2: Подивіться, який кернел-драйвер реально зв’язався з пристроєм

cr0x@server:~$ lspci -k -s 00:02.0
00:02.0 VGA compatible controller: Intel Corporation 82865G Integrated Graphics Controller (rev 02)
	Subsystem: Dell Device 0163
	Kernel driver in use: i915
	Kernel modules: i915

Значення: «Kernel driver in use» — це правда. «Kernel modules» — що могло б бути використано.
Рішення: Якщо воно каже vesafb або fbdev, коли ви очікуєте нативний DRM-драйвер, ймовірно, ви на повільному шляху.

Завдання 3: Підтвердіть стан DRM/KMS і виявте fallback на simpledrm

cr0x@server:~$ dmesg | egrep -i 'drm|fb0|simpledrm|vesafb' | tail -n 12
[    1.234567] simpledrm: framebuffer at 0xe0000000, 0x300000 bytes
[    1.234890] simpledrm: format=a8r8g8b8, mode=1024x768x32, linelength=4096
[    2.101010] [drm] Initialized i915 1.6.0 20201103 for 0000:00:02.0 on minor 0

Значення: На ранньому етапі завантаження може стартувати simpledrm і пізніше перейти на реальний драйвер. Це нормально.
Рішення: Якщо ви ніколи не бачите ініціалізації справжнього драйвера, ви застрягли на generic framebuffer. Очікуйте низької 2D-продуктивності.

Завдання 4: Перевірте Xorg на предмет вимкненого прискорення

cr0x@server:~$ grep -E "(EE|WW|Accel|glamor|uxa|sna)" /var/log/Xorg.0.log | tail -n 20
[    22.123] (II) modeset(0): glamor X acceleration enabled on Mesa DRI Intel(R) 865G
[    22.125] (WW) modeset(0): Disabling glamor because of old hardware
[    22.126] (II) modeset(0): Using shadow framebuffer

Значення: «shadow framebuffer» — це кодове слово для «програмне виконання робить додаткові копії».
Рішення: На старому обладнанні це може бути неминуче; тоді зменшіть перерисовування і глибину пікселя. На новішому обладнанні — це помилка конфігурації.

Завдання 5: Перевірте, який OpenGL-рендерер ви отримали (апаратний чи програмний)

cr0x@server:~$ glxinfo -B | egrep 'OpenGL vendor|OpenGL renderer|OpenGL version'
OpenGL vendor string: Mesa
OpenGL renderer string: llvmpipe (LLVM 15.0.7, 256 bits)
OpenGL version string: 4.5 (Compatibility Profile) Mesa 23.0.4

Значення: llvmpipe означає програмне рендерення. Ваш CPU тепер грає роль GPU.
Рішення: Якщо ви очікували апаратного прискорення — припиніть тонке налаштування додатка і виправляйте стек драйверів.
Якщо приймаєте програмне рендерення — обмежте роздільність/ефекти і бюджет CPU відповідно.

Завдання 6: Переконайтесь, що direct rendering увімкнено

cr0x@server:~$ glxinfo | grep -i "direct rendering"
direct rendering: Yes

Значення: «Yes» свідчить, що DRI працює, але не гарантує продуктивність (це все ще може бути програмним).
Рішення: Поєднайте з рядком renderer. Якщо direct rendering — «No», очікуйте сильного уповільнення і розривів.

Завдання 7: Підтвердіть поточний режим (роздільність + частота)

cr0x@server:~$ xrandr --current
Screen 0: minimum 320 x 200, current 1024 x 768, maximum 8192 x 8192
VGA-1 connected primary 1024x768+0+0 (normal left inverted right x axis y axis) 0mm x 0mm
   1024x768      60.00*+
   800x600       60.32
   640x480       59.94

Значення: У вас 1024×768@60. Це сирий піксельний бюджет, який ви маєте перерисовувати.
Рішення: Якщо продуктивність погана — спочатку знизьте роздільність або глибину кольору. Це найшвидша важіль з найбільшим ефектом.

Завдання 8: Перевірте, чи ядро повідомляє про зависання або ресети GPU

cr0x@server:~$ dmesg | egrep -i 'hang|reset|gpu|ring|fault' | tail -n 20
[  912.332100] i915 0000:00:02.0: GPU HANG: ecode 9:1:0x85dffffb, in Xorg [1234]
[  913.001234] i915 0000:00:02.0: Resetting chip for hang on rcs0

Значення: Ви маєте справу не з «повільно», а зі нестабільністю, що викликає зупинки.
Рішення: Зменшіть функції прискорення, спробуйте старіший/новіший драйвер або змініть навантаження (вимкніть композитинг).
Не замазуйте це стороною додатка шляхом вставляння sleep.

Завдання 9: Виміряйте завантаження CPU і контекстні переключення під час лагу UI

cr0x@server:~$ vmstat 1 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 2  0      0 512000  42000 320000    0    0     1     2  180  300 25 10 65  0  0
 5  1      0  98000  41000 250000    0    0     0   120  900 3200 65 20 10  5  0
 4  2  20480  12000  20000 120000   20   40    10   600 1200 5000 70 15  5 10  0

Значення: Зростання r, низький id і ненульові si/so свідчать про контенцію і свопінг.
Рішення: Якщо починається своп, спочатку вирішіть проблему пам’яті (знизити роздільність, вимкнути композитинг, зменшити кеші або додати RAM).
Своп перетворює «графіку» на розподілені системи, і не в приємному сенсі.

Завдання 10: Виявити тиск пропускної здатності пам’яті (швидкий проксі через perf)

cr0x@server:~$ sudo perf stat -a -e cycles,instructions,cache-misses,context-switches -d -- sleep 5
 Performance counter stats for 'system wide':

    12,345,678,901      cycles
     6,789,012,345      instructions              #    0.55  insn per cycle
       234,567,890      cache-misses
             12,345      context-switches

       5.001234567 seconds time elapsed

Значення: Низький IPC разом із високими cache misses під час стагнації узгоджується з обмеженням по пам’яті або шляхами копіювання.
Рішення: Зменшіть дотики до пікселів (dirty rectangles), зменшіть глибину кольору і уникайте per-pixel alpha blend-ів, що примушують зчитування.

Завдання 11: Перевірити статус композитора (частий прихований податок)

cr0x@server:~$ ps -ef | egrep -i 'picom|compton|mutter|kwin_x11' | grep -v grep
cr0x      1888     1  5 10:01 ?        00:02:11 picom --config /home/cr0x/.config/picom.conf

Значення: Композитор може перетворити прості 2D-копії в змішані текстури і додаткове буферування.
Рішення: На слабкому/старому GPU або при програмному рендерингу вимкніть композитинг. Якщо потрібен — налаштуйте (vsync вимк/увімк, тіні вимк).

Завдання 12: Зняти легкий X11-бенчмарк рендерингу (попередня перевірка)

cr0x@server:~$ x11perf -copywinwin500 | head -n 20
x11perf:  description:  local server
x11perf:  drawing to window 500x500
CopyWinWin500          200 reps @   4.50 msec (  444.4/sec): Copy 500x500 from window to window

Значення: Це апроксимує, як швидко система може копіювати помірний прямокутник — саме те, що роблять 2D UI старої школи.
Рішення: Порівнюйте між машинами або до/після змін. Якщо після оновлення воно в рази повільніше, підозрюйте fallback-драйвер.

Завдання 13: Перевірити деталі framebuffer-пристрою (коли ви справді в fbdev-ландії)

cr0x@server:~$ cat /sys/class/graphics/fb0/virtual_size
1024,768

Значення: Підтверджує віртуальний розмір framebuffer; корисно, коли додатки припускають один режим, а ядро обрало інший.
Рішення: Якщо це не відповідає очікуваному режиму, виправте KMS mode setting або конфіг Xorg перед тим, як чіпати додаток.

Завдання 14: Перевірити список модулів ядра на предмет конфліктуючих framebuffer

cr0x@server:~$ lsmod | egrep 'i915|nouveau|radeon|amdgpu|vesafb|simpledrm|fbdev' | head
i915                  3121152  3
drm_kms_helper         315392  1 i915
drm                   622592  4 drm_kms_helper,i915
simpledrm              20480  1

Значення: Кілька framebuffer-драйверів можуть співіснувати, але конфлікти можуть прив’язати вас до generic-драйвера.
Рішення: Якщо vesafb завантажений поруч із реальним DRM-драйвером і ви бачите проблеми, чорний список generic-у обережно й тестуйте.

Завдання 15: Виявити «шторми перерисовування» від додатка (високий трафік X11)

cr0x@server:~$ xrestop -b | head -n 12
res-base  win  pix  GC  col  fnt  pmap  other  total  PID  Login  Name
      36   12  820   18   12    2     0     45    945  2444 cr0x   legacy-dashboard
      22    8  120   10    6    1     0     18    177  1888 cr0x   picom

Значення: Зростання pixmap-ів і ресурсів може вказувати на надмірне офскрін-буферування або витоки, що погіршують продуктивність з часом.
Рішення: Якщо pixmap-и додатка ростуть нескінченно, розглядайте це як витік пам’яті; виправдана політика рестарту або патч.

Завдання 16: Перевірити диск IO і тиск журналювання (бо трапляється своп і логування)

cr0x@server:~$ iostat -xz 1 3
avg-cpu:  %user   %nice %system %iowait  %steal   %idle
          35.21    0.00   12.10    9.88    0.00   42.81

Device            r/s     w/s   rkB/s   wkB/s  avgrq-sz avgqu-sz   await  %util
sda              2.00   45.00   64.00  980.00     45.16     0.90   19.50  92.00

Значення: Високий %util і await вказують, що диск зайнятий; якщо UI лагатиме, можливо, ви пейджете або залежні від логів.
Рішення: Зупиніть IO-кровотечу: зменшіть рівень логування, перемістіть логи, додайте RAM або виправте диск. Графіка не існує ізольовано.

Швидкий план діагностики

Коли система «відчувається повільною», найшвидший спосіб втратити час — сперечатися про відчуття.
Запустіть наступне в порядку, і зазвичай ви визначите клас вузького місця за 10 хвилин.

Перший крок: переконайтесь, що ви не на fallback-драйвері

  • Запустіть lspci -k і перевірте, що очікуваний кернел-драйвер використовується.
  • Перевірте dmesg на наявність тільки simpledrm/vesafb без ініціалізації proper DRM-драйвера.
  • Перевірте glxinfo -B і подивіться, чи ви на llvmpipe.

Якщо ви на fallback: зупиніться. Виправте це спочатку. Все інше — це косметика на framebuffer.

Другий крок: ізолюйте, чи ви CPU-bound, memory-bound або IO-bound

  • vmstat 1 під час відтворення лагу: дивіться високий us/sy (CPU), високі si/so (swap), високий wa (IO wait).
  • iostat -xz 1, якщо з’являється своп або IO wait.
  • perf stat як швидкий сигнал для cache misses і поганого IPC під навантаженням.

Рішення: Якщо ви свопите або IO-bound — вирішіть пам’ять/диск спочатку. Якщо CPU завантажений — зменшіть навантаження програмного рендерера або увімкніть прискорення.
Якщо spike-ять cache misses — зменшіть торкання пікселів і копіювання.

Третій крок: безжально зменшіть піксельний бюджет

  • Знизьте роздільність (xrandr), потім протестуйте знову.
  • Зменшіть глибину кольору, якщо можливо (на легасі-стаках це ще можливо; на сучасних — рідше).
  • Вимкніть композитинг і «гладкі ефекти».

Рішення: Якщо продуктивність негайно покращується, ваш вузький напрямок — пропускна здатність/копіювання, а не «логіка додатка».

Четвертий крок: перевірте патерни перерисовування

  • Використовуйте x11perf для швидкої перевірки 2D-операцій.
  • Слідкуйте за ростом ресурсів з xrestop, щоб упіймати витоки або надмірне буферування.

Рішення: Якщо додаток генерує шторми перерисовування, виправляйте інвалідацію і кліпування в додатку, а не ганяйтесь за прапорами драйвера.

Поширені помилки (симптом → корінь → виправлення)

1) Миша рухається, але вікна «липнуть» при перетягуванні

Симптом: Курсор залишається чутливим; перетягування вікна лишає сліди; перерисовування відбувається шматками.

Корінь: Аппаратний курсор працює, але 2D-прискорення вимкнене; оновлення — це програмні копії через shadow framebuffer.

Виправлення: Підтвердьте прив’язування драйвера; вимкніть композитора; зменшіть глибину кольору/роздільність; переконайтесь у правильному Xorg-драйвері (modesetting vs vendor).

2) Гладко в лабораторії, повільно в полі

Симптом: Те саме ПЗ; різні сайти; тільки деякі машини повзають.

Корінь: Різні ревізії пристроїв або прошивки; драйвер відкатується для певних PCI ID; або замало пам’яті, через що починається своп.

Виправлення: Інвентаризація hardware IDs; порівняйте Xorg логи; зафіксуйте відомо-робочі версії драйверів по моделях; забезпечте мінімум RAM.

3) «Покращені візуали» спричиняють стутер без високого CPU

Симптом: UI підлаговує; CPU не завалений; користувач каже «липке» відчуття.

Корінь: Насичення шини/VRAM; вищий bpp і alpha blending збільшили трафік пам’яті; потоки блокуються в драйверних викликах.

Виправлення: Зменшіть bpp/ефекти; кліпайте області перерисовування; замініть per-pixel blends на передкомпозитні ресурси; застосуйте dirty rectangles.

4) Випадкові чорні кадри або мерехтіння після увімкнення подвійного буфера

Симптом: Періодичне затемнення, особливо під навантаженням; інколи тільки на певних моніторах.

Корінь: Повні blit-и пропускають таймінг оновлення; page flipping не підтримується надійно; тиск VRAM викликає помилки алокацій.

Виправлення: Гібридна буферизація: буфер тільки анімовані області; використовувати vsync/page-flip лише коли підтримується; зменшити роздільність; обмежити FPS.

5) Продуктивність погіршується протягом годин

Симптом: Починається добре; поступово лаги; перезавантаження «виправляє».

Корінь: Витік ресурсів (pixmaps, офскрін поверхні), поступове зростання свопу, наростання IO логування, або роздування кешу композитора.

Виправлення: Слідкуйте за ресурсами (xrestop), пам’яттю (vmstat), диском (iostat); впровадьте політику рестартів; виправте витоки.

6) Розриви видимі при анімаціях і прокрутці

Симптом: Горизонтальні лінії розривів під час руху.

Корінь: Немає vsync/page flipping; прямі записи у front buffer; композитор вимкнений або неправильно налаштований.

Виправлення: Увімкніть vsync, де підтримується; використовуйте композитинг на придатному обладнанні; або зменшіть рух/вартість оновлення, якщо обладнання не витягує.

7) «Ми увімкнули прискорення», але стало гірше

Симптом: Вищий CPU, нижча відзивчивість після перемикання драйверів.

Корінь: Шлях прискорення викликає дорогі відкатні операції (наприклад, unsupported operations призводять до readbacks); невідповідність Mesa/драйвера.

Виправлення: Підтвердіть фактичний renderer (glxinfo -B); спробуйте альтернативний метод прискорення (UXA/SNA/glamor залежно від стеках);
тримайте версії узгодженими; надавайте перевагу меншій кількості стабільних функцій над багатими, але проблемними.

Контрольні списки / покроковий план

Покроково: стабілізувати легасі-графічне середовище

  1. Інвентаризація обладнання. Зніміть lspci -nn і збережіть з профілем машини.

    Чому: Різні ревізії поводяться по-різному; ви не зможете керувати тим, чого не назвали.
  2. Зафіксуйте відомо-робочі драйвери по класу обладнання.

    Чому: Стеки графіки регресують. Трактуйте їх як ядра: поетапне розгортання і фіксація версій.
  3. Базова продуктивність. Збережіть x11perf -copywinwin500, роздільність, стан композитора.

    Чому: Коли хтось каже «здається повільніше», ви зможете відповісти цифрами.
  4. Встановіть розумний режим за замовчуванням. Оберіть роздільність і частоту, які підтримує обладнання.

    Чому: Найдешевший виграш у продуктивності — це менше пікселів.
  5. Рішіть питання композитингу явно. Або вимкніть його, або налаштуйте; не дозволяйте йому «просто статися».

    Чому: Композитори додають буферування і змішування — саме там старі системи вмирають.
  6. Бюджет пам’яті. Переконайтеся, що система не свопитиме під нормальним навантаженням.

    Чому: Своп перетворює дрібні затримки на секунди мовчання.
  7. Контролюйте патерни перерисовування у додатках. Віддавайте перевагу dirty rectangles; уникайте повних перерисовок вікна за таймером.

    Чому: Записи у фреймбуфер — ваш найдорожчий «API-виклик».
  8. Тестуйте з кейсами найгіршого випадку. Найбільші шрифти, найбільш загружені екрани, максимальна щільність даних.

    Чому: Якщо воно ледве проходить у ідеальних умовах — воно впаде в проді.
  9. Визначте режими деградації. Зменшення анімацій, зниження альфа, відкат до простішого рендерингу при падінні продуктивності.

    Чому: Стабільний «менш гарний» UI краще за гарний UI, що зависає.
  10. Підтримуйте можливість відкату. Зберігайте останні відомо-робочі пакунки і конфіги.

    Чому: Коли графіка ламається, часто треба відновити без локального робочого UI.

Контрольний список: валідація перед зміною (оновлення драйвера, OS, новий UI)

  • Підтвердьте прив’язку кернел-драйвера (lspci -k).
  • Перевірте шлях renderer (glxinfo -B).
  • Запишіть поточний режим (xrandr --current).
  • Зробіть швидкий 2D-бенчмарк (набір тестів x11perf).
  • Підтвердьте вибір композитора і його конфіг (ps -ef).
  • Переконайтесь, що після стресу немає GPU hangs у логах (dmesg).
  • Перевірте запас пам’яті під навантаженням (vmstat).
  • Переконайтесь, що диск не насичений (iostat), особливо для тонких клієнтів з дешевою флеш-пам’яттю.

Контрольний список: аварійна відповідь, коли UI непридатний

  • Переключіться на нижчу роздільність через віддалений шелл, де можливо.
  • Вимкніть композитинг і перезапустіть сесію.
  • Відкотіть пакети стеку графіки до бази.
  • Якщо застрягли в fbdev, завантажтесь з відомими параметрами ядра і переконайтесь у завантаженні модулів.
  • Зменшіть навантаження додатка: вимкніть анімації, знизьте частоту оновлення, спростіть візуали.

Питання та відповіді

1) Що насправді робила «графічна карта» до ери GPU?

Зазвичай: виводила фреймбуфер на монітор, керувала палітрою і, можливо, прискорювала 2D-операції, як копіювання прямокутників і заповнення.
CPU все ще малював більшість речей, особливо те, що не було простим блоковим перенесенням.

2) Чому 320×200 був таким поширеним в старих PC-іграх?

Тому що це було швидко і просто. Воно добре вміщувалось у пам’яті, лінійно відображалось у знаменитому 256-колірному режимі,
і не вимагало багато пропускної здатності. Ігри могли оновлювати помірну частину екрану без падіння продуктивності.

3) Що таке «blitter» і чому це має значення?

Blitter — це апарат, присвячений переміщенню блоків пікселів (BitBLT) і іноді простим растровим операціям.
Він був важливий, бо UI і 2D-ігри домінуються операціями «копіюй цей прямокутник», а не «вираховуй цей трикутник».
З операційної точки зору це DMA-двигун для пікселів.

4) Чи завжди програмне рендерення було повільним?

Не завжди. Воно часто було дивовижно конкурентним, бо CPU міг бути пристойним у математиці, а хитрі програмісти мінімізували записи пам’яті.
Але воно було крихким: один додатковий прохід по фреймбуферу, ще один бленд або вища глибина кольору могли зруйнувати продуктивність.

5) Чому зміни глибини кольору спричиняли катастрофи?

Бо пропускна здатність і обсяг зберігання масштабуються з байтами на піксель. Перехід з 16bpp на 32bpp подвоює трафік фреймбуфера.
На старих шинах і інтегрованих графіках це не «дрібниця»; це може бути весь бюджет.

6) Як уникали мерехтіння без сучасних композиторів?

Використовували dirty rectangles, ретельне замовлення малювання, таймінг оновлень на вертикальний бланк, коли можливо, і іноді page flipping,
якщо апарат підтримував кілька буферів. Вони також проектували UI, що не перерисовувався постійно — бо інакше не було можливості.

7) Який сучасний еквівалент «вузького місця фреймбуфера»?

Будь-коли, коли домінують копії пам’яті і пропускна здатність: програмний композитинг, віддалені робочі столи, що штовхають повні оновлення екрана,
або додатки, що змушують GPU робити readback-и. Назви змінились; фізика — ні.

8) Якщо моя система показує llvmpipe, чи це завжди погано?

Залежить від навантаження. Для статичних панелей або легкого 2D це може бути прийнятно. Для важкого композитингу, відео чи 3D — зазвичай проблема.
Практичний крок: розглядати llvmpipe як сигнал пропускної здатності: ви витрачаєте CPU на графіку.

9) Який є найвищий за ефектом важіль налаштування в старих графічних системах?

Зменшити пікселі, що торкаються в секунду. Зазвичай це означає нижчу роздільність, менше повних перерисовок вікна, менше блендів і менше композитингу.
Якщо оптимізувати, спочатку оптимізуйте стратегію перерисовування до мікрооптимізації математики.

10) Чому проблеми легасі-графіки відчуваються «випадковими»?

Бо вони часто знаходяться на перетині ревізій апаратури, прошивок і fallback-драйверів.
Дві машини, що виглядають однаковими для закупівель — можуть поводитися по-різному для драйвера.
Ось чому базові знімки і hardware IDs важливі.

Висновок: практичні наступні кроки

До ери NVIDIA і GPU «графіка» була бюджетом, який можна було порахувати: байти на піксель, пікселі на кадр, кадри на секунду
та шина, що має це все перенести. Інженерна культура, що виникла з того періоду — dirty rectangles, палітрові трюки,
обережне буферування і підозра до «безкоштовних» візуальних покращень — не була ностальгією. Це працювало в умовах жорстких обмежень.

Якщо ви оперуєте або модернізуєте щось, що все ще пахне тією епохою (вбудовані кіоски, thin client-и, промислові HMI,
віддалені робочі столи, легасі X11-додатки), зробіть три речі цього тижня:

  1. Доведіть шлях рендерингу. Підтвердіть реальний драйвер і renderer у використанні; покінчіть з тихими fallback-ами.
  2. Зніміть базу і зафіксуйте. Збережіть логи і прості бенчмарки, і закріпіть відомо-робочий стек графіки по класу обладнання.
  3. Зменшіть перерисовування. Знизьте торкання пікселів: роздільність, глибина кольору, композитинг і стратегію перерисовування.

Світ до GPU не був лагідніший. Він був просто чесніший: ви могли побачити вузьке місце своїми очима.
Використайте ту чесність як діагностичну перевагу, і ви утримаєте навіть вперту легасі-графіку стабільною настільки, щоб бізнес міг працювати.

← Попередня
Docker: обмеження швидкості та WAF перед контейнерами без блокування реальних користувачів
Наступна →
MySQL проти Percona Server: продуктивність під час піків — що змінюється на практиці

Залишити коментар