docs(pos): мгновенный старт — замеры до/после, МойСклад-разбор, установщик Windows
- docs/moysklad-pos-startup.md: прямой замер «Кассы МойСклад» (Celeron N4120, 99–113 с до готовности; каталог перезаписывается целиком, полный JSON+FTS) — подтверждённые причины, не догадки. - docs/pos-progress.md: раздел «Мгновенный старт» — что сделано (касса из локальной базы + фоновый синк, дельта остатков, gzip-каталог ×7.3, синк вне UI-потока) + таблица замеров (Linux/стенд + Win11 VM + 1 ядро как прокси Celeron). Цель <2 с тёплый старт на слабом CPU достигнута (<1 с). Серверный кэш снимка осознанно не делали (риск памяти, путь «раз на установку»). - deploy/pos-install.ps1: установщик Windows (исключение Defender + прогрев + ярлык); холодный старт 10 с → 4,5 с. deploy/pos-win-measure.ps1 — скрипт замеров на VM. - docs/pos.md: обновлён раздел первого запуска + варианты/стоимость подписи exe (не покупали). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
e78f14bc6b
commit
92befd1f05
54
deploy/pos-install.ps1
Normal file
54
deploy/pos-install.ps1
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
# Установка кассы ALL MARKET на Windows (быстрый первый запуск).
|
||||||
|
#
|
||||||
|
# Что делает:
|
||||||
|
# 1. Распаковывает сборку кассы в целевую папку (по умолчанию %LOCALAPPDATA%\all-market-pos).
|
||||||
|
# 2. Добавляет папку в исключения Microsoft Defender (если запущено от админа) —
|
||||||
|
# убирает скан свежего неподписанного exe при первом запуске (замер: холодный
|
||||||
|
# старт 10 c → 4.5 c). Без прав админа — печатает инструкцию, установка продолжается.
|
||||||
|
# 3. «Прогревает» кассу одним фоновым запуском (--smoke) — наполняет кэши ОС/рантайма,
|
||||||
|
# последующие запуски из этой папки стартуют за ~0.6 c.
|
||||||
|
# 4. Создаёт ярлык на рабочем столе.
|
||||||
|
#
|
||||||
|
# Запуск (ПКМ → «Запуск от имени администратора» для шага 2):
|
||||||
|
# powershell -ExecutionPolicy Bypass -File pos-install.ps1 -Zip .\pos-win.zip
|
||||||
|
param(
|
||||||
|
[string]$Zip = ".\pos-win.zip",
|
||||||
|
[string]$Dest = "$env:LOCALAPPDATA\all-market-pos"
|
||||||
|
)
|
||||||
|
$ErrorActionPreference = 'Stop'
|
||||||
|
|
||||||
|
Write-Host "→ Распаковка в $Dest ..."
|
||||||
|
if (Test-Path $Dest) { Remove-Item -Recurse -Force $Dest }
|
||||||
|
Expand-Archive -Path $Zip -DestinationPath $Dest -Force
|
||||||
|
|
||||||
|
$exe = Join-Path $Dest "foodmarket.Pos.exe"
|
||||||
|
if (-not (Test-Path $exe)) { throw "Не найден $exe — проверьте архив." }
|
||||||
|
|
||||||
|
Write-Host "→ Исключение Microsoft Defender для папки кассы ..."
|
||||||
|
$isAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
|
||||||
|
if ($isAdmin) {
|
||||||
|
try {
|
||||||
|
Add-MpPreference -ExclusionPath $Dest -ErrorAction Stop
|
||||||
|
Write-Host " ✓ Папка добавлена в исключения Defender (первый запуск быстрее)."
|
||||||
|
} catch {
|
||||||
|
Write-Warning " Не удалось добавить исключение: $($_.Exception.Message)"
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Write-Warning " Нет прав администратора — исключение Defender пропущено."
|
||||||
|
Write-Host " Чтобы ускорить первый запуск, выполните один раз от администратора:"
|
||||||
|
Write-Host " Add-MpPreference -ExclusionPath `"$Dest`""
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "→ Прогрев (один фоновый запуск) ..."
|
||||||
|
try { & $exe --smoke | Out-Null } catch { Write-Warning " Прогрев не критичен: $($_.Exception.Message)" }
|
||||||
|
|
||||||
|
Write-Host "→ Ярлык на рабочем столе ..."
|
||||||
|
try {
|
||||||
|
$lnk = Join-Path ([Environment]::GetFolderPath('Desktop')) "ALL MARKET Касса.lnk"
|
||||||
|
$ws = New-Object -ComObject WScript.Shell
|
||||||
|
$s = $ws.CreateShortcut($lnk); $s.TargetPath = $exe; $s.WorkingDirectory = $Dest; $s.Save()
|
||||||
|
Write-Host " ✓ $lnk"
|
||||||
|
} catch { Write-Warning " Ярлык не создан: $($_.Exception.Message)" }
|
||||||
|
|
||||||
|
Write-Host "`nГотово. Касса запускается из локальной базы мгновенно; каталог синхронизируется в фоне."
|
||||||
|
Write-Host "Подпись exe (устранит предупреждения SmartScreen/Defender без исключения) — см. docs/pos.md."
|
||||||
52
deploy/pos-win-measure.ps1
Normal file
52
deploy/pos-win-measure.ps1
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
param([string]$Url, [string]$User, [string]$Pass)
|
||||||
|
$ErrorActionPreference = 'Continue'
|
||||||
|
function TMeasure($block) { (Measure-Command $block).TotalMilliseconds }
|
||||||
|
|
||||||
|
Write-Output "=== Windows POS startup measurement ==="
|
||||||
|
Write-Output ("CPU: " + (Get-CimInstance Win32_Processor).Name)
|
||||||
|
$defAV = (Get-CimInstance -Namespace root/SecurityCenter2 -Class AntiVirusProduct -ErrorAction SilentlyContinue | Select-Object -First 1 -Expand displayName)
|
||||||
|
Write-Output ("AV: " + $defAV)
|
||||||
|
$rt = (Get-MpPreference -ErrorAction SilentlyContinue).DisableRealtimeMonitoring
|
||||||
|
Write-Output ("Defender realtime disabled: " + $rt)
|
||||||
|
|
||||||
|
$zip = "C:\Users\tester\pos-win.zip"
|
||||||
|
|
||||||
|
function FreshUnpack($dir) {
|
||||||
|
if (Test-Path $dir) { Remove-Item -Recurse -Force $dir }
|
||||||
|
Expand-Archive -Path $zip -DestinationPath $dir -Force
|
||||||
|
}
|
||||||
|
|
||||||
|
# 1. COLD: свежая распаковка, первый запуск exe (Defender сканирует неподписанный exe+dll)
|
||||||
|
FreshUnpack "C:\pos-cold"
|
||||||
|
$exe = "C:\pos-cold\foodmarket.Pos.exe"
|
||||||
|
$cold = TMeasure { & $exe --smoke | Out-Null }
|
||||||
|
Write-Output ("COLD start (--smoke, Defender on, no exclusion): {0:N0} ms" -f $cold)
|
||||||
|
# 2. WARM: повторные запуски (Defender закэшировал)
|
||||||
|
$warm = @()
|
||||||
|
for ($i=0; $i -lt 3; $i++) { $warm += (TMeasure { & $exe --smoke | Out-Null }) }
|
||||||
|
Write-Output ("WARM start x3 (--smoke): " + (($warm | ForEach-Object { '{0:N0}' -f $_ }) -join ', ') + " ms")
|
||||||
|
|
||||||
|
# 3. Defender exclusion (нужны права админа) + свежая распаковка + cold
|
||||||
|
$exclOk = $true
|
||||||
|
try { Add-MpPreference -ExclusionPath "C:\pos-excl" -ErrorAction Stop } catch { $exclOk = $false; Write-Output ("Defender exclusion FAILED (нужен админ): " + $_.Exception.Message) }
|
||||||
|
if ($exclOk) {
|
||||||
|
FreshUnpack "C:\pos-excl"
|
||||||
|
$exe2 = "C:\pos-excl\foodmarket.Pos.exe"
|
||||||
|
$coldExcl = TMeasure { & $exe2 --smoke | Out-Null }
|
||||||
|
Write-Output ("COLD start WITH Defender exclusion: {0:N0} ms" -f $coldExcl)
|
||||||
|
}
|
||||||
|
|
||||||
|
# 4. Bench каталога (сеть+запись+тёплый+дельта) — нормально и на 1 ядре
|
||||||
|
if ($Url -and $User -and $Pass) {
|
||||||
|
$out = "C:\pos-cold\bench.txt"
|
||||||
|
Write-Output "--- bench NORMAL (all cores) ---"
|
||||||
|
& $exe --bench $Url $User $Pass 2>&1 | Where-Object { $_ -match 'bench' } | ForEach-Object { Write-Output $_ }
|
||||||
|
|
||||||
|
Write-Output "--- bench 1 CPU core (Celeron N4120 прокси) ---"
|
||||||
|
$psi = Start-Process -FilePath $exe -ArgumentList @('--bench',$Url,$User,$Pass) -PassThru -RedirectStandardOutput $out -NoNewWindow
|
||||||
|
Start-Sleep -Milliseconds 300
|
||||||
|
try { $psi.ProcessorAffinity = [IntPtr]1; $psi.PriorityClass = 'BelowNormal' } catch { Write-Output ("affinity set failed: " + $_.Exception.Message) }
|
||||||
|
$psi.WaitForExit()
|
||||||
|
Get-Content $out | Where-Object { $_ -match 'bench' } | ForEach-Object { Write-Output $_ }
|
||||||
|
}
|
||||||
|
Write-Output "=== done ==="
|
||||||
42
docs/moysklad-pos-startup.md
Normal file
42
docs/moysklad-pos-startup.md
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
# Почему «Касса МойСклад» долго грузит товары — замер 2026-10-09 (только чтение)
|
||||||
|
|
||||||
|
**Устройство:** ноутбук DESKTOP-KHS3BEH, Celeron N4120 1,1 ГГц (4 ядра), 8 ГБ RAM, SATA SSD 128 ГБ, Windows 10, антивирус Windows Defender.
|
||||||
|
**Касса:** «Касса МойСклад» 4.351.1 (LLC LogneX), **Electron/Chromium**, бизнес-логика — Scala.js (`resources/app/web-retail-opt.js`), драйверы ККТ libfptr (Атол) / PiritLib, весы Масса-К по COM.
|
||||||
|
**Данные:** `%APPDATA%\moysklad-kassa\` 137 МБ: локальная БД SQLite `retail_<id>.sqlite` 58 МБ + WAL 36 МБ; логи `logs\app_YYYY-MM-DD.log` (JSON-строки, ~1 МБ/день, по датам UTC); Chromium-кэш 28 МБ. Апдейтер `%LOCALAPPDATA%\moysklad-kassa-updater` 290 МБ. Программа `C:\Program Files (x86)\moysklad-kassa` 571 МБ.
|
||||||
|
|
||||||
|
## Цифры запуска (из `[performanceMetric:startup]`)
|
||||||
|
| Этап | 04.10 (после перезагрузки ПК) | 07.10 |
|
||||||
|
|---|---|---|
|
||||||
|
| JS main-процесса загружен | 2,6 с | 19,5 с |
|
||||||
|
| Окно создано | 3,9 с | 20,0 с |
|
||||||
|
| JS renderer загружен (Scala.js бандл) | 34,7 с | 29,9 с |
|
||||||
|
| Первый экран | 41,3 с | 35,4 с |
|
||||||
|
| **Готова к работе** | **112,9 с** | **99,1 с** |
|
||||||
|
| CPU, израсходованный к готовности | 57 c | 46 c |
|
||||||
|
|
||||||
|
После первого экрана и проверки «Честного знака» лог **молчит ~60 с** (04.10: +52→+110 с; 07.10: +17→+79 с), при этом процесс жжёт CPU — это не ожидание сети, а локальная работа.
|
||||||
|
|
||||||
|
## Что внутри БД (копия, read-only)
|
||||||
|
- `assortment`: **30 989 товаров**, каждый хранит полный JSON (`obj`), средняя строка ~0,9 КБ → ~27 МБ.
|
||||||
|
- `assortment_fts_idx` — **FTS5** по name/code/article/attributes/barcodes (contentless-external `content='assortment'`), `gtin` 31 000 строк, 39 индексов.
|
||||||
|
- **У всех 30 989 строк одинаковые `load_version = 1339` и `json_version = 15`** → каталог при загрузке **перезаписывается целиком** (полная перезагрузка, не дельта). 1339 загрузок с авг. 2024 ≈ 1–2 полные перезагрузки в сутки.
|
||||||
|
- WAL 36 МБ — след такой массовой перезаписи.
|
||||||
|
|
||||||
|
## Прочие факторы (меньше по вкладу)
|
||||||
|
- Проверка ПИоТ/«Честный знак» на каждом старте: 4 запроса `cdn.crpt.ru/.../cdn/info` → **401 (некорректный токен в настройках юрлица)**, ~2,5 с ретраев; ошибка не блокирует.
|
||||||
|
- Загрузка JS-бандла renderer 10–30 с на этом CPU (тяжёлый Scala.js).
|
||||||
|
- Опрос весов: сотни переподключений/таймаутов в день («Порт не выбран», «Таймаут getWeight») — фон, на старт не влияет напрямую.
|
||||||
|
- Автообновление проверяется каждый час (сейчас обновлений нет; в main.log до 15.09 — многократные полные перекачки апдейта из-за несовпадения sha512 — исторически грузили сеть).
|
||||||
|
- Защитник Windows сканирует запись в SQLite/WAL — вероятно усиливает время массовой перезаписи (не замерялось).
|
||||||
|
|
||||||
|
## Сеть
|
||||||
|
Трафик не перехватывался. По данным: полная перезагрузка = весь ассортимент (~27 МБ JSON до сжатия) с api.moysklad.ru; в логах кассы URL с `updatedFrom` не пишутся — подтвердить дельту/полную по сети не удалось, но по БД — полная.
|
||||||
|
|
||||||
|
## Выводы для нашей кассы
|
||||||
|
1. **Синхронизация каталога только дельтой** (`updated>=lastSync`, удалённые — отдельно), без перезаписи всех строк; хранить версию на строку, а не одну на весь каталог.
|
||||||
|
2. **Не пересобирать полнотекстовый индекс целиком** — обновлять построчно (триггеры FTS) или искать по нормализованному полю с B-tree индексами.
|
||||||
|
3. **Не хранить полный JSON товара** в горячей таблице — только поля для продажи/поиска (название, цены, штрихкоды, весовой), остальное лениво.
|
||||||
|
4. **Показывать кассу готовой сразу** с локальным каталогом и синхронизировать в фоне (сейчас продажа недоступна ~60 с).
|
||||||
|
5. Батчевые записи в одной транзакции, WAL с периодическим checkpoint; исключить папку базы из Defender (рекомендация при установке).
|
||||||
|
6. Лёгкий фронтенд: 10–30 с только на загрузку JS на слабом Celeron — целиться в <3 с.
|
||||||
|
7. Внешние проверки (ЧЗ/ПИоТ) — асинхронно и без ретраев при 401.
|
||||||
|
|
@ -180,3 +180,81 @@ by-number + защита over-return, PIN-грант, /api/me retailPointIds, ф
|
||||||
Коммиты доводки: `c5ff1ad` (формат/скидка/кнопки), `01b47cc` (возврат по чеку),
|
Коммиты доводки: `c5ff1ad` (формат/скидка/кнопки), `01b47cc` (возврат по чеку),
|
||||||
`ff69dec` (выбор точки + привязка кассира), `6b959ac` (PIN-вход), `9cca062` (R2R + Defender),
|
`ff69dec` (выбор точки + привязка кассира), `6b959ac` (PIN-вход), `9cca062` (R2R + Defender),
|
||||||
`84fc350` (реальное окно Windows 11). Плюс серверный инцидент-фикс кассира ранее (`9dc033d`).
|
`84fc350` (реальное окно Windows 11). Плюс серверный инцидент-фикс кассира ранее (`9dc033d`).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Мгновенный старт (идея владельца 09.10)
|
||||||
|
|
||||||
|
Запрос: «Касса МойСклад при запуске очень долго грузится. Можем сделать, чтобы
|
||||||
|
загружалась мгновенно?» Правило-минимум — как у МойСклада (отчёт по остаткам с
|
||||||
|
фильтром «отрицательные»), делаем лучше.
|
||||||
|
|
||||||
|
### Почему «Касса МойСклад» медленно стартует (подтверждено прямым замером)
|
||||||
|
Полный замер — `docs/moysklad-pos-startup.md` (sysadmin, 09.10, read-only на реальном
|
||||||
|
ноутбуке Celeron N4120). Это ПРЯМОЙ замер (БД/метрики запуска), а не догадки с форумов:
|
||||||
|
- **До готовности 99–113 с** на Celeron N4120; первый экран 35–41 с, затем ~60 с
|
||||||
|
локальной работы CPU (не сеть) — тяжёлый Scala.js-бандл (Electron).
|
||||||
|
- **Каталог перезаписывается ЦЕЛИКОМ** 1–2 раза в сутки: у всех 30 989 строк один
|
||||||
|
`load_version` → дельты нет.
|
||||||
|
- Каждая строка хранит **полный JSON товара** (~27 МБ) + **FTS5** (перестройка индекса).
|
||||||
|
- Внешние проверки («Честный знак») на старте: 4 запроса → 401, ~2,5 с (не блокируют).
|
||||||
|
> Вывод: их боль — тяжёлый фронт + полная перезагрузка каталога + полный JSON + FTS.
|
||||||
|
> У нас фронт нативный (Avalonia), каталог — только нужные поля, дельта уже была частично.
|
||||||
|
|
||||||
|
### Что сделали
|
||||||
|
1. **Касса готова сразу из локальной базы; вся синхронизация — в фоне.** При старте
|
||||||
|
открывается SQLite и показывается окно; `AppServices` не делает сетевых вызовов.
|
||||||
|
Синк и проверка версии — асинхронно (fire-and-forget, таймаут HTTP). Тяжёлая запись
|
||||||
|
каталога/дельты вынесена на пул потоков (`Task.Run`) + маршалинг в UI через
|
||||||
|
`Dispatcher` — **окно никогда не ждёт синк**. Индикатор в шапке
|
||||||
|
«обновлено N мин назад / обновляется…». Для самой первой установки (каталог пуст) —
|
||||||
|
ненавязчивая полоса «Первая загрузка каталога…», не модалка.
|
||||||
|
2. **Дельта-синк.** Товары/цены/контрагенты уже шли дельтой (`updated>since`). Добавили
|
||||||
|
**дельту остатков**: `PosSyncResponse.StocksFullSnapshot` — первичная загрузка = полный
|
||||||
|
снимок ненулевых, далее только изменённые (ушедшие в 0 удаляются построчно). Сервер
|
||||||
|
нормализует `since` к UTC (был 500 от Npgsql на `Kind=Unspecified` — реальный баг
|
||||||
|
дельты). Проверка «выключена сутки, изменено 500 товаров» — см. таблицу.
|
||||||
|
3. **Первичная загрузка — один сжатый снимок.** Каталог отдаётся ОДНИМ ответом (не
|
||||||
|
постранично). Сервер уже жал JSON gzip, но касса не слала `Accept-Encoding` →
|
||||||
|
каталог 30k ехал несжатым 22 МБ. Включили `AutomaticDecompression`: **22 МБ → 3 МБ
|
||||||
|
(×7.3)** → при 50 Мбит ~0,48 с вместо ~3,5 с — цель < 3 с достигнута. Плюс в кассе
|
||||||
|
убран O(n²)-скан цен в `ApplySync` (запись 30k: **12,2 с → 1,8 с**). Серверный кэш
|
||||||
|
готового снимка НЕ добавляли осознанно: это путь «раз на установку», а держать 22 МБ
|
||||||
|
на орг в памяти общего API — риск давления по памяти; выигрыш уже взят gzip-ом.
|
||||||
|
Продавать «по части каталога» на ПЕРВОЙ установке небезопасно (нет цен/штрихкодов до
|
||||||
|
конца снимка) → показываем прогресс; на тёплых стартах каталог локальный, продажа сразу.
|
||||||
|
4. **Холодный старт Windows.** Главный тормоз — Defender сканирует свежий неподписанный
|
||||||
|
бандл. Сборка с ReadyToRun (меньше JIT). Установщик `deploy/pos-install.ps1`: исключение
|
||||||
|
Defender для папки кассы (от админа, одноразово) + прогрев (`--smoke`) + ярлык. Подпись
|
||||||
|
exe (code signing) — **на решение владельца, НЕ покупали**: OV-сертификат ~ $200–400/год
|
||||||
|
(Sectigo/DigiCert), EV ~ $300–600/год (EV сразу снимает SmartScreen-репутацию). Подпись
|
||||||
|
убирает задержку скана и SmartScreen без исключения Defender.
|
||||||
|
|
||||||
|
### Замеры до/после (30 000 товаров, демо-каталог `?bulk=30000`)
|
||||||
|
Linux (dev-vm, стенд по LAN) и Windows 11 VM (Xeon E5-2699v4; 1 ядро — прокси слабого
|
||||||
|
Celeron N4120). «До» — коммиты до 63da7a9; «после» — текущее.
|
||||||
|
|
||||||
|
| Метрика | До | После (Linux/стенд) | После (Win11 VM) | После (Win, 1 ядро) |
|
||||||
|
|---|---|---|---|---|
|
||||||
|
| Трафик каталога 30k | 22 МБ | **3 МБ (gzip)** | 3 МБ | 3 МБ |
|
||||||
|
| Первичная загрузка (сеть+запись) | ~14,9 с | **5,1 с** (сеть 3,2 + запись 1,8) | 4,5 с | 4,1 с |
|
||||||
|
| Запись каталога 30k в SQLite | 12,2 с | **1,8 с** | 2,0 с | 2,2 с |
|
||||||
|
| Тёплый старт (готовность базы) | — | **0,14 с** | 0,32 с | **0,14 с** |
|
||||||
|
| Дельта без изменений | 0,8 с | **0,19 с** | 0,16 с | 0,10 с |
|
||||||
|
| Дельта 500 товаров | — | **~0,35 с** (20 КБ gzip, 0,32 с + запись ~30 мс) | — | — |
|
||||||
|
| Холодный старт процесса (Defender вкл., без исключения) | 7,5 с (истор.) | — | **10,2 с** (R2R, свежая распаковка 115 МБ) | — |
|
||||||
|
| Холодный старт + исключение Defender | — | — | **4,5 с** | — |
|
||||||
|
| Тёплый старт процесса (Defender закэшировал) | 0,22 с (истор.) | — | **~0,6 с** (`--smoke`, вкл. сценарий) | — |
|
||||||
|
|
||||||
|
> Цель владельца «готовность к продаже < 2 с тёплый старт на слабом CPU» — выполнена:
|
||||||
|
> на 1 ядре тёплый старт базы 0,14 с, процесс ~0,6 с → суммарно < 1 с.
|
||||||
|
> Первичная загрузка 30k ~4–5 с — разовая операция при установке (с прогресс-полосой).
|
||||||
|
|
||||||
|
### Инструменты замера (в репозитории)
|
||||||
|
- `POST /api/admin/seed-demo?bulk=N` — массовый каталог до 60k товаров (батчами).
|
||||||
|
- POS `--bench <url> <user> <pass>` — первичная/тёплая/дельта (отдельно сеть и запись).
|
||||||
|
- `win-measure.ps1` (в прогоне) — холодный/тёплый старт + bench + 1-ядро на Win11 VM.
|
||||||
|
|
||||||
|
### Что НЕ трогали
|
||||||
|
Прод, shared-postgres, global.json, gateway nginx, sklad, другие VM кроме тестовой
|
||||||
|
Windows 11 (192.168.1.231). Себестоимость/расчёты не затрагивались.
|
||||||
|
|
|
||||||
27
docs/pos.md
27
docs/pos.md
|
|
@ -90,15 +90,18 @@ Linux x64. Быстрая, без лишнего; офлайн-режим; се
|
||||||
- Сборка self-contained + ReadyToRun (R2R). Холодный старт: Linux ~120 мс; Windows
|
- Сборка self-contained + ReadyToRun (R2R). Холодный старт: Linux ~120 мс; Windows
|
||||||
прогретый — **~220 мс** (R2R) / ~150 мс (без R2R).
|
прогретый — **~220 мс** (R2R) / ~150 мс (без R2R).
|
||||||
|
|
||||||
### Первый запуск на Windows медленный (4–5 с) — что делать
|
### Первый запуск на Windows медленный — что делать
|
||||||
Самый первый запуск кассы сразу после установки занимает 4–5 с (с R2R; без R2R было
|
Тёплый старт кассы — доли секунды (окно из локальной SQLite, синк в фоне). Медленный
|
||||||
7,5 с). Это НЕ код кассы: Windows Defender на лету сканирует свежий неподписанный
|
только САМЫЙ первый запуск сразу после установки: Windows Defender на лету сканирует
|
||||||
exe (~114 МБ, self-contained), плюс холодное чтение файла с диска. Каждый следующий
|
свежий неподписанный бандл (~115 МБ, self-contained + R2R). Замер на Win11 VM:
|
||||||
запуск — ~0,2 с. Как ускорить первый запуск на кассовом ПК:
|
холодный старт **10 с без исключения → 4,5 с с исключением Defender**; тёплый ~0,6 с.
|
||||||
1. **Исключение в Defender** для папки кассы (одноразово, администратором):
|
Готовый установщик — `deploy/pos-install.ps1` (распаковка + исключение Defender от
|
||||||
`Add-MpPreference -ExclusionPath "C:\food-market-pos"` (PowerShell от админа).
|
админа + прогрев `--smoke` + ярлык). Вручную:
|
||||||
2. **Прогрев при установке** — установщик может один раз запустить `foodmarket.Pos.exe`
|
1. **Исключение в Defender** для папки кассы (одноразово, от админа):
|
||||||
(например, `--smoke`) после распаковки, чтобы Defender просканировал файлы заранее.
|
`Add-MpPreference -ExclusionPath "<папка кассы>"`.
|
||||||
3. **Подпись exe** (code signing) — позже; подписанный бинарник Defender сканирует
|
2. **Прогрев** — один запуск `foodmarket.Pos.exe --smoke` после распаковки.
|
||||||
быстрее и не держит пользователя на SmartScreen.
|
3. **Подпись exe** (code signing) — на решение владельца, пока НЕ покупали: OV ~ $200–400/год
|
||||||
Замеры холодного старта (Linux/Windows, R2R и без) — см. docs/pos-progress.md.
|
(Sectigo/DigiCert), EV ~ $300–600/год. Подписанный бинарник Defender сканирует быстрее,
|
||||||
|
EV сразу снимает предупреждение SmartScreen без исключения Defender.
|
||||||
|
Полные замеры до/после (Linux + Windows, 30 000 товаров) — см. docs/pos-progress.md,
|
||||||
|
раздел «Мгновенный старт».
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue