Valorant的128刻分服务器

嗨,我是布伦特“Brentmeister”Randall,我是游戏机完整团队的工程师valorant.。我的团队负责valorant.'建立系统,自动化框架,游戏客户端性能和服务器性能。在本文中,我将重点关注最后一个主题 - 我将在我们寻找最佳服务器性能后告诉技术故事。

从发展中的早期开始,我们知道valorant.将具有非常严格的服务器性能要求。我希望我能给你一些洞察力,以及我们如何完成雄心勃勃的目标。当我们开始时,服务器帧需要50毫秒,最后我们通过查看代码优化,硬件调整和操作系统调整来达到每帧的Sub-2ms。

让我们一起旅行。

Netcode的重要性

所有在线射击者(甚至valorant.)有一定数量的帕克斯的优势。我们已经完成了视频博客在网码和Peeker的优势上,和以前的vip亚博 一样的。

提供简短的摘要 -valorant.,游戏玩法的关键部分正在采取战略位置并持有它们。如果其他玩家可以在拐角处跑步并在后卫由于延迟作出反应之前,其他玩家可以变得不可能变得不可能。延迟部分基于网络,部分基于服务器刻度率。为了给予防守者,他们需要对侵略者做出反应的时候,我们确定了valorant.需要128次刻度网。如果您对我们如何结束结论感兴趣,我们的技术博客帖子vip亚博 详细介绍它。

代码优化

当我们以128次刻度率考虑托管服务器时,我们最大的约束是CPU资源。我们需要能够在7.8125ms内处理整个帧,但如果我们这样做,单个游戏将占用整个CPU核心!

此图演示了我们每核可以运行多少游戏:亚博论坛

每场比赛利用1个完整核心将在规模上托管我们的游​​戏服务器昂贵,考虑到我们知道我们希望免费提供128次,而不是作为高级服务玩家必须支付费用。在嘎嘎作响之后,我们知道我们需要每核(GPC)比3场比赛更好。亚博论坛要以透视图示,我们通常运行36个核心主机,因此每个物理游戏服务器都需要108个游戏或1080名玩家。亚博论坛甚至3 GPC也是一项大规模的投资,但骚乱领导地位了解并支持我们雄心勃勃的服务器性能目标。

让我们拍摄7.8125ms,将其除以3 GPC,我们最终得到2.6ms。但是等待 - 我们还需要保留10%的OR OPS发货,计划和在主机上运行的其他软件。在这些计算之后,我们最终每帧的目标预算只有2.34毫秒。当我们看着valorant.初始数据,我们达到50毫秒;我们有很长的路要走。这将是涉及整个开发团队所需的努力。

打破问题

“使服务器20倍更快”不是一个非常易易的问题,因此我们在软件工程中应用了单一最佳工具:将一个大的恐吓问题分解为更小的可解决问题。我们需要弄清楚那些50毫米的人们所花费的地方,以便我们可以开始剃须。我们坐下来valorant.技术领导和讨论了CPU成本可能的大面积和提出的类别:

  • 复制

  • 仙女

  • 网络

  • 动画

  • 游戏玩法

  • 运动

  • 合一

  • 字符

  • 物理

  • 其他

使用此列表,我们构建了一个系统,允许程序员轻松标记游戏代码并适当地对其进行分类。使用宏系统执行的每一行代码都被视为上述桶之一,并且我们为更大系统进行了更精细的粒度分析,添加了一个子系统的概念。我们打电话给系统valsubsystemtelemetry.

随着游戏运行,这些范围让我们跟踪我们在每个类别中支出的时间。

利用防暴技术:分析平台

所以现在我们有一个图书馆,我们正在生成所有这些数据。我们该怎么办?

像骚乱这样的更大工作室工作的一部分是我们能够利用现有的工具和技术,即其他团队的发展和支持。例如,在这种情况下,骚乱的中央团队开发了一种称为分析平台的技术。亚搏网站此工具允许RIOR的程序员将数据发布到我们的大数据仓库,然后在其周围构建可视化。

以下是我们可视化性能数据的一些方式valorant.


每轮平均服务器帧时间

每个Valsubsystem的平均处理时间

没有像这样的数据,对于非性能代码或内容更改很容易,以使其进入未检测到的游戏。在这些变化堆叠到开发人员或玩家注意到事物减速时,我们可能会去几周。

挖回到几个月的变昌家,寻找罪魁祸首是昂贵的工作,但是当您一直跟踪性能数据时,这是一个更容易的任务。例如,在上面的第二图像中,我们可以看到改变数字445887和446832之间存在导致复制(橙色线)需要更长的问题。这种类型的可视化允许我们通过更小的更改,并快速分配工程师以解决问题。

