[Dr.Lib]Minecraft 服务器资源控制策略:AI 抑制而非数量限制

转载自 Minecraft 服务器资源控制策略:AI 抑制而非数量限制 · Phoenix’s island

Minecraft 的 lag 问题已经司空见惯,各种控制资源消耗和卡顿的插件也层出不穷。但是它们几乎都非常用力地在一个点上:控制实体数量。

这并不无道理,因为 Minecraft 中最消耗资源的部分就是实体。但是暴力控制实体数量会导致刷怪塔无法正常工作、掉落物清理速度过快等问题,在生存服务器中可能引发玩家的强烈不满。

所以,喵窝开发组从另一个角度做出了一些尝试。

启发

生物实体的数量巨大,主要集中的地区显然不是野外的自然刷怪区,而是玩家聚集的刷怪场、村民工程、动物养殖场等。如果不限制生物的数量和密度同时降低资源消耗,那么只能从生物实体的特性入手了。

Minecraft 最近的版本中引用了 NoAI  的 NBT Tag,带有此标签的生物将不会进行 AI 计算。换句话说,除了占用服务器内存中的一点数据,几乎不会对这个生物实体有任何其他的 CPU 算力消耗。

也就是说,实体消耗的算力资源,绝大部分都是 AI 计算的消耗。

方案

抓上一票人做了一些测试,结果证实生物失去 AI 后大幅降低了 CPU 的算力消耗。这是个 positive 的信号,但是接下来的测试则遇到了问题。

对于养殖场,等生物数量变化不大(或者说只是定期来清理并重新养殖一次)的设施,生物失去 AI 的影响很小,只有在重新繁殖时需要恢复 AI。但是刷怪塔则因为生物没有 AI,同时也被强制不受重力影响而几乎无法使用,即便同时设置 NoGravity 为 false 也无效。

开发组中 @Librazy 提到了 Spigot 的一个参数 nerf-spawner-mobs ,开启时刷怪笼生成的生物将不会拥有 AI,但是会被外界影响(例如水流和火球等)而移动。这个选项是全局的,因此不需要开启,只需要反射 spigot 中设置该功能的方法即可。

经过 @Cylin 查阅Spigot的代码,这个参数会给刷怪笼生成的实体设置 fromMobSpawner = true ,导致实体的 doTick()中跳过实体的AI处理。

于是整个方案的流程便是当服务器卡顿时抑制生物密集区的生物 AI 从而降低资源占用,同时最大程度上保证玩家对生物的需求。「服务器卡顿」的考量以服务器 TPS 而非实体数量为准,当服务器 TPS 高于一定值时即认为服务器没有超负荷,不会有任何操作,最大程度上利用硬件的性能。

实现

插件主要由开发组的 @Cylin 编写,源代码以 MIT 协议发布在 GitHub 上。

插件每隔一段时间扫描服务器的 TPS 确认运行状况,如果 TPS 低于阈值则触发 AI 控制,TPS 高于一定值且持续一段时间即认为服务器已恢复正常运行状态,自动恢复被抑制的实体 AI 减少对生存体验的影响。

实现过程中额外添加了一些额外可能被生存服务器用到的功能:

  • per-world 控制,如果玩家需要建造以仇恨为基础的小黑塔,可以关闭对末地的控制。
  • 实体总量和单区块实体密度在 AI 抑制时纳入考虑,更加精准抑制资源消耗较高的区块。

测试

yasui 插件在 毛玉線圈物語 服务器中应用测试。由于近期玩家数量爆炸式增长(日常在线 5 人到 ~30 人甚至 50 人),各种实体控制插件均告无效。yasui 插件应用后被证实数次发挥作用,没有任何实体数量限制的前提下将服务器 TPS 稳定在 19 以上,服务器实体承载数量从 ~2500 提到至接近 5000,并且还有继续提高的可能(数次触发中最高一次单世界实体记录是 4808,其他世界中仍有大约 2000 实体未被计入)。

吐槽:你们贼能刷

[Dr.Lib]跑起一个TiDB

