OpenTTD 货运分配链路图(Link Graph)机制与性能调优指南

发布时间:2026/9/26 8:19:52

OpenTTD 货运分配链路图(Link Graph)机制与性能调优指南 游戏开发【免费下载链接】OpenTTDOpenTTD is an open source simulation game based upon Transport Tycoon Deluxe项目地址https://gitcode.com/gh_mirrors/op/OpenTTD点击查看免费下载本文以 docs/linkgraph.md 为主线结合 OpenTTD 源码中src/linkgraph/目录下的调度器、MCF 求解器与设置定义系统讲解货运分配Cargo Distribution背后的链路图重算线程、多商品流MCF算法复杂度以及recalc_interval、recalc_time、accuracy等配置项如何影响游戏性能与卡顿体验帮助玩家与开发者在大地图、慢速 CPU 环境下合理调参理解链路图调度内部原理。一、链路图Link Graph是什么链路图是 OpenTTD 货运分配Cargo Distribution功能的核心数据结构。当你在游戏设置中为旅客、邮件、装甲货物或默认货物启用对称 / 不对称 / 手动等分布模式时游戏会把地图上的站点视为节点把可通行的运输线路视为边构建出一张描述货物供需与运力关系的图并在后台周期性重算这张图上的货物流向。src/linkgraph/目录集中了该功能的全部实现包括src/linkgraph/linkgraph.h 与 src/linkgraph/linkgraph_base.h链路图节点/边的数据结构与基本操作src/linkgraph/linkgraphschedule.cpp 与 src/linkgraph/linkgraphschedule.h调度器负责排队、启动线程与回收线程src/linkgraph/mcf.cpp 与 src/linkgraph/mcf.h多商品流Multi-Commodity Flow求解器src/linkgraph/demands.cpp货物需求估算src/linkgraph/flowmapper.cpp把计算结果写回边注释供车辆路径选择使用。从源码结构看每一次重算并非全图一次性完成而是按连通分量拆分成若干LinkGraphJob由调度器逐个排队执行Queue/SpawnNext见 src/linkgraph/linkgraphschedule.h。二、重算线程的生命周期从 Spawn 到 Join2.1 每 X 天一个周期链路图的重算按游戏内的经济日历日驱动。LinkGraphSchedule定义了一个静态常量static const uint SPAWN_JOIN_TICK 21; /// Tick when jobs are spawned or joined every day.见 src/linkgraph/linkgraphschedule.h。调度逻辑在OnTick_LinkGraph()src/linkgraph/linkgraphschedule.cpp中实现每天的固定 tick调度器会检查TimerGameEconomy::date.base() % (_settings_game.linkgraph.recalc_interval / EconomyTime::SECONDS_PER_DAY)余数为0调用SpawnNext()为队首的链路图启动一个新的重算任务Job余数为recalc_interval / SECONDS_PER_DAY / 2调用JoinNext()回收已经到期的任务线程并把结果并入游戏状态。2.2 InitializeLinkGraphs开局即回收线程原文档首先强调了一个容易被忽视的事实InitializeLinkGraphsjoins all threads, so if the game is abandoned with some threads still running, theyre joined as soon as the next game (possibly the title game) is started.即在开始新一局游戏甚至只是回到标题画面时游戏会调用清理逻辑把所有仍在运行的链路图线程强制回收join。对应源码是LinkGraphSchedule::Clear()src/linkgraph/linkgraphschedule.cpp它对running列表中每个 Job 先调用AbortJob()再清空队列。配合InitializeGame()src/misc.cpp在开新局时的整体初始化流程任何上一局遗留的线程都会在此被汇合避免线程泄漏或与新游戏的数据相互干扰。2.3 线程不可用时同步执行LinkGraphJob::SpawnThread()src/linkgraph/linkgraphjob.cpp的逻辑是先尝试StartNewThread(this-thread, ottd:linkgraph, ...)启动一个名为ottd:linkgraph的后台线程如果平台不支持线程、启动失败则在当前线程主线程里同步执行整个 Job——这正是原文档所说没有线程的平台上游戏会卡住的代码级原因。同步执行期间主线程被 MCF 计算占据无法响应其他游戏逻辑。三、MCF 算法为什么它可能吃掉大量 CPU3.1 指数级复杂度的来源原文档明确指出The MCF (multi-commodity flow) algorithm can be quite CPU-hungry as its NP-hard and takes exponential time (though with a very small constant factor) in the number of nodes.多商品流问题本身是 NP-hard 的。OpenTTD 的求解器在 src/linkgraph/mcf.h 中声明了基类MultiCommodityFlow与两趟递进式的实现MCF1stPass第一趟先饱和最短路径按需创建新路径并消除环cycle。mcf.h的注释明确说明该计算在节点数量上呈指数复杂度但常数因子足够小对大多数真实链路图分量可用MCF2ndPass第二趟优先饱和剩余容量最大的路径且不会沿第一趟未访问过的边新建路径因此无需再做环检测与消除——环消除是第一趟最耗时的部分这使得第二趟更廉价见 src/linkgraph/mcf.h。这意味着一张链路图包含的节点站点越多、连通分量越复杂单次重算耗时按指数级增长。原文档据此给出两条实用结论大尺寸地图 复杂链路图 → 建议调高重算时间设置以避免卡顿慢 CPU 系统同理。3.2 调度器的 6 步处理管线每个 Job 在后台线程里由 6 个无状态处理器按序执行LinkGraphSchedule构造函数src/linkgraph/linkgraphschedule.cpp顺序处理器作用0InitHandler初始化节点与边注释见 src/linkgraph/init.h1DemandHandler估算各节点对某类货物的供需见 src/linkgraph/demands.cpp2MCFHandlerMCF1stPass第一趟最短路径饱和与建路3FlowMapper(false)第一趟后写回流量统计4MCFHandlerMCF2ndPass第二趟剩余容量饱和5FlowMapper(true)最终写回边注释ComponentHandler接口的注释src/linkgraph/linkgraphschedule.h特别强调处理器不得读写 Job 之外的任何数据否则会造成多人游戏 desync。LinkGraphSchedule::Run()会在每个处理器之间检查job-IsJobAborted()一旦被中止立即返回。四、重算时间设置给每个 Job 的限时4.1 配置项定义链路图相关设置全部集中定义在 src/table/settings/linkgraph_settings.ini并在 src/settings_table.cpp 注册为_linkgraph_settings设置表。其中与本主题最直接相关的两个参数配置项默认值范围单位含义linkgraph.recalc_interval84–90秒游戏内时间两次重算启动之间的间隔决定 Job 多久被排队/回收一次linkgraph.recalc_time321–9000秒游戏内时间单个 Job 被允许运行的最长时间到期即 join原文档的解释是重算时间为 X 天意味着每个链路图 Job 在被 join 之前有 X 天时间运行。换算成源码视角recalc_interval以秒为单位存储调度器在OnTick_LinkGraph()中按recalc_interval / EconomyTime::SECONDS_PER_DAY折算成天数取模使用见 src/linkgraph/linkgraphschedule.cpp。4.2 高值的代价流量统计更新滞后原文档特别提醒了调高recalc_time的副作用The downside is that the flow stats wont be updated before the job is finished and thus a high value means less updates and longer times until changes in capacities are accounted for.也就是说在 Job 完成之前流量统计flow stats不会更新。若把重算时间调得很大新开辟的线路、新增的运力、拆除的设施对货物流向的影响会被推迟反映玩家在链路图窗口src/linkgraph/linkgraph_gui.cpp中看到的统计长期不变容易误判线路盈亏。因此在大图/慢 CPU 需要防卡顿与统计及时性之间存在权衡recalc_time调得越高重算越不容易超时但流向更新越滞后。4.3 超时与自动暂停保护当 Job 到期仍未完成时JoinNext()src/linkgraph/linkgraphschedule.cpp会删除 Job 对象并隐式 join 线程——若线程仍在计算主线程就会在此阻塞表现为游戏卡顿原文档称之为 the game will hang。为防止这种阻塞被玩家感知OpenTTD 还实现了两处保护StateGameLoop_LinkGraphPauseControl()src/linkgraph/linkgraphschedule.cpp在预计 join 前 2 个 tick提前量是为多人游戏命令延迟预留的检测到 Job 尚未完成时向游戏发布PauseMode::LinkGraph暂停命令主动暂停游戏等待计算完成而不是让主循环硬卡Job 就绪后自动解除暂停。该函数由主循环 src/openttd.cpp 在服务端/单机时每帧调用AfterLoad_LinkGraphPauseControl()src/linkgraph/linkgraphschedule.cpp载入存档时如果某个 Job 已到期仍未完成立即置暂停位由存档加载流程 src/saveload/linkgraph_sl.cpp 调用避免读档后立刻卡死。五、降低精度另一种降低 CPU 消耗的手段5.1 accuracy 的作用原文档指出Another option to avoid excessive lags is to reduce the accuracy of link graph calculations. Generally the accuracy is inversely correlated to the CPU requirements of the MCF algorithm.linkgraph.accuracy的默认值为 16范围 2–64src/table/settings/linkgraph_settings.ini。它在两个环节影响计算量需求估算DemandHandler以accuracy作为距离缩放的分母——scaled_distance按(accuracy * scaled_distance * 16) / (base_distance * 2)折算 divisoraccuracy 越小 divisor 越小、单次纳入计算的供需越多同时给远处节点分配剩余供给的兜底条件chance accuracy * num_demands * num_supplies也随 accuracy 缩小而更快触发见 src/linkgraph/demands.cpp。可见 accuracy 越低每轮分配的流量越多、需要的迭代轮数越少MCF 两趟求解MCF1stPass与MCF2ndPass都读取job.Settings().accuracy作为每次PushFlow的步长——accuracy 越小单次推流越多收敛越快见 src/linkgraph/mcf.cpp、src/linkgraph/mcf.cpp。因此降低accuracy可以直接减少迭代轮数、缩短单 Job 运行时间代价是流向计算结果更粗糙、分配精度下降。5.2 相关配套参数linkgraph_settings.ini中还定义了与精度/需求相关的其他参数供完整调优参考配置项默认值范围含义linkgraph.demand_distance1000–255% 距离对需求的加权系数100 时按二次方放大源码中over100^2 / 12见 src/linkgraph/demands.cpplinkgraph.demand_size1000–100% 站点规模客流量/吞吐量对需求的加权linkgraph.short_path_saturation800–250% MCF 第一趟的路径饱和上限越低第一趟越早收手、耗时越少见 src/linkgraph/mcf.hlinkgraph.distribution_pax/mail/armoured/defaultManual见 DistributionType 枚举各类货物的分布模式开关对称/不对称/手动决定是否参与链路图计算5.3 配置入口上述配置项以linkgraph.*前缀持久化在openttd.cfg中linkgraph_settings.ini的注释明确说明其同时写入主配置文件、存档 PATS chunk 与每个运行中 Job 的链路图 chunk。运行时可从游戏内设置 → 高级设置Advanced Settings中找到对应条目修改也可在openttd.cfg的[linkgraph]段落直接编辑。由于设置属于GameSettings修改后会写入存档多人游戏需注意联机双方的设置一致性。六、实战调优建议综合原文档结论与源码机制可给出如下调优路线默认配置即可满足大多数场景默认recalc_interval8秒、recalc_time32秒、accuracy16配合后台线程通常不会造成可感知卡顿大地图 / 站点密集的复杂网络优先把linkgraph.recalc_time从 32 逐步提高例如 64、128给每个 Job 更充裕的运行时间减少到期 join 时的主线程阻塞同时接受流量统计更新变慢的事实CPU 较弱的机器在提高recalc_time的同时把linkgraph.accuracy从 16 下调例如 8、4用精度换速度也可适当调低short_path_saturation让 MCF 第一趟更早结束务必理解权衡关系recalc_time越大新建线路的容量变化被纳入统计越慢accuracy越小流向越粗糙。二者不可兼得需按地图规模与机器性能平衡观察信号若游戏频繁出现PauseMode::LinkGraph自动暂停表现为主机未操作却自行暂停说明 Job 频繁超时应进一步加大recalc_time或降低accuracy若链路图窗口src/linkgraph/linkgraph_gui.cpp中流量统计长时间不动则应考虑缩小recalc_time。七、结语链路图重算是 OpenTTD 货运分配功能中最具计算压力的子系统它把 NP-hard 的多商品流问题放入后台线程用限时 到期 join的调度策略在实时性与性能之间寻找平衡。理解InitializeLinkGraphs的线程回收、recalc_interval/recalc_time的调度节奏、以及accuracy与 MCF 迭代次数的反比关系就能在超大存档或低配机器上有的放矢地调参。相关实现细节可进一步阅读 src/linkgraph/ 目录源码以及设置定义 src/table/settings/linkgraph_settings.ini。赞分享游戏开发【免费下载链接】OpenTTDOpenTTD is an open source simulation game based upon Transport Tycoon Deluxe项目地址https://gitcode.com/gh_mirrors/op/OpenTTD点击查看免费下载相关推荐Anarlog deeplink2 插件 Tauri 权限机制与 Deep Link 回调链路实现解析Anarlog deeplink2 插件 Tauri 权限机制与 Deep Link 回调链路实现解析 本文以 plugins/deeplink2/permisAI 应用人工智能语音本地部署桌面应用音频SvelteKit 性能优化实战指南从默认机制到资源、导航与托管的全链路调优SvelteKit 性能优化实战指南从默认机制到资源、导航与托管的全链路调优 SvelteKit 开箱即用地实现了代码分割、资源预加载、文件哈希缓存、请求合并Web框架后端前端Gatsby 页面间链接完全指南Link 组件、相对链接与性能机制详解Gatsby 页面间链接完全指南 Link 组件、相对链接与性能机制详解 在 Gatsby 站点中页面之间的跳转是构建多页面应用的基础能力。本文基于 do前端静态站点Web框架上一篇GitHub网络优化终极方案让国内开发者告别龟速访问的实用指南下一篇10分钟掌握OpenCore Configurator黑苹果系统配置终极指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/9/26 8:19:52