子系统的绩效预算

既然我们有可视化设置的数据验证,我们能够为每个子系统设置预算,并跟进任何差异。该valorant.技术领导再次聚集在一起,并讨论了每个系统的合理预算。这在很大程度上被提供了系统所在的位置,以及根据专家的系统中存在优化的机会。从那里,每个团队和专家都有一个目标,我们可以并行工作,以使性能成为可移动状态。

在这里,我们可以看到上面提到的类别组织的一些早期数据:

让我们来看看两个具体部分,以展示我们如何谴责性能成本。首先,我们将专注于复制,因为它是需要最大变化的系统。然后我们会看一下动画,因为我们必须制作的更改高度代表我们在所有类别中制作的解决方案类型。

复制

财产复制我们经常仅仅呼叫复制,是虚幻引擎4(UE4)的系统,它允许服务器和客户端之间的状态的网络同步。这是一个很好的系统,可以快速原型设计新的字符/能力/功能与客户端的网络。开发人员可以简单地将变量标记为“复制”,并且它将自动在服务器和客户端之间同步。

不幸的是,它也很慢。它需要扫描标记为每个帧的每个变量,然后将其与10个客户端的最后一个已知状态中的每一个进行比较,然后将任何Δ一起包装到客户端发送到客户端。这是有效的内存随机访问,并且真的很缓存密集,缓慢的工作。无论状态如何变化,仍然检查变量。我认为这样的“轮询”系统就是这样的性能反模式。

修复程序是使用另一个UE4网络工具:远程过程调用(rpcs.)。RPC允许服务器通过在一个或多个客户端上执行的网络调用函数。在状态更改的RPC上使用RPCS更改游戏事件将性能成本限制在其发生状态变更的帧中。这种“推动”模型更加表现。缺点是设计人员和工程师必须更仔细地思考RPC和处理案例,如重新连接。但是,我们发现在许多情况下从复制变量转换为RPC提供了100倍至10000倍的性能改进!

例如,考虑玩家健康。网络播放器健康的一种方法是将玩家健康标记为复制。每帧,游戏服务器都会检查该值是否已更改,如果是这样,请通知正确的客户端。使用RPC,您可能会从服务器发送“浏览”事件,损坏值。客户将通过对玩家的健康造成损坏来保持同步。

动画

动画对我们在服务器端的巨大成本。要正确地弄清楚拍摄是否击中,我们需要在播放器在客户端上看到的服务器上运行相同的动画。命中登记valorant.通过在历史缓冲区中保存播放器位置和动画状态来作用。当服务器从客户端接收拍摄报文时,它将使用历史缓冲区倒带播放器位置和动画状态,以计算镜头命中。最初我们正在计算动画并填充每个帧的缓冲区。但是,在仔细测试和比较之后,我们发现我们可以动画每一帧。在倒带的情况下,我们可以LERP.在保存的动画之间。这种有效地切割动画成本下降了75%。

另一个重要的实现是,摊销服务器性能是尺度上最重要的性能。想象一下A.valorant.服务器运行约150场比赛。亚博论坛在任何特定时间,这些游戏中的〜50次将在买阶段。亚博论坛玩家将安全地购买设备后面的产卵障碍,没有镜头可以伤害它们。我们意识到我们甚至不需要在购买阶段进行任何服务器端动画,我们可以关闭它。因此,这正是我们所做的 - 如果您查看服务器视图,玩家就在购买阶段的空闲姿势中。这有助于将动画系统的成本降低到另一轮左右的33%!

红色线框显示服务器的非动画仔仔宾客VS客户端的蓝色。

现实世界表现

现在你有品尝我们如何优化代码 - 但性能不仅仅是代码。这也是你正在运行的平台。因此,让我们讨论造成巨大问题的事情 - 操作系统和硬件。

为了正确测试我们的游戏如何在现实世界中表现,我们需要时尚载重测试。我们必须知道服务器如何在同一CPU上运行的100多个实例进行。建立负载测试对于成功启动至关重要valorant.。它允许我们预测每个玩家需要多少核心,并允许我们解决许多只出现在高负荷时的问题。结果,它并不像我之前提到的每核的7.8ms / 3游戏那么简单。亚博论坛

首先,让我们来看看这个图表。它在Y轴上的帧时间和X轴上的实例数。

所以只有一个实例运行,我们击中了一个光荣的1.5ms ......但是一旦我们有168个实例运行,我们就会悬停在大约5.7ms。

哦,不 - 这是怎么回事?要了解为什么发生这种情况以及我们如何解决它,我们必须先看看现代CPU架构。

CPU架构

