|
| 1 | +--- |
| 2 | +id: perf |
| 3 | +title: 关于性能 |
| 4 | +sidebar_position: 3 |
| 5 | +--- |
| 6 | + |
| 7 | +# 关于性能 |
| 8 | + |
| 9 | +对于本框架来说,有一个问题经常会被问到:**"LibXR对底层驱动封装之后,性能是否会很差?"** |
| 10 | + |
| 11 | +这个问题的答案是:**完全不必担心**。虽然相比与直接调用厂家SDK(例如hal库,ESP-IDF)提供的API来自行管理DMA等资源,性能会有一定的损失,但是这种损失是很小的,可以忽略不计。下面会附上一些性能测试结果,大家可以自行分析。 |
| 12 | + |
| 13 | +## 测试环境 |
| 14 | + |
| 15 | +串口驱动是整个LibXR里面最复杂的部分,性能测试的环境如下: |
| 16 | + |
| 17 | +* STM32F103,Cortex-M3 @ 72Mhz,无FPU和Cache |
| 18 | +* 使用杜邦线将USART1的TX RX连接起来,数据位为8,停止位为1,无流控,无奇偶校验 |
| 19 | +* 开启一个频率50khz的定时器中断,用于FreeRTOS的占用率统计 |
| 20 | +* 收到数据后对首尾进行检查,出现任何错误都会中断测试,并输出错误信息 |
| 21 | + |
| 22 | +## 测试代码 |
| 23 | + |
| 24 | +```cpp |
| 25 | + LibXR::Semaphore sem_r, sem_w; |
| 26 | + LibXR::ReadOperation op_r(sem_r); |
| 27 | + LibXR::WriteOperation op_w(sem_w); |
| 28 | + static uint8_t read_buffer[256], write_buffer[256]; |
| 29 | + uint32_t count = 0; |
| 30 | + |
| 31 | + void (*fun)(uint32_t *) = [](uint32_t *count) { |
| 32 | + XR_LOG_INFO("\r\ncount: %d, speed: %d BAUD", *count, |
| 33 | + *count * 10 * sizeof(write_buffer)); |
| 34 | + *count = 0; |
| 35 | + static uint8_t cpu_info[1000]; |
| 36 | + |
| 37 | + memset(cpu_info, 0, 400); |
| 38 | + |
| 39 | + vTaskList((char *)&cpu_info); |
| 40 | + |
| 41 | + XR_LOG_DEBUG("\r\n---------------------------------------------\r\n"); |
| 42 | + XR_LOG_DEBUG("\r\n任务名 任务状态 优先级 剩余栈 任务序号\r\n"); |
| 43 | + XR_LOG_DEBUG("\r\n%s", cpu_info); |
| 44 | + XR_LOG_DEBUG("\r\n---------------------------------------------\r\n"); |
| 45 | + |
| 46 | + memset(cpu_info, 0, 400); |
| 47 | + |
| 48 | + vTaskGetRunTimeStats((char *)&cpu_info); |
| 49 | + |
| 50 | + XR_LOG_DEBUG("\r\n任务名 运行计数 利用率\r\n"); |
| 51 | + XR_LOG_DEBUG("\r\n%s", cpu_info); |
| 52 | + XR_LOG_DEBUG("\r\n---------------------------------------------\r\n\n"); |
| 53 | + }; |
| 54 | + auto print_task = LibXR::Timer::CreateTask(fun, &count, 1000); |
| 55 | + LibXR::Timer::Add(print_task); |
| 56 | + LibXR::Timer::Start(print_task); |
| 57 | + |
| 58 | + for (uint32_t i = 0; i < sizeof(write_buffer); i++) { |
| 59 | + write_buffer[i] = i; |
| 60 | + } |
| 61 | + |
| 62 | + usart1.SetConfig({2000000, LibXR::UART::Parity::NO_PARITY, 8, 1}); |
| 63 | + while (true) { |
| 64 | + write_buffer[0]++; |
| 65 | + write_buffer[sizeof(write_buffer) - 1]--; |
| 66 | + usart1.Write(write_buffer, op_w); |
| 67 | + usart1.Read(read_buffer, op_r); |
| 68 | + ASSERT(read_buffer[sizeof(read_buffer) - 1] == |
| 69 | + write_buffer[sizeof(write_buffer) - 1]); |
| 70 | + ASSERT(read_buffer[0] == write_buffer[0]); |
| 71 | + count++; |
| 72 | + } |
| 73 | +``` |
| 74 | +
|
| 75 | +## 测试结果 |
| 76 | +
|
| 77 | +### 同步方式 |
| 78 | +
|
| 79 | +同步模式需要等待数据传输完成,因此距离理论最大波特率相差较大。 |
| 80 | +
|
| 81 | +```bash |
| 82 | +# 无优化,256字节每包,同步方式收发,2M波特率 |
| 83 | +每秒包数: 480, 实际波特率: 1228800 BAUD |
| 84 | +任务名 运行计数 利用率 |
| 85 | +libxr_timer_task 70824 5% |
| 86 | +defaultTask 343292 28% |
| 87 | +IDLE 786968 65% |
| 88 | +terminal 6 <1% |
| 89 | +Tmr Svc 1 <1% |
| 90 | +
|
| 91 | +# -Og优化,256字节每包,同步方式收发,2M波特率 |
| 92 | +每秒包数: 552, 实际波特率: 1413120 BAUD |
| 93 | +任务名 运行计数 利用率 |
| 94 | +libxr_timer_task 19505 2% |
| 95 | +defaultTask 140176 21% |
| 96 | +IDLE 493635 75% |
| 97 | +terminal 3 <1% |
| 98 | +Tmr Svc 0 <1% |
| 99 | +
|
| 100 | +# -O3优化,256字节每包,同步方式收发,2M波特率 |
| 101 | +每秒包数: 560, 实际波特率: 1433600 BAUD |
| 102 | +任务名 运行计数 利用率 |
| 103 | +libxr_timer_task 15535 2% |
| 104 | +defaultTask 128254 19% |
| 105 | +IDLE 499330 77% |
| 106 | +terminal 3 <1% |
| 107 | +Tmr Svc 1 <1% |
| 108 | +``` |
| 109 | + |
| 110 | +### 异步方式 |
| 111 | + |
| 112 | +异步方式无需等待数据传输完成,因此波特率可以达到理论最大值。 |
| 113 | + |
| 114 | +```bash |
| 115 | +# 无优化,256字节每包,异步方式收发,2M波特率 |
| 116 | +每秒包数: 770, 实际波特率: 1971200 BAUD |
| 117 | +任务名 运行计数 利用率 |
| 118 | +libxr_timer_task 32071 7% |
| 119 | +defaultTask 160159 38% |
| 120 | +IDLE 223565 53% |
| 121 | +terminal 6 <1% |
| 122 | +Tmr Svc 1 <1% |
| 123 | + |
| 124 | +# -Og优化,256字节每包,异步方式收发,2M波特率 |
| 125 | +每秒包数: 779, 实际波特率: 1994240 BAUD |
| 126 | +任务名 运行计数 利用率 |
| 127 | +libxr_timer_task 161892 4% |
| 128 | +defaultTask 399267 9% |
| 129 | +IDLE 3480600 86% |
| 130 | +terminal 3 <1% |
| 131 | +Tmr Svc 1 <1% |
| 132 | + |
| 133 | +# -O3优化,256字节每包,异步方式收发,2M波特率 |
| 134 | +每秒包数: 779, 实际波特率: 1994240 BAUD |
| 135 | +任务名 运行计数 利用率 |
| 136 | +libxr_timer_task 22077 3% |
| 137 | +defaultTask 58714 8% |
| 138 | +IDLE 604531 88% |
| 139 | +terminal 3 <1% |
| 140 | +Tmr Svc 0 <1% |
| 141 | +``` |
| 142 | + |
| 143 | +### 其他情况 |
| 144 | + |
| 145 | +受限于硬件性能,实际波特率可能会比理论最大值略低。 |
| 146 | + |
| 147 | +```bash |
| 148 | +# -O3优化,64字节每包,异步方式收发,4M波特率 |
| 149 | +每秒包数: 5824, 实际波特率: 3727360 BAUD |
| 150 | +任务名 运行计数 利用率 |
| 151 | +libxr_timer_task 22170 3% |
| 152 | +defaultTask 497262 85% |
| 153 | +IDLE 58956 10% |
| 154 | +terminal 3 <1% |
| 155 | +Tmr Svc 1 <1% |
| 156 | + |
| 157 | +# -O3优化,512字节每包,异步方式收发,4M波特率 |
| 158 | +每秒包数: 780, 实际波特率: 3993600 BAUD |
| 159 | +任务名 运行计数 利用率 |
| 160 | +libxr_timer_task 24692 5% |
| 161 | +defaultTask 103896 23% |
| 162 | +IDLE 321381 71% |
| 163 | +terminal 3 <1% |
| 164 | +Tmr Svc 1 <1% |
| 165 | + |
| 166 | +# -O3优化,16字节每包,异步方式收发,1M波特率 |
| 167 | +每秒包数: 5145, 实际波特率: 823200 BAUD |
| 168 | +任务名 运行计数 利用率 |
| 169 | +libxr_timer_task 12758 2% |
| 170 | +defaultTask 124461 23% |
| 171 | +IDLE 389558 73% |
| 172 | +terminal 3 <1% |
| 173 | +Tmr Svc 1 <1% |
| 174 | +``` |
| 175 | + |
| 176 | +## 总结 |
| 177 | + |
| 178 | +在 STM32F103 上,2Mbps 波特率下异步模式可达 **1.99 M**带宽,接近理论极限,CPU 空闲率高达 **88%**。即便使用同步模式,也能达到 **1.43 M**带宽。**LibXR 对底层驱动的封装几乎不影响性能**。 |
0 commit comments