fix(ocr): 页面文件不足防护——双重预检+长期冷却
问题:EasyOCR worker启动报 WinError 1455(页面文件太小), 无法加载 cufft64_11.dll,物理内存充足但虚拟内存(已提交32.5/35.7GB)不足。 修复: 1. worker端:import前预检虚拟内存——剩余<2GB则直接exit(2),不进入torch/easyocr加载 2. worker端:import捕获WinError 1455时写入虚拟内存诊断信息(物理/页面/提交率) 3. 父进程端:启动worker前预检虚拟内存——<2GB直接冷却1小时,不启动worker 4. 父进程端:识别exit(2)/页面文件错误——冷却1小时而非30秒(系统级问题不反复重试) 诊断增强: - _get_virtual_memory_info():通过Win32 API获取物理/虚拟内存/页面文件状态 - 崩溃日志包含完整虚拟内存快照,便于排查 - 日志明确提示'增大Windows页面文件'
This commit is contained in:
+57
-1
@@ -19,6 +19,36 @@ import traceback
|
||||
from datetime import datetime
|
||||
|
||||
# ── 崩溃日志文件:写入源码目录根(easyocr_crash.log),统一管理、便于父进程读取 ──
|
||||
def _get_virtual_memory_info() -> dict:
|
||||
"""获取虚拟内存(页面文件)状态,用于诊断 WinError 1455。"""
|
||||
try:
|
||||
import ctypes
|
||||
class MEMORYSTATUSEX(ctypes.Structure):
|
||||
_fields_ = [
|
||||
("dwLength", ctypes.c_ulong),
|
||||
("dwMemoryLoad", ctypes.c_ulong),
|
||||
("ullTotalPhys", ctypes.c_ulonglong),
|
||||
("ullAvailPhys", ctypes.c_ulonglong),
|
||||
("ullTotalPageFile", ctypes.c_ulonglong),
|
||||
("ullAvailPageFile", ctypes.c_ulonglong),
|
||||
("ullTotalVirtual", ctypes.c_ulonglong),
|
||||
("ullAvailVirtual", ctypes.c_ulonglong),
|
||||
("ullAvailExtendedVirtual", ctypes.c_ulonglong),
|
||||
]
|
||||
mem = MEMORYSTATUSEX()
|
||||
mem.dwLength = ctypes.sizeof(MEMORYSTATUSEX)
|
||||
ctypes.windll.kernel32.GlobalMemoryStatusEx(ctypes.byref(mem))
|
||||
return {
|
||||
"total_phys_gb": round(mem.ullTotalPhys / (1024**3), 1),
|
||||
"avail_phys_gb": round(mem.ullAvailPhys / (1024**3), 1),
|
||||
"total_pagefile_gb": round(mem.ullTotalPageFile / (1024**3), 1),
|
||||
"avail_pagefile_gb": round(mem.ullAvailPageFile / (1024**3), 1),
|
||||
"commit_pct": round((1 - mem.ullAvailPageFile / max(mem.ullTotalPageFile, 1)) * 100, 1),
|
||||
}
|
||||
except Exception:
|
||||
return {}
|
||||
|
||||
|
||||
def _get_crash_log_path() -> str:
|
||||
try:
|
||||
base = os.path.dirname(os.path.abspath(__file__))
|
||||
@@ -67,11 +97,37 @@ try:
|
||||
os.environ.setdefault("OMP_NUM_THREADS", "1")
|
||||
os.environ.setdefault("MKL_NUM_THREADS", "1")
|
||||
|
||||
# ── 预检:虚拟内存是否足够加载 CUDA 库(cufft64_11.dll ~800MB) ──
|
||||
_vm = _get_virtual_memory_info()
|
||||
if _vm and _vm.get("avail_pagefile_gb", 99) < 2.0:
|
||||
_msg = (
|
||||
f"页面文件不足: 剩余{_vm.get('avail_pagefile_gb', '?')}GB"
|
||||
f"(提交{_vm.get('commit_pct', '?')}%)"
|
||||
f",CUDA库需要≥2GB连续虚拟地址空间"
|
||||
)
|
||||
_write_crash_log(f"{datetime.now()} [easyocr_worker] 页面文件预检失败: {_msg}")
|
||||
_flush_exit(f"页面文件不足: {_msg}", code=2)
|
||||
|
||||
from PIL import Image
|
||||
import numpy as np
|
||||
import easyocr
|
||||
except Exception as e:
|
||||
_flush_exit(f"import 失败: {e}\n{traceback.format_exc()}")
|
||||
_vm = _get_virtual_memory_info()
|
||||
_vm_hint = ""
|
||||
if _vm:
|
||||
_vm_hint = (
|
||||
f"\n[virtual memory] 物理内存: {_vm.get('avail_phys_gb',0)}/{_vm.get('total_phys_gb',0)} GB"
|
||||
f" | 页面文件: {_vm.get('avail_pagefile_gb',0)}/{_vm.get('total_pagefile_gb',0)} GB"
|
||||
f" | 提交使用率: {_vm.get('commit_pct',0)}%"
|
||||
)
|
||||
# WinError 1455 = 页面文件太小 → 标记为永久失败,不重试
|
||||
_is_pagefile_error = "1455" in str(e) or "页面文件" in str(e)
|
||||
_exit_code = 2 if _is_pagefile_error else 1 # exit(2) = 虚拟内存不足
|
||||
_write_crash_log(
|
||||
f"{datetime.now()} [easyocr_worker] import {_exit_code}: "
|
||||
f"{'页面文件不足' if _is_pagefile_error else 'import失败'}: {e}{_vm_hint}"
|
||||
)
|
||||
_flush_exit(f"import 失败{'(页面文件不足)' if _is_pagefile_error else ''}: {e}{_vm_hint}", code=_exit_code)
|
||||
|
||||
|
||||
def _init_reader():
|
||||
|
||||
Reference in New Issue
Block a user