Files
virtual_simulation_midware/tests/test_udp_performance.py
2026-06-16 15:40:19 +08:00

148 lines
6.1 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
验证工程满足1553B 6-12us 响应、同时支持 10 个单机接入、CAN/1553B 消息顺序发送的性能需求在test/下创建test_udp_performance.py
2026/2/26
Tan Mingyan
"""
import socket
import binascii
import time
import threading
from midware.config.base_config import DEVICE_CONFIG_DICT, UDP_CONFIG
# 全局配置
LOCAL_IP = UDP_CONFIG["LOCAL_IP"]
FAULT_PORT = UDP_CONFIG["FAULT_INJECT_PORT"]
BUFFER_SIZE = 4096
# 测试用1553B外设端口取CSV中的1553B0/1553B1如8882/8886
B1553B_PORTS = [dev_info["udp_port"] for dev_name, dev_info in DEVICE_CONFIG_DICT.items() if dev_info["protocol"] == "1553B"]
# CAN外设端口
CAN_PORTS = [dev_info["udp_port"] for dev_name, dev_info in DEVICE_CONFIG_DICT.items() if dev_info["protocol"] == "CAN"]
# 10个测试端口覆盖所有协议
TEST_PORTS = [dev_info["udp_port"] for dev_name, dev_info in DEVICE_CONFIG_DICT.items()][:10]
# 测试数据(小数据包,模拟星务平台实时数据)
TEST_DATA = b"PERF_TEST" + b'\x9c\x47' # 含校验位
class UDPPerformanceTest:
def __init__(self):
self.send_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.send_sock.setblocking(False)
# 接收套接字(统计回传时延)
self.recv_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.recv_sock.bind((LOCAL_IP, FAULT_PORT))
self.recv_sock.setblocking(False)
# 时延统计
self.latency_list = []
# 并发计数
self.send_count = 0
self.recv_count = 0
def _calc_latency(self, port, send_ts):
"""计算单包时延:发送时间→接收回传时间"""
try:
data, _ = self.recv_sock.recvfrom(BUFFER_SIZE)
recv_ts = time.time()
latency = (recv_ts - send_ts) * 1000000 # 转换为微秒(us)
self.latency_list.append(latency)
self.recv_count += 1
print(f"1553B端口{port} | 响应时延:{latency:.2f}us | 累计接收:{self.recv_count}")
except:
pass
def test_1553b_latency(self, test_times=1000):
"""测试1553B响应时延要求6-12us发送test_times次数据包"""
if not B1553B_PORTS:
print("❌ 未配置1553B外设跳过时延测试")
return
test_port = B1553B_PORTS[0]
print(f"===== 1553B时延测试端口{test_port},发送{test_times}次) =====")
self.latency_list.clear()
self.recv_count = 0
for i in range(test_times):
send_ts = time.time()
# 发送数据
hex_data = binascii.hexlify(TEST_DATA).decode("utf-8")
self.send_sock.sendto(hex_data.encode("utf-8"), (LOCAL_IP, test_port))
# 立即统计时延(模拟中间层实时回传)
self._calc_latency(test_port, send_ts)
# 微秒级间隔,模拟星务平台请求频率
time.sleep(0.000001)
# 统计结果
if self.latency_list:
avg_latency = sum(self.latency_list) / len(self.latency_list)
min_latency = min(self.latency_list)
max_latency = max(self.latency_list)
print(f"\n1553B时延统计 | 平均:{avg_latency:.2f}us | 最小:{min_latency:.2f}us | 最大:{max_latency:.2f}us")
if avg_latency >=6 and avg_latency <=12:
print("✅ 1553B时延满足要求6-12us")
else:
print("❌ 1553B时延不满足要求")
def test_10_device_concurrent(self, test_times=500):
"""测试10个单机并发接入同时发送验证无丢包"""
if len(TEST_PORTS) <10:
print("❌ 未配置10个外设跳过多机并发测试")
return
print(f"===== 10机并发测试发送{test_times}次/机) =====")
self.send_count = 0
self.recv_count = 0
def send_task(port):
for _ in range(test_times):
hex_data = binascii.hexlify(TEST_DATA).decode("utf-8")
self.send_sock.sendto(hex_data.encode("utf-8"), (LOCAL_IP, port))
self.send_count +=1
time.sleep(0.0001)
# 启动10个线程对应10个外设
threads = [threading.Thread(target=send_task, args=(p,), daemon=True) for p in TEST_PORTS]
for t in threads:
t.start()
for t in threads:
t.join()
# 等待接收完成
time.sleep(2)
loss_rate = (self.send_count - self.recv_count) / self.send_count * 100
print(f"总发送:{self.send_count} | 总接收:{self.recv_count} | 丢包率:{loss_rate:.2f}%")
if loss_rate == 0:
print("✅ 10机并发测试通过无丢包")
else:
print("❌ 10机并发测试失败存在丢包")
def test_can_b1553b_order(self):
"""测试CAN/1553B消息顺序发送要求一个节点发完再发下一个"""
print("===== CAN/1553B消息顺序测试 =====")
# 按顺序发送多个节点数据,查看中间层日志
test_ports = CAN_PORTS[:2] + B1553B_PORTS[:2]
for port in test_ports:
hex_data = binascii.hexlify(TEST_DATA + str(port).encode()).decode("utf-8")
self.send_sock.sendto(hex_data.encode("utf-8"), (LOCAL_IP, port))
print(f"按顺序发送:端口{port} 数据标识:{port}")
time.sleep(0.001)
print("✅ 请查看工程logs/run_*.log验证日志中节点数据是否按发送顺序打印无乱序")
def close(self):
self.send_sock.close()
self.recv_sock.close()
if __name__ == "__main__":
perf_test = UDPPerformanceTest()
try:
# 1. 1553B时延测试发送1000次
perf_test.test_1553b_latency(test_times=1000)
time.sleep(3)
# 2. 10机并发测试每机发送500次
perf_test.test_10_device_concurrent(test_times=500)
time.sleep(3)
# 3. CAN/1553B消息顺序测试
perf_test.test_can_b1553b_order()
except KeyboardInterrupt:
print("\n用户终止性能测试")
finally:
perf_test.close()