TiDB 是新一代开源分布式 NewSQL 数据库,模型受 Google Spanner / F1 论文的启发, 实现了自动的水平伸缩,强一致性的分布式事务,基于 Raft 算法的多副本复制等重要 NewSQL 特性。 TiDB 结合了 RDBMS 和 NoSQL 的优点,部署简单,在线弹性扩容和异步表结构变更不影响业务, 真正的异地多活及自动故障恢复保障数据安全,同时兼容 MySQL 协议,使迁移使用成本降到极低。

PingCAP

TiDB 是 PingCAP 公司基于 Google Spanner / F1 论文实现的开源分布式 NewSQL 数据库,具备如下 NewSQL 核心特性:

  • SQL支持 (TiDB 是 MySQL 兼容的)
  • 水平线性弹性扩展
  • 分布式事务
  • 跨数据中心数据强一致性保证
  • 故障自恢复的高可用

一个完整的 TiDB 集群包括 PD,TiKV 以及 TiDB。

获取TiDB 官方 Binary

在 Archlinux 下可以使用AUR中的tidb-bin-nightly包。对于大多数发行版,官方的二进制都能完美的工作。

可以使用-V命令查询当前二进制的版本、编译时间。

部署TiDB

我的测试环境有三台机器,为方便起见做了如下配置

单节点部署

官方文档参考

启动TiDB需要按顺序启动 PD -> TiKV -> TiDB

在服务器上部署的时候,可以在nohup或者tmux中启动。笔者推荐使用基于tmux的byobu以方便管理与监控。

在以受限用户运行tikv的时候,可能会遇到这样的错误

此时可以选择以root用户启动或在配置文件中按实际情况指定RocksDB的max-open-files。

全部启动完成后,就可以使用mysql客户端连接了。TiDB默认的MySQL监听端口是0.0.0.0:4000

添加与卸载节点

官方文档参考

添加pd节点

在两台机器上分别启动pd节点并加入集群

添加tikv节点

可以使用pd-ctl查看当前集群状况

删除节点

可以用pd-ctl进行,或使用PD API

多节点集群模式部署

官方文档参考
在三个机器上分别启动pd实例

pd启动完成后,启动tikv实例

启动tidb

开始使用TiDB

你可以从 MySQL 无缝切换到 TiDB。如果您现有的业务已经基于 MySQL 开发,那么大多数情况下无需修改代码即可直接替换单机的 MySQL

 

更多信息可以参考官方文档

[Dr.Lib]各种.travis.yml

于是这两天撸mod和插件的.travis.yml的时候还是整出了不少东西的,记录一下什么的。

C++: 测试Clang3.8 & GCC 6 的 Coveralls 数据

这个是当年折腾数据结构时写的CI了,因为travis的Ubuntu环境目前还是古代的12.04 precise,所以很多东西要么走PPA要么直接下

这里我用的是两个镜像,分别测Clang与GCC。由于两个编译器的目标gconv版本不同所以还需要判断一下.

Java Minecraft Forge mod:repo无关的.travis.yml & 自动更新update.json

其实主要部分还是给了gradle来做= =

要做到.travis.yml和gradle里不带repo信息的话,善于利用环境变量吧。

有一个遗憾是 travis-ci/dpl issues#613 ,暂时没法自动设定是否为prerelease^

 

Java Spigot plugin:repo无关的.travis.yml & 自动更新maven repo

 gz

[Dr.Lib@ASTL]开始使用Open-Channel SSD

Open-Channel SSD文档翻译:

https://github.com/OpenChannelSSD/documentation/blob/master/docs/gettingstarted.md

 

要使用Open-Channel SSD,操作系统内核的支持是必要的。通过LightNVM 子系统的引入,Linux内核在4.4及以后的版本添加了Open-Channel SSD支持。OpenChannelSSD 这个项目仍在开发中,推荐使用最新的 release 版本或者RC版。最新的源码可以参见https://github.com/OpenChannelSSD/linux

启动一个受支持的内核后,需要满足下列条件:

  1. 一个兼容的设备,如QEMU NVMe或者一个Open-Channel SSD,如 CNEX Labs LightNVM SDK.
  2. 驱动之上的媒体管理器。媒体管理器负责管理设备的分区表。
  3. 块设备管理器之上暴露Open-Channel SSD。

