Empty Bytes type scaling notes 28int +4bytes about every 30 powers of 2 37bytes +1 byte per additional byte 49str +1-4 per additional character (depending on max width) 48tuple +8 per additional item 64list +8for each additional 224set 5th increases to 736; 21nd, 2272; 85th, 8416; 341, 32992 240dict 6th increases to 368; 22nd, 1184; 43rd, 2280; 86th, 4704; 171st, 9320 136 func defdoesnot include default args and other attrs 1056classdef no slots 56classinst has a __dict__ attr, same scaling asdict above 888classdefwith slots 16 __slots__ seems to store in mutable tuple-like structure first slot grows to 48, and so on.
# memoryview 无需额外拷贝 mview = memoryview(data) for index in sliced_indexes: ifnot index.valid_start: logger.warning("data<len:%s> has no valid start, may not be parsed", len(index)) yield mview[index.start : index.end]
deffind_udp_data_sliced_indexes(data: bytes, udp_package_max_size: int = 65507, mtu: int = 1500) -> SlicedIndexList: """对 UDP 发送数据进行切片处理,保证每次发送成功 :param data: 预发送数据 :param udp_package_max_size: 当前系统支持的最大 UDP 发送包大小,以 bytes 计算,默认为 65535 (在 macOS 下默认为 9126) :param mtu: Maximum Transmission Unit udp_package_max_size = 0xffff - (sizeof(IP Header) + sizeof(UDP Header)) = 65535-(20+8) = 65507 ref to: https://en.wikipedia.org/wiki/User_Datagram_Protocol """ length = len(data) if length > mtu: # TODO: 当前我们暂不考虑处理 MTU 的问题,先解决 UDP 包过大的情况 logger.debug("UDP packages is larger than MTU, not safe for single push.")
if length <= udp_package_max_size: return SlicedIndexList(indexes=[SlicedIndex(0, length)])
sliced_index_list = SlicedIndexList() try: find_sliced_indexes(data, 0, udp_package_max_size, sliced_index_list) except RecursionError: logger.warning("data has no valid format, drop it...")
return sliced_index_list
效果
1 2 3 4 5 6 7 8 9
# 原来的 UDP 直接发送 # 将抛出 error: [Errno 90] Message too long udp_socket.sendto(data, (address, port))
# 循环调用 UDP 请求 for sliced_data in slice_metrics_udp_data(data, find_udp_data_sliced_indexes(data)): # 所有 UDP 包都可以发送出去 # 同时取决于数据特性,**绝大多数**的 UDP 数据都能在服务端得到解析 udp_socket.sendto(sliced_data, (address, port))