Add parallel rendering#84
Conversation
Co-authored-by: Andrey Sitnik <andrey@sitnik.ru>
| } | ||
|
|
||
| let originSize = new Map<HTMLCanvasElement, [number, number]>() | ||
| export let originSize = new Map<HTMLCanvasElement, [number, number]>() |
There was a problem hiding this comment.
А зачем экспорт? Этот Map вроде был нужен для понижения разрешения и сейчас больше не нужен.
| color: string | ||
| ): void { | ||
| let pos = 4 * (y * pixels.width + x) | ||
| let colorArr = color |
There was a problem hiding this comment.
Такой обратный парсинг — грязно. Лучше измени paintSeparator, чтобы там нормально конвертировать цвет в RGB и тогда не нужно будет и этой функции.
| pixels.data[pos + 3] = +colorArr[3] * 255 | ||
| } | ||
|
|
||
| export function trackTime(cb: () => void): number { |
There was a problem hiding this comment.
trackTime не имеет отношения к рисованию, чтобы быть тут. Она по сути же может замерять что угодно. Создай lib/time.js.
| @@ -1,4 +1,4 @@ | |||
| lockfileVersion: 5.4 | |||
| lockfileVersion: 5.3 | |||
There was a problem hiding this comment.
Обнови pnpm и откати изменение файла
| @@ -1,12 +1,12 @@ | |||
| import { atom, map } from 'nanostores' | |||
| import { setStart, resetFreeze, reportFreeze } from './benchmark.js' | |||
There was a problem hiding this comment.
ESLint тут ругается, потому что у меня импорты группируются — из npm идут отдельным блоком, из проекта — другим.
Перенеси этот импорт в группу ниже.
|
|
||
| for (let i = 0; i < availableWorkers; i++) { | ||
| let renderType: RenderType = | ||
| canvas === canvasL ? 'l' : canvas === canvasC ? 'c' : 'h' |
There was a problem hiding this comment.
Вложенные a ? b : c — плохая практика (мозг ломается при попытке такое прочитать). ESLint тут тебе и кидает поэтому предупреждение.
Переделай на обычные if.
There was a problem hiding this comment.
у if своя область видимости и я подумал что это немного перегрузит функцию поэтому просто в параметр перекинул
| export type RenderType = 'l' | 'c' | 'h' | ||
|
|
||
| export let lastBenchmark = map({ freeze: 0, quick: 0, full: 0 }) | ||
| export let lastBenchmark = map({ freezeSum: 0, freezeMax: 0, frame: 0, full: 0 }) |
There was a problem hiding this comment.
full непонятно о чём речь.
Давай переименуем в frame → paint и full → workersSum. И так же во всех функциях и в UI.
| color: string, | ||
| line: [number, number][] | undefined | ||
| ): void { | ||
| let colorArr = color |
There was a problem hiding this comment.
Прошлый комментарий был про то, что парсить rgb() — нельзя. Зачем перенёс просто сюда?
Я предлагаю отпарсить цвет нормально вызвав rgb(string) и получив нормальные цифры. Только сделай это один раз, там где достаются цвета разделителя.
There was a problem hiding this comment.
а что за rgb(string)...
There was a problem hiding this comment.
ладно я нашел какую-то регулярку надеюсь так можно...
There was a problem hiding this comment.
rgb() из lib/colors.js может парсить rgb()
| y: number, | ||
| colorArr: string[] | ||
| ): void { | ||
| let pos = 4 * (y * pixels.width + x) |
There was a problem hiding this comment.
Сейчас paintSeparatorPixel стала слишком маленькой, переноси код в paintSeperator
| count: 0, | ||
| total: 0, | ||
| prevScale: 1 | ||
| export function setStart(ms: number): void { |
There was a problem hiding this comment.
Не понятно, что за start. Давай, например, setFrameStart(ms).
| quick[type].prevScale = scale | ||
| return scale | ||
| export function resetFreeze(): void { | ||
| lastBenchmark.get().freezeMax = 0 |
There was a problem hiding this comment.
Значения можно менять только через setKey()
| lastBenchmark.get().freezeSum = 0 | ||
| } | ||
|
|
||
| export function reportFull(ms: number): void { |
There was a problem hiding this comment.
У тебя одно и то же имя аргумента используется и для продолжительности и для времени.
Давай тут использовать time (и так же в setFrameStart).
| export function getLastBenchmarkColor(): string { | ||
| let { freeze } = lastBenchmark.get() | ||
| let hue = BEST_HUE - ((BEST_HUE - WORST_HUE) * freeze) / MAX_TIME | ||
| let hue = BEST_HUE - ((BEST_HUE - WORST_HUE) * lastBenchmark.get().freezeSum) / MAX_TIME |
There was a problem hiding this comment.
Строка длиннее 80 символов (и кажется ты не везде Prettier запускаешь).
Верни подход, что мы достаём переменную на отдельной строчке.
| runListeners(changeListeners, prev) | ||
| } | ||
| }) | ||
| export let framesToChange = atom<number>(0) |
There was a problem hiding this comment.
Передавай framesToChange как обычное число в аргументы listener. Типа i.l(value.l, framesToChange).
Это будет проще, чем заводить отдельный стор. Всё равно тебе framesToChange нужен в том же listener.
| message: object, | ||
| transfer: (Transferable | HTMLCanvasElement)[] | ||
| ): void | ||
| postMessage(message: object, transfer: Transferable[]): void |
There was a problem hiding this comment.
Давай вернём старый тип, он правильнее и может в будущем пригодиться
| export function formatRgb(c: string): string | undefined | ||
|
|
||
| export type Color = Hsl | Lab | Lch | Oklab | Oklch | Xyz65 | P3 | Rec2020 | Rgb | ||
| export type Color = |
There was a problem hiding this comment.
Откати (кажется у тебя старый Prettier)
| = "Freeze " | ||
| strong.benchmark_freeze | ||
| = "Freeze sum " | ||
| strong.benchmark_freeze_sum |
There was a problem hiding this comment.
У меня система именования CSS-классов вида .block-name_element-name. Тут должно быть benchmark_freeze-sum.
| @@ -0,0 +1,100 @@ | |||
| import type { RenderType } from '../../stores/benchmark' | |||
There was a problem hiding this comment.
| import type { RenderType } from '../../stores/benchmark' | |
| import type { RenderType } from '../../stores/benchmark.js' |
На конце импортов по правилам ESM всегда должно быть расширение. Ниже так же исправь (и проверь остальные импорты).
| let unbusyWorkers: Worker[] = [] | ||
| let busyWorkers: Worker[] = [] | ||
|
|
||
| let totalWorkers = navigator.hardwareConcurrency |
There was a problem hiding this comment.
Лучше написать так let totalWorkers = navigator.hardwareConcurrency ?? 12
?? делает то же, только короче и чуть правильнее (проверяет что это именно undefined, а не false).
Ну и 12 воркеров мало у кого сейчас есть. Давай тут хотя бы 8.
| ...busyWorkers.splice(busyWorkers.indexOf(worker), 1) | ||
| ] | ||
|
|
||
| if (e.data.renderType === 'l') { |
There was a problem hiding this comment.
Логика для l, c и h очень похожая. Надо её куда-то вынести.
| let ctx = getCleanCtx(canvasC) | ||
|
|
||
| ;[...pixelsC, e.data].forEach(pixels => { | ||
| let { pixelsBuffer, pixelsWidth, pixelsHeight, xPos } = pixels |
There was a problem hiding this comment.
А зачем тут так? Если ниже писать pixelsBuffer вместо pixels.pixelsBuffer то будет не сложнее.
| worker.onmessage = (e: MessageEvent<PaintedMessageData>) => { | ||
| let start = Date.now() | ||
|
|
||
| unbusyWorkers = [ |
There was a problem hiding this comment.
Очень сложно читать. Давай разделим доставание из одного массива и помещение в другой массив.
| availableWorkers: number, | ||
| renderType: RenderType, | ||
| canvas: HTMLCanvasElement, | ||
| lch: number |
There was a problem hiding this comment.
lch название для LCH-цвета. Давай лучше value.
* move drawing to OffscreenCanvas * correct quotes and tabs * prettier * prettier * prettier * pnpm lock * fix errors * fix errors * increase size limit * fix types * fix package * fix types * fix types * fix types * test without worker * test with worker * fix eslint * fix eslint * Update .size-limit.json Co-authored-by: Andrey Sitnik <andrey@sitnik.ru> * fix reportFreeze * fix dynamic scaling * ifx types * fix * . * add job queue * report paint * general queue * no queue * report freeze * add parallel rendering * benchmark * clg * clg * retina * Revert "clg" * only last pending test * no retina * hardwareConcurrency * fix * shared workers * fix * fix eslint * fix * fix * fix * rename benchmark --------- Co-authored-by: Andrey Sitnik <andrey@sitnik.ru>
в сафари и ff работает, багов нет. единственное что в paintSeparatorPixel() как-то неправильно отрабатывает альфа канал. вместо прозрачности у линий как-будто инвертируется фоновый черный цвет