看看上面的图像,你会注意到几个重要的事情。每个核心都有自己的L1 / L2高速缓存,但核心之间的L3缓存越大。只有一个在主机上运行的服务器,它会将L3缓存全部耗尽到自身,这导致较少的未命中 - 这意味着CPU核心花费更少的时间等待内存请求。这就是为什么我们的低负载方案让我们的服务器运行快速炽热,但由于缓存越来越大,每个实例都越来越响起,他们开始减速。我们对英特尔的云计算专家团队进行了一些测量,以确保我们没有击中热限制或其他因素,并简单地将其缩小以缓存性能。

与英特尔合作

幸运的是,英特尔从他们的平台测量和分析工具中汲取了一些伎俩。我们仍在播放旧的英特尔Xeon E5处理器,这使得使用包含的缓存。基本上,包容性意味着L2缓存中存在的每个缓存行必须也存在于L3缓存中。如果从L3缓存中驱逐线路,它也会从L2缓存中逐步驱逐!这意味着即使每个L2缓存都是分开的,也可能通过在L3高速缓存中引起逐步逐渐延伸彼此的L2高速缓存。

完全不公平,你觉得不觉得吗?使用英特尔Xeon可扩展处理器,英特尔将迁移到非包含的缓存,完全消除了这个问题。移动到更现代的Xeon可扩展的处理器显示我们的服务器应用程序的主要性能提升。我们仍然看到L3争用的影响,但我们看到性能增加了30%,甚至使用类似的时钟速度。

非统一内存访问

我们希望进一步推动我们的记忆性能。首先,您需要了解叫做非统一内存访问的现代CPU架构的另一个方面(numa.)。在服务器架构上,您通常会运行双(或更多)套接字CPU。这些套接字中的每一个都直接访问系统RAM的一部分,并通过互连共享数据。这允许增加内存带宽(2倍的连接),但互连可以成为瓶颈。重新审视上图,您可以看到具有两个套接字的Numa架构的简化布局。如果只有操作系统可以确保分配内存和CPU资源以保持互连流量......

好吧,事实证明,许多现代操作系统都是Numa-Arews和能够做这个。例如,在Linux上,一种方法是使用numactl.开始过程时。上valorant,我们在这样的节点之间来回开始游戏服务器实例:

numactl --cpunodebind = {mabid%2} --membind = {gameid%2} shouterg亚博论坛ameerver

通过这种小变化的最大利用架构导致了5%左右的性能提升。我们将内存访问从大约50%Numa Local到97-99%Numa Local的内存访问。除了5%之外,服务器实例之间的性能更加一致。

OS调度程序

在我们的时间监控游戏服务器主机期间,我们看到了一个有趣的模式,其中核心将悬停在90-96%的使用率约为90-96%,但即使将主机加载到2x的游戏数量,它也能够托管2倍。亚博论坛我们怀疑操作系统调度程序是原因,所以我们使用英特尔的PMU分析工具,自适应优化,以及Linux上的实用程序挖掘调度程序事件。利用Linux也意味着我们有机会查看调度程序的源代码。

通过我们的调查,我们了解到现代Linux使用完全公平的调度程序(CFS.)。调度程序真的很聪明,并具有许多优化。一个优化是它试图将过程保留在同一核心上,阻止它们迁移到其他核心上运行。它可能做的一个原因可以是允许进程重用仍然热的缓存行。另一个原因可能是防止不必要地唤醒空闲核心,以便做少量的工作。迁移成本基本上将在考虑允许它将其迁移到可用核心之前,将过程保持在繁忙的核心上等待一段时间。我们的Linux发行版中的默认值为.5ms。

valorant.在我们的2.34毫秒预算中,案例,.5ms是一个有意义的块。您可以在那段时间内处理近1/4的框架!任何游戏服务器的内存都有0%的几率仍然是缓存中的热点。虽然在帧之间的单个游戏服务器闲置时,其他游戏服务器正在将缓存充分利用其最大程度。通过将迁移成本设置降低到0,我们保证调度程序立即迁移需要运行到系统上任何可用核心的游戏服务器。这样做让我们在系统上更好地利用CPU资源,并授予另外4%的性能提升。此外,我们看到各个核心怠速下降到近0%的时间核心。

C-州

我们发现直接胜利的另一个领域正在控制C-Late.我们允许CPU进入。当多核CPU运行时,它允许核心进入不同的功率状态。在减少负载下,核心通常会进入较低的状态以节省权力。然而,一旦加载增加,那么这些核心将交换到更高功率状态需要时间。在高度循环工作负载中 - 就像一堆游戏服务器处理帧,然后睡觉 - CPU经常最终得到交换功率状态。每个交换都具有对性能产生负面影响的延迟。通过将我们的进程限制在更高的C状态(C0,C1和C1E),我们能够稳定地举办1-3%的游戏。亚博论坛它特别稳定为60-90%的加载服务器,减少工作量允许许多核心经常怠速。

