高性能序列化库选型与优化实战:从JSON到Protobuf、FlatBuffers
序列化库是每个后端工程师都躲不开的组件。最近因为一个支付系统的数据同步模块遇到性能瓶颈我把手头的高性能序列化库整个折腾了一遍从选型对比到落地优化踩了不少坑今天把这些经验整理出来。这篇文章适合正在做微服务通信、消息队列、缓存存储优化的开发者也适合刚接触序列化概念、想搞清楚二进制协议和文本协议差异的新人。我会从核心原理讲到具体实操最后附上我排查问题时的真实记录希望能帮你少走弯路。有人觉得序列化就是个“对象转字节流”的小事随便用个 Java 自带的 Serializable 或者 JSON 就够了。真在高并发场景下跑过一轮就会发现序列化常常是整个链路里最容易成为瓶颈的一环。数据量一大延迟就上去了对象一变兼容性问题就冒出来内存一紧频繁分配回收都像在割肉。所以高性能序列化库不是“性能极客”的玩具而是生产环境里实打实的刚需。它的核心工作就是两件事把数据结构变成紧凑的二进制再从二进制高效还原成对象——在这两个动作之间比拼的是速度、体积、内存占用和可扩展性。1. 高性能序列化的核心问题拆解1.1 为什么序列化性能如此关键在一个典型的分布式系统里一次 RPC 请求要经历“编码 - 网络传输 - 解码”三个环节。网络传输耗时取决于数据包大小而数据包大小直接由序列化格式决定。比如你用 JSON 传输一个包含 100 个字段的对象光字段名就要浪费几百字节用二进制协议可能几十字节就搞定了。1KB 和 200B 的差距在每秒几万次请求的流量下意味着网络带宽占用能差好几倍。更关键的是 CPU 开销。Jackson 这类 JSON 库在序列化时要做大量的字符串反射和哈希查找反序列化时还要做字段映射而像 Protobuf、FlatBuffers 这类二进制库通过预编译的 schema 直接偏移量访问CPU 消耗能低一个数量级。我用过一个广告推荐系统流量峰值时全链路拆分分析发现JSON 序列化占了 23% 的 CPU换成 Protobuf 之后直接降到 6%整个集群的 CPU 水位都松了一大截。还有一个常被忽略的点是内存带宽和 GC 压力。每次序列化都要创建字节数组每次反序列化都要创建对象如果还伴随着频繁的字符串拼接或者中间缓冲拷贝年轻代 GC 的频率会直线上升。高性能序列化库往往都有“池化复用”机制比如 FlatBuffers 支持直接访问底层 buffer连反序列化对象都可以不创建这对内存敏感的应用几乎是救命的。1.2 评估高性能序列化库的关键指标选序列化库不能光看快不快我一般从四个维度打分序列化时间、反序列化时间、序列化体积、内存分配量。这四项在生产环境里各有各的权重不同的业务侧重完全不一样。序列化时间主要影响写路径比如日志写入、消息发送。单位是微秒或纳秒级别需要看 P99 而不是平均值因为垃圾回收导致的停顿会让平均值失真。反序列化时间主要影响读路径比如请求处理、缓存读取。这对在线服务的影响通常更大因为一个请求可能反序列化多次比如网关解包、业务层取数据、下游再透传。序列化体积直接影响网络带宽和存储成本。二进制协议通常比 JSON 小 40%~70%但具体要结合字段类型和压缩选项来判断。体积小也能减少缓存占用提升缓存命中率。内存分配量分配次数少、分配字节过关的对象 JVM 会少一些避免频繁 Full GC。这一点在长期运行的服务里比前两项都致命因为一次 GC 停顿可能干掉所有吞吐优势。这四项并不是完全正相关的。有些库用预分配 buffer 加紧凑二进制做到了极快的序列化但反序列化时要解析偏移量绑定到对象上反而慢有些库体积最小但需要额外压缩解压步骤。所以我的做法是先定义自己的业务特征如果只写一次读一次优先看延迟如果数据要存好几层优先看体积如果集群内存紧张优先看分配量。没有万能答案只有适合当下场景的选择。2. 主流高性能序列化库选型解析2.1 文本格式与二进制格式的取舍文本格式的代表是 JSON、XML、CSV。优点是开发者友好、调试直观、语言无关但代价是解析繁琐、体积冗余、性能上限低。二进制格式的代表是 Protobuf、Avro、Thrift、MessagePack、FlatBuffers 等。优点是紧凑、快速、schema 驱动缺点是需要代码生成或者 schema 管理调试难度高一些。我在早期项目里长期用 JSON原因很简单微服务之间传递简单的订单信息接口变更频繁JSON 灵活性高。但后来服务拆分后一次请求要通过三层服务透传每一层都要重新序列化和反序列化JSON 的体积膨胀和字符串解析就完全不可接受了。对二进制库来说schema 是双刃剑好处是字段编码有据可依可以省略字段名坏处是 schema 变更需要兼容策略比如 Protobuf 的字段号不能随意复用否则老数据解析直接挂。那么直接换二进制格式就行了吗也不是。二进制格式的调试噩梦我经历了很多次线上数据包没法直接看你要挂着 debug 工具装上插件去解 hex dump出问题了你还要比对 schema 版本。所以更实际的做法是分场景考虑——链路内部的传输用二进制格式面向外部 API 和前端页面继续提供 JSON 接口两边都能拿自己的优势。2.2 我用过的几个主流库的横向对比Protobuf 是我用得最久的库了它在并发上相当成熟代码生成覆盖方便跨语言支持非常完善兼容性上可以用 optional、optional 字段进行平滑演进。对于大多数后台系统的 RPC、存储场景我会首选它。不过它序列化后的二进制被绑定在 schema 上而且反序列化时要创建对象对于高对象构建成本的应用有更好的选择。FlatBuffers 是个有趣的设计它序列化到内存后就是一个 buffer你可以直接按字节读取字段不需要把整个数据恢复成对象。这对游戏服务端、缓存热路径很舒爽——你命中一次对象创建都能省掉。它的延迟数据很亮眼但代价是 API 不是特别自然写代码时要基于 offset 思考不太适合复杂嵌套业务模型。MessagePack 有点像“压缩版 JSON 的二进制化”它支持动态类型和 schema-less 方式是最容易从 JSON 平滑切过来的方案。用了它之后延迟和体积都有提升但跟 Protobuf 这种真正 schema 预生成的库还是有差距适合对性能要求中等、又不想背 schema 负担的业务。Avro 和 Thrift 也是老牌选择。Avro 的设计跟 hadoop 生态绑定很深它的 schema 是以 JSON 文件形式存储的适合批处理写出去的数据也可以做顺序读跟 Spark、Hive 很合拍。Thrift 当年在 Facebook 用的很多但社区活跃度现在低了他最大的特色是自带 RPC 框架如果你要开发整套网络协议栈可以省不少事。我做一个对比表吧直接列出我用的时候的感知指标库名称序列化速度相对反序列化速度相对体积优势内存分配上手难度适用场景JSON约 10MB/s约 5MB/s大高低外部 API、调试、数据交换Protobuf约 60MB/s约 40MB/s小中中RPC、存储、微服务内部链路FlatBuffers约 90MB/s约 80MB/s较小极低中高缓存、游戏、热路径读多写少MessagePack约 30MB/s约 20MB/s较小中低从 JSON 平滑迁移的场景Avro约 50MB/s约 35MB/s小中高中高大数据批处理、Hadoop 生态注意这个表是我在自己机器上跑 benchmark 的近似值不是官方数据具体项目还要实测。因为你的字段结构、schema 复杂度、运行环境都会改变相对排名。3. 实操实现高性能序列化方案的完整流程3.1 定义性能目标与基准测试方法动手选型之前一定要先定目标否则你会在各种轮子上犹豫不决。我这次定的目标很明确在 8 核 16G 的云服务器上针对一个包含 20 个字段的订单对象要求序列化 P99 小于 2 毫秒反序列化 P99 小于 3 毫秒消息体积对比 JSON 至少减少 50%持续运行 30 分钟无 Full GC。基线怎么打拿一个你线上真实的典型对象把它抽成测试用例。不要用 hello world 级别的小对象字段太少测不出差距。我用的是团队里一个真实的 order 对象包含整数类型 id、字符串 userId、嵌套的 address 对象、一个商品列表、以及几个时间戳。这样的对象才能反映出实际链路里的水分。测试工具我用了 JMH它可以避免 JIT 预热和循环优化带来的误差。JMH 里设置Warmup(iterations 5, time 1s)、Measurement(iterations 10, time 1s)。测序列化时直接把对象生成字节数组测反序列化时把预先序列化的 buffer 作为输入确保不会把不必要的操作混进来。还要注意 JMH 的黑洞消费结果要作为返回值而不是直接丢弃防止被 JIT 作弊。3.2 完整选型步骤与代码示例我的选型流程分四步第一步把需要序列化的对象定义成 schema。这一步在 Protobuf 里就叫 proto 文件它在代码生成之前就把数据协议给固定了。Protobuf 的 proto 文件我用syntax proto3;字段建议手动指定数字编号不要用动态编号兼容性完全依赖这些编号。第二步生成代码。使用 protoc 编译工具生成对应语言的代码。我直接用 Maven 插件protobuf-maven-plugin集成到了项目里不用手动跑命令行因为每次构建自动生成不会出现版本漂移。第三步写基准测试。我来演示一下我测 Protobuf 的 JMH 代码模板// 核心依赖 dependency groupIdcom.google.protobuf/groupId artifactIdprotobuf-java/artifactId version3.21.12/version /dependencyBenchmark BenchmarkMode(Mode.Throughput) // 测试吞吐量 public byte[] serializeOrderBlackhole() { OrderProto.Order order buildOrder(); byte[] data order.toByteArray(); return data; } Benchmark BenchmarkMode(Mode.AverageTime) // 测试平均耗时 public OrderProto.Order deserializeOrder() throws Exception { byte[] data preSerializedBytes; return OrderProto.Order.parseFrom(data); }上面的 serialize 测试跑完输出里会有 ops/s每秒操作次数以及 us/op微秒每次操作。我拿 JSON 跑了同样的baseline后从结果就能看出是否达到预期。第四步算体积和内存分配量。体积直接data.length对比。内存分配量更有技巧我之前用 JFRJava Flight Recorder录制一段观察 Allocation profile重点关注每次序列化的字节数。这个值能决定你的 GC 拥挤程度不要只看耗时。基于这些结果我最终选了 FlatBuffers 做热读路径因为缓存命中场景读多写少且对内存分配量要求极高其余通用 RPC 场景用 Protobuf因为它各方面均衡团队成员熟悉度高踩坑率低。3.3 参数调优与实测数据解读得到基准结果以后调优是一步半步走出来的。我最先调的是 Protobuf 的底层 buffer 管理。默认情况下它会为每个序列化操作分配一个 new byte[]我在高并发场景下把每个线程的序列化对象池化用ThreadLocal持有CodedOutputStream和ByteArrayOutputStream。private static final ThreadLocalByteArrayOutputStream bufferHolder ThreadLocal.withInitial(() - new ByteArrayOutputStream(512)); public byte[] serializeFast(OrderProto.Order order) throws Exception { ByteArrayOutputStream baos bufferHolder.get(); baos.reset(); order.writeTo(baos); return baos.toByteArray(); }注意上面的代码返回时仍然会产生一个新数组拷贝因为toByteArray()会 new 一个数组。想彻底零分配就难了除非你用直接内存并手动管理 buffer 生命周期。我实测这个改动让每秒序列化次数从 48000 涨到了 63000分配量直接从每操作 850B 降到了 220BFull GC 次数在半小时内是 0效果非常显著。另一个调优点是字段值。Proto3 里整数类型分 int32、sint32、int64 等不要随手用。如果你的字段值经常是负数或者接近 0用 sint32 会使用 zigzag 编码体积更小如果数值大概率超过 2^32就直接用 int64避免精度丢失后多次通信性能差异。FlatBuffers 的调优重点在于用FlatBufferBuilder的初始化大小。默认 capacity 是 1024如果你事先知道对象大小直接设置成合适的值可以减少 reallocation。我根据线上日志平均值把 capacity 设成了 2048单对象序列化时间又降了约 12%。实测数据我用一张表记录一下优化前 vs 优化后以 Protobuf 为例指标优化前优化后变化幅度序列化 P994.5 us3.2 us-29%反序列化 P995.1 us4.4 us-14%每操作分配量852 B246 B-71%Full GC 次数(1h)30明显减少这个结果再次说明很多时候性能瓶颈不在序列化库本身而在于你使用它的姿势。最好的编码器在你频繁分配内存时也会被拖垮。4. 常见性能瓶颈与排查技巧实录4.1 从一次线上故障聊起GC 猛增导致接口超时有个兄弟团队找过我说他们换了高性能序列化库之后接口反而更慢了。我一看监控串行化 P99 正常但 Full GC 次数几乎每分钟一次。再一查代码发现他们在请求里反复 new 了序列化器对象并且没有做 buffer 复用。在高并发下每个请求都新建缓冲区年轻代瞬间塞满然后频繁晋升到老年代老年代一满就触发 Mixed GC。解决办法很简单把序列化器对象做成单例将所有不会变化的配置提取出来如果必须存储中间结果就用线程私有 buffer。我还顺手给他们接入了对象池针对反序列化常复用的业务对象用ObjectPool包装这一套下来 GC 次数直接降了一个数量级。4.2 排查序列化库性能问题的三个层次遇到性能下降我会按这个顺序去排查先看是不是“伪序列化”场景。比如用 JSON 库做动态类型但业务字段类型本来很固定或者用 Protobuf 之前调了toString()暴击了——toString()返回的其实是调试文本跟真正的二进制序列化流程完全不是一回事。线上有人把toString()结果当数据传输性能直接变成兼容 JSON 的废渣。再看是不是“boxing/unboxing”和反射调用太多了。Protobuf 生成的代码是直接赋值的但如果你在业务代码里用 map 存储了对象再通过 get/set 反射调用那库本身再快也没用。我见过一个案例反序列化只要 0.8ms紧接着一个字段反射取值反而花了 5ms。尽量生成类型安全的代码或者使用泛型来避免反射。最后看是不是内存布局问题。如果你序列化之后立刻存到缓存里缓存 key 太长导致哈希碰撞或者缓存 value 分配在堆外但你还在堆内保留了一份引用都会影响整体吞吐。我可以再强调一遍序列化的性能问题一半是序列化库的问题一半是周边代码的问题。我整理的排查速查表如下遇到问题先对着表看一遍症状可能原因操作建议序列化速度慢反复创建序列化器和 buffer池化复用使用 ThreadLocal buffer内存分配过高使用了 toByteArray() 且没有复用直接写入输出流避免额外数组拷贝反序列化偶发高峰schema 版本不匹配导致校验统一 schema 版本关闭运行时校验在 JSON 换二进制后更慢代码反射调用过多改用生成代码或使用静态泛型方式调用体积依然很大没用 sint32/varint 等压缩编码根据数值范围调整整数类型线程不按预期快线程竞争序列化器共享状态确保序列化器没有任何可写共享状态4.3 三个避坑建议省下一整周排查时间第一在引入新序列化库之前先写“契约测试”。把序列化的数据跨版本、跨语言测试一遍。我踩过最大的坑是升级了字段编号旧的线上消费者没跟着升级结果生产数据解析直接抛出 unrecognized field而且静默丢弃新字段。序列化是跨系统协议不是普通的库接口改 schema 一定要带兼容性计划。第二不要只看吞吐量要盯着“分配量”。吞吐量高但少量多次分配就像你一口气倒了很多杯水但杯子不够最终漏水溢出。建议在 CI 流程里加入内存分配断言超过阈值直接失败防止后续改动引入偷偷分配。第三对于极端延迟敏感的业务优先考虑 FlatBuffers 或 SBESimple Binary Encoding。它们的特点是不创建对象、不复制字段直接由数据的二进制表示作为可读对象。虽然在编程模型上不优雅但换来的是监听热路径上几乎为零的 GC 压力和固定的内存访问时间这种收益在金融交易、毫米波雷达数据处理这类场景里非常值。我没有把这些二进制协议的底层字节顺序、varint 编码实现全都记住因为通常不需要直接实现一个序列化协议那是解密协议工程师的事情。你真正需要的是一套能快速做性能压测、优化 buffer 复用、并进行跨版本兼容的实践流程。在我现在的团队里我把这套流程沉淀成了一个内部文档任何新同学在接触序列化选型时第一天就是读一遍我的三个坑第二天直接跑 JMH 基准测试第三天上生产灰度看监控。用这套流程效率比自己盲目摸索高出一大截。