Synology HDD db 教程:3步把第三方硬盘加入群晖兼容数据库

Synology HDD db 教程:3步把第三方硬盘加入群晖兼容数据库 【免费下载链接】Synology_HDD_db Add your HDD, SSD and NVMe drives to your Synologys compatible drive database and a lot more 项目地址: https://gitcode.com/GitHub_Trending/sy/Synology_HDD_d…

2026/9/26 8:14:51

全球城市地理元数据SQL包:中英文+经纬度+行政层级一体化方案

简介:本资源是一份面向C#开发者及地理信息系统初学者的全球城市地理数据基础包,解决位置服务开发中城市级经纬度数据缺失、多语言支持不足与行政层级关系模糊等实际问题。压缩包为ZIP格式,内含1个SQL文件(146KB)&#…

2026/9/26 9:19:54

IM消息转发子服务架构精讲:高并发、ACK重试与全链路故障排查

搞IM系统最容易被低估的,就是消息转发这个环节。很多人觉得,转发不就是把A的消息丢给B吗?但等你真的在高并发im场景里跑起来,就会发现这条链路上全是坑——消息乱序、重复投递、ACK超时、连接被对端RST、群消息把服务打爆……一个…

2026/9/26 9:19:54

Atlas 300V 24G推理加速卡部署YOLO全流程:环境配置与模型转换实战