超线程

超线程是一种CPU架构技术,其中单个物理核心可以举办两个同时线程。通过超线程,核心的某些部分是共享的(如缓存),并且某些部分(如不同的计算单元)被复制。

它最终取决于您正在查看的特定CPU。在开发的早期,我们有25亿帧时间,我们发现关闭超线程产生20ms帧时间。董事会的性能增加25%!但是,我们在英特尔的朋友持怀疑态度。鉴于我们的负载,我们可以通过利用超线程优惠的虚拟核心来屏蔽更多的硬件。当我们翻转超线程时,我们看到性能增加了25%。

这怎么发生的?沿途,我们将服务器帧时间减少到低于我们的7.8125ms目标。我们迁移到英特尔Xeon可扩展处理器架构,这些架构改善了缓存和超线程性能。我们调整了调度程序,以更好地利用可用的核心。我们在C1E下面禁用C-Series以获得更好的核心延迟和许多其他优化。

测量的重要性

这里的课程是每个应用程序的性能概况和考虑因素是不同的。即使是每年的同一应用程序也可以急剧上的性能需求。可以肯定的唯一方法是创建一个可重复的测试和测量

如果您只需在Internet上的游戏开发博客帖子中列出了“性能调整”,并且在互联网上的游戏开发博客帖子,并且在不考虑您的应用程序的特定需求和考虑因素的情况下,您可能会伤害比您的表现更好。

其他性能优化

ClockSource.

亚博论坛游戏往往经常标记时间的流逝。这通常是通过通过对OS的系统调用来完成的ClockSource.。在虚拟机管理程序环境(如AWS)中运行的操作系统可能会使用不太表演的虚拟化时钟源。在我们的AWS节点上,我们最初使用Xen Hypervisor提供的Xen ClockSource。我们更改为CPU指令RDTSC提供的TSC ClockSource。对于我们的游戏服务器,我们可以通过移动我们的ClockSource来获得大约1-3%的性能。

幽灵故事:它只发生在刺子上

当我们临近我们的船舶时,我们注意到我们的游戏服务器负载测试主机之一比其他游戏服务器更糟糕。它是相同的硬件,唯一的区别是它正在运行我们的完整部署堆栈。在生成此框上运行负载测试双倍到三倍搭乘手动上携带的硬件上运行的猎犬或慢帧的数量。我们调查了几个角度 - 可能是AWS虚拟机管理程序,配置差异,甚至是糟糕的硬件?什么都没有淘汰。

最终我们决定再次在Linux调度程序中查看完善的时间表只要看看我们是否可以找到对流程如何运行的一些差异。我们发现,每5秒钟,如发条,72进程将开始称为scheduler_1 ... scheduler_72。每个虚拟核心一个。这些将开始并立即将任何正在运行的游戏服务器关闭。在高负载的游戏服务器上,这导致了级联的搭便车。事实证明,我们使用的MESOS用于我们的部署,利用了TeleGraF的指标,这使DNS请求每5秒劫持,它被erlang应用程序劫持了DCOS_NET。

Erlang可配置它的调度程序允许生成多少线程。默认值是系统上每个核心的一个线程,因此72个进程。一旦我们将其设置为更合理的默认值,如4,问题会在一夜之间消失。这里的课程是,在与您的生产环境匹配的配置中测量性能非常重要!

结论

最终,很容易想念树木的森林。即使在这种快速的飞行中,通过我们的一些性能努力,技术细节也可以快速堆积。很容易迷失在微小的细节,调整和奇怪中。

你真的必须不断重新审视并强化您记住的整体性能目标。确保将整个团队保持在您的目标周围,以便您可以在合适的时间争取您团队的正确帮助。

代码优化是一个很大的性能部分,但您需要能够将您的应用程序性能分解为离散块。不要忘记优化环境(硬件和操作系统)以最有效的方式托管您的应用程序。

以上所有措施,测量,测量valorant.测量最终使我们能够在预测服务器硬件的同时推出1%以内。这导致了光滑的发射经验和为我们的玩家提供的128个刻度网。

我想结束特别感谢与我们合作的英特尔团队来调查硬件和操作系统调整。

  • 金麦克劳林
  • Harshad S智典
  • Dory Simaan.
  • Prabha Viswanathan.

他们的洞察力和贡献对于帮助我们履行绩效目标非常宝贵。

谢谢阅读!如果您有任何疑问或意见,请在下面发布。

由布伦特兰德发布