相关新闻

C#学生成绩管理系统:三层架构与数据库设计全解析

C#学生成绩管理系统:三层架构与数据库设计全解析

简介:这是一个基于C#与Access数据库的《学生成绩管理系统》课程作业完整项目,适合正在学习C#、数据库编程或需要完成类似课设的初学者参考。系统涵盖学生、课程、成绩三类核心数据的录入、查询、修改与删除,并实现了Windows窗体界面、ADO.NET…

2026/10/5 3:02:49 阅读更多 →
专科生写论文必备:8个亲测有效的AI工具清单

专科生写论文必备:8个亲测有效的AI工具清单

写这篇推荐的时候,我其实挺有感触的。我自己是专科出身,当年写毕业论文的时候是真的头疼。不是不努力,是没方法。选题不知道怎么选,文献看了就困,写出来的东西自己都觉得像流水账,改到第三稿的时候连导师都…

2026/10/5 3:01:49 阅读更多 →
AI写论文避坑指南:8款免费工具组合把AIGC率压到8%

AI写论文避坑指南:8款免费工具组合把AIGC率压到8%

又到论文季了。写论文这件事,如今早就不是“闷头敲键盘”的旧模式了,用AI打辅助已经成了很多人的默认操作。但踩过坑的人都知道,AI最擅长的不只是帮你写,更是“面不改色地编”。你让它列参考文献,它给你列得漂漂亮亮、…