最近后台收到不少留言,都在问同一个问题:atlas 300V 24G 到底是不是运算加速卡,它能不能拿来部署 YOLO。正好我手上就有一台装了两张 Atlas 300V 的服务器,也踩了不少坑,今天就把这套从环境准备、模型转换到推理落地的…

2026/9/26 9:19:54

昇腾 Atlas 300V 24G 推理加速卡解析:YOLOv8 部署实战指南

先说结论:Atlas 300V 24G 确实是一张运算加速卡,但它的“加速”和很多人印象里的 GPU 加速完全是两码事。前阵子有朋友反复问我,说想买一张 Atlas 300V 24G 回去,插在普通服务器上部署 YOLO,还问我“是不是跟 RTX 4090…

2026/9/26 9:19:54

Substrate区块链开发框架实战解析:从Runtime到Pallet

Substrate这个名字,在技术圈里其实撞了非常多的车——生物化学里它是酶作用的底物,材料科学里它是承载薄膜的衬底,但在区块链开发这个语境下,它特指Polkadot生态那套模块化区块链开发框架。简单说,它能让你不写P2P网络…

2026/9/26 9:19:54

Wireshark过滤器实战:5个核心过滤器搞定80%网络排障

1. 为什么是过滤器,而不是“抓了再说”刚接触 Wireshark 的人,十有八九会犯同一个错误:打开软件,选好网卡,点一下那个蓝色的鲨鱼鳍按钮,然后眼睁睁看着屏幕上滚过成千上万行数据包,密密麻麻的十…

