核心热路径(数学/内存/字符串/性能分析)用MASM汇编(SSE/AVX2) 外围系统(窗口/渲染/ECS/音频/UI/脚本)用C语言 含自研编辑器、VisualScript积木编程、中文渲染(glyph_atlas)
173 lines
4.6 KiB
NASM
173 lines
4.6 KiB
NASM
; ============================================================================
|
|
; profiling.asm - 性能分析工具 (x86-64 MASM)
|
|
; 使用 RDTSC/RDTSCP 进行高精度计时
|
|
; ============================================================================
|
|
|
|
include asm_macros.inc
|
|
|
|
.DATA
|
|
ALIGN 8
|
|
cpu_freq DQ 0 ; CPU 频率 (Hz)
|
|
cpu_freq_init DB 0 ; 是否已初始化
|
|
|
|
.CODE
|
|
|
|
; ============================================================================
|
|
; RDTSC 计时
|
|
; ============================================================================
|
|
|
|
; uint64_t prof_rdtsc(void) -> RAX
|
|
; 返回: TSC (Time Stamp Counter) 值
|
|
prof_rdtsc PROC
|
|
; 使用 RDTSCP 获取有序的 TSC
|
|
rdtscp
|
|
; EDX:EAX = TSC
|
|
shl rdx, 32
|
|
or rax, rdx
|
|
ret
|
|
prof_rdtsc ENDP
|
|
|
|
; uint64_t prof_get_freq(void) -> RAX
|
|
; 获取 CPU 频率 (通过 OS 或推断)
|
|
prof_get_freq PROC
|
|
; 检查是否已初始化
|
|
cmp byte ptr [cpu_freq_init], 0
|
|
jnz prof_freq_return
|
|
|
|
; 初始化 CPU 频率
|
|
; 方法: 使用 QueryPerformanceCounter 测量 RDTSC
|
|
push rbx
|
|
push rdi
|
|
push rsi
|
|
sub rsp, 40
|
|
|
|
; 获取 QPC 频率
|
|
lea rcx, [rsp + 32]
|
|
call QueryPerformanceFrequency
|
|
|
|
; 获取起始 QPC 和 TSC
|
|
lea rcx, [rsp + 16]
|
|
call QueryPerformanceCounter
|
|
rdtscp
|
|
shl rdx, 32
|
|
or rax, rdx
|
|
mov rbx, rax ; rbx = 起始 TSC
|
|
|
|
; 等待约 10ms
|
|
mov rcx, 10000 ; 10,000 微秒
|
|
call Sleep
|
|
|
|
; 获取结束 QPC 和 TSC
|
|
lea rcx, [rsp]
|
|
call QueryPerformanceCounter
|
|
rdtscp
|
|
shl rdx, 32
|
|
or rax, rdx
|
|
mov rdi, rax ; rdi = 结束 TSC
|
|
|
|
; 计算经过的 QPC ticks
|
|
mov rax, [rsp]
|
|
sub rax, [rsp + 16] ; qpc_diff
|
|
|
|
; 计算 QPC 频率 (ticks/sec)
|
|
mov rsi, [rsp + 32]
|
|
|
|
; TSC diff
|
|
mov rax, rdi
|
|
sub rax, rbx ; tsc_diff
|
|
|
|
; CPU freq = tsc_diff * qpc_freq / qpc_diff
|
|
; 但 qpc_diff 对应 10ms, 所以要 * 100
|
|
mov rdx, rsi
|
|
mul rdx ; tsc_diff * qpc_freq
|
|
; rdx:rax = result
|
|
div qword ptr [rsp + 16] ; / qpc_diff
|
|
; rax = freq * 100 (因为等待了 10ms)
|
|
mov rcx, 100
|
|
mul rcx
|
|
|
|
mov [cpu_freq], rax
|
|
mov byte ptr [cpu_freq_init], 1
|
|
|
|
add rsp, 40
|
|
pop rsi
|
|
pop rdi
|
|
pop rbx
|
|
|
|
prof_freq_return:
|
|
mov rax, [cpu_freq]
|
|
ret
|
|
prof_get_freq ENDP
|
|
|
|
; double prof_cycles_to_ms(uint64_t cycles) -> XMM0
|
|
; 将 TSC cycles 转换为毫秒
|
|
prof_cycles_to_ms PROC
|
|
; 先获取频率
|
|
call prof_get_freq
|
|
; rax = CPU freq (Hz)
|
|
|
|
; ms = cycles / (freq / 1000)
|
|
; 或: ms = cycles * 1000 / freq
|
|
mov rdx, 1000
|
|
mul rdx ; freq * 1000
|
|
; rdx:rax = freq * 1000
|
|
|
|
; 转换为 double
|
|
cvtsi2sd xmm0, qword ptr [rsp - 8] ; 需要栈存储
|
|
; 简化: 使用整数除法再转 double
|
|
mov rcx, rax
|
|
mov rax, [cpu_freq]
|
|
; 重新计算
|
|
mov rax, rcx
|
|
; cycles * 1000 / freq
|
|
; 已经: rax = freq * 1000, 需要 cycles * 1000 / freq
|
|
; 调整: cycles * 1000 / freq = cycles / (freq/1000)
|
|
|
|
; 简化实现
|
|
cvtsi2sd xmm0, rcx ; cycles * 1000 (转 double)
|
|
cvtsi2sd xmm1, rax ; freq (转 double)
|
|
divsd xmm0, xmm1 ; (cycles*1000) / freq = ms
|
|
ret
|
|
prof_cycles_to_ms ENDP
|
|
|
|
; ============================================================================
|
|
; 内联性能宏 (在 C 代码中使用)
|
|
; ============================================================================
|
|
|
|
; 获取当前时间戳 (直接 RDTSC, 无函数调用开销)
|
|
; 在 C 中使用: __rdtsc() 内联函数
|
|
|
|
; 高精度计时器结构
|
|
; struct ProfTimer {
|
|
; uint64_t start;
|
|
; uint64_t end;
|
|
; double elapsed_ms;
|
|
; };
|
|
|
|
; void prof_timer_start(ProfTimer* timer)
|
|
prof_timer_start PROC
|
|
rdtscp
|
|
shl rdx, 32
|
|
or rax, rdx
|
|
mov [rcx], rax ; timer->start = tsc
|
|
ret
|
|
prof_timer_start ENDP
|
|
|
|
; void prof_timer_stop(ProfTimer* timer)
|
|
prof_timer_stop PROC
|
|
rdtscp
|
|
shl rdx, 32
|
|
or rax, rdx
|
|
mov [rcx + 8], rax ; timer->end = tsc
|
|
|
|
; 计算 elapsed_ms
|
|
mov rax, [rcx + 8]
|
|
sub rax, [rcx] ; cycles
|
|
; 转换为 ms
|
|
call prof_cycles_to_ms
|
|
movsd qword ptr [rcx + 16], xmm0 ; timer->elapsed_ms
|
|
ret
|
|
prof_timer_stop ENDP
|
|
|
|
END
|