2026/10/5 3:01:49 阅读更多 →

最新新闻

吃豆人AI实战:Minimax、Alpha-Beta剪枝与Expectimax完整解析

吃豆人AI实战:Minimax、Alpha-Beta剪枝与Expectimax完整解析

如果你刷过伯克利CS61B,或者看过AI入门视频,大概率见过那只黄色吃豆人在迷宫里被鬼追得满地图跑的画面。那个场景十有八九就来自CS188的Project 2: Multi-Agents。这个项目是所有CS188课程作业里最有“游戏感”的一个,任务很直接——亲手写出…

2026/10/5 3:52:15 阅读更多 →
构建真正开放的跨平台Shell工作流

构建真正开放的跨平台Shell工作流

1. OpenShell:一个被严重误读的开源项目名称,以及它真实的技术定位OpenShell 这个名字一出来,很多人第一反应是“Windows 的替代开始菜单”——没错,确实存在一个叫 Open-Shell 的经典开源项目,它基于已停更的 Classic…

2026/10/5 3:52:15 阅读更多 →
C/C++源字符集与执行字符集:乱码根源与配置指南

C/C++源字符集与执行字符集:乱码根源与配置指南

如果你写过C/C程序,大概率遇到过这种事:代码在编辑器里显示得清清楚楚,注释里的中文也一切正常,可一旦编译运行,printf打印出来的中文字符串就变成了一堆“鏂囧瓧”之类的天书。还有更诡异的,同一份源码在L…