2026/9/26 9:14:54

Milvus实战:构建AI语义搜索与推荐系统的记忆中枢

还记得第一次在推荐系统里跑通语义检索时的那个瞬间吗?用户搜“适合下雨天看的电影”,出来的不再是标题里硬含“下雨”二字的稿件,而是一些画面质感暗沉、情绪氛围慵懒,甚至影评里反复强调“雨声白噪音”的片子。那一刻我才真正意…

2026/9/25 21:00:17

GAMP 5 基于风险的计算机化系统验证:软件分类与审计追踪实践

简介:《A Risk-Based Approach to Compliant GxP Computerized Systems》即业内熟知的GAMP 5指南,面向制药企业质量与IT合规人员、验证工程师及计算机化系统管理者,用于解决GxP法规环境下系统合规性难以科学落地的问题。文档以风险管理为主线…

2026/9/25 20:59:52

安全托管MSSP实战:从静态防御到人机协同的攻防运营与应急响应

简介:这份PPT围绕互联网业务安全托管服务展开,面向企业安全负责人、IT运维人员及关注MSSP/MSS选型的读者,重点回应传统安全过度依赖人工、碎片化静态防御难以对抗产业化攻击等痛点。资源共1个pptx文件,包体约30.63MB,以…

2026/9/26 0:04:28

画质修复APP怎么选?Wink影像修复能力与产品实力解析

现如今手机拍摄场景愈发丰富,演唱会直拍、漫展记录、老视频翻新、日常vlog录制,都会遇到画面模糊、噪点多、曝光失衡等问题,不少用户在挑选工具时比较在意一款画质修复APP能够兼顾修复效果与自然质感。Wink作为美图公司推出的全球化AI影像增强…

2026/9/26 0:04:28

超低能耗建筑K值要求能否满足?浙东铝业建筑型材解析

核心摘要浙东铝业的超低能耗系统门窗产品,资料显示保温性能可达 K≤1.4W/(㎡K),能够对应上海地区超低能耗住宅对门窗保温性能的应用需求。判断建筑是否满足超低能耗要求,不能只看铝型材本身,还需要结合玻璃、隔热条、密封系统、开…

2026/9/25 20:55:38

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/25 18:41:36

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/25 18:34:56

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