继续阅读 “[Dr.Lib@ASTL]开始使用Open-Channel SSD” »

GeekyTeen Conference 青少年极客大会 2016

GeekyTeen Conference 青少年极客大会将于 2016.07.14-2016.07.15 于厦门举行~这是一个交流先进思想,了解先进技术的交流平台。虽说是青少年,但却不局限于他们。今年的活动将有Rust编程语言、二进制逆向、Docker 容器化部署、Meteor 等主题,将有相关的从业人员或者爱好者到场讲解,与听众交流。

继续阅读 “GeekyTeen Conference 青少年极客大会 2016” »

Posted on by

Functional Programming For The Rest Of Us

Via https://github.com/justinyhuang/Functional-Programming-For-The-Rest-of-Us-Cn/blob/master/FunctionalProgrammingForTheRestOfUs.cn.md

傻瓜函数式编程

2006年6月19日,星期一

开篇

我们这些码农做事都是很拖拉的。每天例行报到后,先来点咖啡,看看邮件还有RSS订阅的文章。然后翻翻新闻还有那些技术网站上的更新,再过一遍编程论坛口水区里那些无聊的论战。最后从头把这些再看一次以免错过什么精彩的内容。然后就可以吃午饭了。饭饱过后,回来盯着IDE发一会呆,再看看邮箱,再去搞杯咖啡。光阴似箭,可以回家了……
(在被众人鄙视之前)我唯一想说的是,在这些拖拉的日子里总会时不时读到一些不明觉厉的文章。如果没有打开不应该打开的网站,每隔几天你都可以看到至少一篇这样的东西。它们的共性:难懂,耗时,于是这些文章就慢慢的堆积成山了。很快你就会发现自己已经累积了一堆的收藏链接还有数不清的PDF文件,此时你只希望隐入一个杳无人烟的深山老林里什么也不做,用一年半载好好的消化这些私藏宝贝。当然,我是说最好每天还是能有人来给送吃的顺带帮忙打扫卫生倒垃圾,哇哈哈。

我不知道你都收藏了些什么,我的阅读清单里面相当大部分都是函数式编程相关的东东:基本上是最难啃的。这些文章充斥着无比枯燥的教科书语言,我想就连那些在华尔街浸淫10年以上的大牛都无法搞懂这些函数式编程(简称FP)文章到底在说什么。你可以去花旗集团或者德意志银行找个项目经理来问问1:你们为什么要选JMS而不用Erlang?答案基本上是:我认为这个学术用的语言还无法胜任实际应用。可是,现有的一些系统不仅非常复杂还需要满足十分严苛的需求,它们就都是用函数式编程的方法来实现的。这,就说不过去了。
关于FP的文章确实比较难懂,但我不认为一定要搞得那么晦涩。有一些历史原因造成了这种知识断层,可是FP概念本身并不难理解。我希望这篇文章可以成为一个“FP入门指南”,帮助你从指令式编程走向函数式编程。先来点咖啡,然后继续读下去。很快你对FP的理解就会让同事们刮目相看了。

什么是函数式编程(Functional Programming,FP)?它从何而来?可以吃吗?倘若它真的像那些鼓吹FP的人说的那么好,为什么实际应用中那么少见?为什么只有那些在读博士的家伙想要用它?而最重要的是,它母亲的怎么就那么难学?那些所谓的closure、continuation,currying,lazy evaluation还有no side effects都是什么东东(译者:本着保留专用术语的原则,此处及下文类似情形均不译)?如果没有那些大学教授的帮忙怎样把它应用到实际工程里去?为什么它和我们熟悉的万能而神圣的指令式编程那么的不一样?
我们很快就会解开这些谜团。刚才我说过实际工程和学术界之间的知识断层是有其历史原因的,那么就先让我来解释一下这个问题。答案,就在接下来的一次公园漫步中:

继续阅读 “Functional Programming For The Rest Of Us” »