2026/10/5 3:52:15 阅读更多 →
插件原理与排障指南:从加载失败到开发实践

插件原理与排障指南:从加载失败到开发实践

做软件这些年,我发现自己经常要在一个单词上跟别人反复解释:plugins。它不是某个产品的功能,而是一整套架构思想加工程实践。最近看到一堆相关热搜,比如“iar plugins 是干什么的”、“failed to load plugins web boot: 2 entrie…

2026/10/5 3:52:15 阅读更多 →
Petalinux工程骨架详解:从XSA到BOOT.BIN的嵌入式Linux构建

Petalinux工程骨架详解:从XSA到BOOT.BIN的嵌入式Linux构建

1. 先把 petalinux 工程骨架这块拼图摆正如果你刚接触 Zynq 这类带 FPGA 的嵌入式平台,想用 petalinux 给板卡做一套 Linux 系统,第一反应大概率是找一份教程,敲几条命令,生成 BOOT.BIN,烧进 SD 卡,完事。我…

2026/10/5 3:52:14 阅读更多 →
Java仓库管理系统课设拆解:JDBC+MySQL+Swing实战开发

Java仓库管理系统课设拆解:JDBC+MySQL+Swing实战开发

简介:基于Java的仓库管理系统项目,是一份面向计算机相关专业学生和Java Web开发者的毕业设计完整参考。项目运用Spring框架、MyBatis持久层、Servlet与JSP等主流技术,实现了用户注册登录、商品信息维护、库存出入管理、价格设置等核心业务&am…

2026/10/5 3:51:14 阅读更多 →

日新闻

马斯克杀回智能体战场,Grok 4.5万亿参数撑腰,Cursor接手数字白领项目:用TaoToken统一Key跑通多模型Agent工作流

马斯克杀回智能体战场,Grok 4.5万亿参数撑腰,Cursor接手数字白领项目:用TaoToken统一Key跑通多模型Agent工作流

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/5 0:00:22 阅读更多 →
AI编程工具插件机制详解:plugin.json配置与加载失败排查指南

AI编程工具插件机制详解:plugin.json配置与加载失败排查指南

1. 从“plugins”这个词说起:它到底在解决什么问题如果你最近在折腾 AI 编程工具,尤其是 Cursor、Codex CLI、Claude Code 这类带 CLI 的编辑器或命令行助手,那你大概率绕不开一个词——plugins。这个词本身不新鲜,从浏览器到 IDE…

2026/10/5 0:00:23 阅读更多 →
第26课:OpenClaw|日志审计与问题诊断:把日志链路改到 TaoToken 的排查清单

第26课:OpenClaw|日志审计与问题诊断:把日志链路改到 TaoToken 的排查清单

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/5 0:00:23 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 1:00:58 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/5 1:10:22 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/5 3:06:17 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 11:40:45 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 9:43:54 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 20:14:29 阅读更多 →