[时间复杂度 Time Complexity of Algorithms

神犇说世上的美有三种,一是优美精致的数据结构,二是巧夺天工的神奇算法,三是你温暖世界的笑容

计算机之所以叫做计算机,就是因为它在“计算”这一件事上做的可以比人类快。而我们的任务,就是告诉计算机要如何去进行一个计算,也就是要实现一个算法。
想要让程序更快,除了要提升计算机处理器的运行速度之外,最重要的就是要提升算法的效率,以及算法的在这个计算机上实现的的速度。
做同样的一件事情,可以有无数种做法。比如说给一些数字排序,就有好几种做法。那么要怎么比较他们的速度呢?
最直观的做法自然是写出对应的程序,给定一个输入,然后比较一下他们的运行时间。这样的做法简单粗暴,然而并不能给我们关于这些算法的更多信息,也只能反映这些算法在这个特定输入的情况,误差也不容小视。
更为严谨的做法,是对这个算法进行数学上的分析,以得出这个算法在理论上的运行效率。
以选择排序为栗子把
(然后把栗子剥开吃掉~

来看看他的运行原理
选择排序
第零轮从所有的n个数据中找出最小的,需要对每个\(j\in \left ( 0,n \right )\)进行一次比较,共n-1次
第一轮从剩下的n-1个数据中找出最小的,需要对\(j\in \left ( 1,n \right )\)每个进行一次比较,共n-2次
……
第i轮从剩下的n-i个数据中找出最小的,需要对\(j\in \left ( i,n \right )\)每个进行一次比较,共n-i-1次
第n-2轮从剩下的2个数据中找出最小的,需要进行一次比较

总共需要进行 \(\sum_{k = 1}^{n-1} k=\frac{n\left ( n-1 \right )}{2}\)次比较
然后每轮需要对数据进行一次交换,合计是\(\left ( n-1 \right )\)次交换
也就是说,这个程序所需要运行的时间大致上是
\(T=\frac{n\left ( n-1 \right )}{2}T_{0}+\left ( n-1 \right )T_{1}\),其中\(T_{0}\)为一次比较需要的时间,\(T_{1}\)为一次交换所需要的时间
当n很大的时候,对T的量级起到决定性作用的将会是什么呢?
(还记得函数在无穷大的极限吗?
n趋向于无穷大时,起作用的将会是n的二次项,也就是\(\frac{n^{2}}{2}T_{0}\)
那么可以看出,选择排序的算法的运行时间在n充分大的时候,大致正比于\(n^{2}\)
继续阅读 “[时间复杂度 Time Complexity of Algorithms” »

[海韵日常]以及图集


军训结束,开学了。
说好的昨天写的,可是时间关系拖到了今天。
今天早上班级一起做了素质拓展活动,感觉萌萌哒。
以及下午参观了图书馆总部。回来后我在宿舍东图随手借了几本。
)剩下的明天写吧
继续阅读 “[海韵日常]以及图集” »

……其实只是想给这几天啥都没干找个借口而已嘛

Win10

GTA GTC15前就看到10240出来,抱着尝鲜的心态下了偷跑的ISO刻了个U盘,备份一下就从Win8.1U1Home升级到了Win10Pro……额果然没办法激活,先KMS撑了几天。

回来后就听说Win10开始推送了,想一想KMS续命可麻烦了……老老实实OTA

还原8.1,联想一键备份duang的一下告诉我“不能访问文件”……呵呵你把我C盘格了再告诉我没法还原?

神奇的是一个NTFS分区被格居然搞的我的Ubuntu都起不来了,我望着我电脑上唯一能用的系统——android5.1在月光下凌乱。

用U盘全新安装了个Win10Home,还是没法激活,先将就用着

折腾了半天备份文件确认是C盘的备份文件在备份时就损坏了,还原前赶时间没有备份Win10呵呵C盘所有数据都丢了吧

想一想有一个原厂Win8镜像恢复上,然后再安装Win10Home……嗯还是没办法激活。孩子激活老不好,多半是SKU废了

找了个OEM的镜像果然可以哈哈哈哈

然后我的GRUB呢?
继续阅读 “[Dr.Lib]工欲善其事,必先利其器” »