Skip to content

性能提升50%,支持连接池负载均衡、事务嵌套

Compare
Choose a tag to compare
@Yurunsoft Yurunsoft released this 29 Oct 02:06

关于此次更新

有一些热心开发者经常问我imi的性能怎么样,稳定性怎么样。由于imi也才刚刚起步,之前并没有对这方面进行测试和优化。

最近一段时间,经过努力,imi 的启动性能、运行性能以及稳定性,全部都有巨大的提升。

针对返回jsonapi环境(无数据库操作)下测试(worker_num=2,并发1000),新版比旧版并发性能提高了50%以上。

下面详细讲解一下,我们所做的工作。

启动性能

在框架初始化完成事件IMI.INITED中,运行一个imi/buildRuntime工具进程。

这个工具里面,扫描项目中所有注解,将它们保存到缓存文件中。(对了,现在的imi拥有一个专门用于存放运行时文件的目录,原本零零散散的文件现在都统一了,默认在临时目录,可以通过配置指定。)

然后在Worker进程中,加载缓存文件,避免重复扫描注解。降低对硬盘读取次数,提高了海量性能!

同样的,在热更新检测到文件更改后,在重启之前,再一次运行imi/buildRuntime工具,然后再执行重启操作。

这样,在启动项目以及热重启时,节省了毫无价值的多次硬盘读取。

运行性能

首先,imi 的对象代理,使用的是匿名类继承原本的类的方式。在之前的版本中,生成匿名类的过程中,针对所有方法都做了代理。调用任意方法都需要进入imi的代理方法中进行额外的处理计算。

在最新版的 imi 中,只针对注入了的方法做代理,所以减少了许多不必要的方法调用以及判断处理等,所以运行性能提升巨大。

稳定性

这个就要说到在 imi 中出现过多次的奇怪问题了,在最近终于弄懂,能够确定是 php 本身的 bug

我已经把这个bug反馈给php了:https://bugs.php.net/bug.php?id=77050

然而其实这个bug早在2016年就被人发现,至今没有修复,先吐槽一下……

这个 bug 是使用 eval 实例化匿名类出现的问题,之前说了,imi 的对象代理使用的是匿名类继承原本的类的方式。具体问题这里不再阐述,具体进 bug 反馈页面里看测试代码吧。

后来 imi 使用的是写入文件,然后include的方式来实例化。然而,在一键协程化的支持后,又出现了新的问题。

很难用语言进行描述,总之目前已经完美解决了这个问题。具体解决方式可以查阅BeanFactory.php的git日志。

更新日志

新增

  • 实现连接池负载均衡,模式:轮流、随机

  • 新增 AnnotationManager 来进行注解统一管理

  • 新增支持 MySQL 事务嵌套

  • 新增支持注入带有注解的方法

  • 新增日志trace精简配置项(实现性功能)

  • 新增项目初始化完毕提示(App Inited)

优化

  • 优化对象代理类性能

  • 优化事件处理性能

  • 将运行时生成的文件统一归类到runtime目录中

  • 实现注解缓存机制,减少Worker进程中不必要的文件I/O

  • 当启用Session中间件时,只有写入了数据,才会发送SessionID响应头

  • 当启用Session中间件时,如果不写入数据,将不再保存(避免正常访问及压测时,写入了过多无意义的数据)

  • 调整Worker::getWorkerID()实现方式

  • 优化 Imi::getNamespacePath() 方法尽可能返回绝对路径

  • 优化池子异常信息

修复

  • 修复删除bean类缓存时,未删除文件夹问题

  • 解决实例化Bean类相关、一键协程化开启后的问题

  • 修复 BeanFactory::newInstance() 可能会引起的问题

  • 优化模型提取属性实现方式,解决特殊情况下影响关联的问题

  • 修复 AbstractMessage 和 ServerRequest 问题

  • 修复模型 Serializable 注解在特定情况下部分失效的问题

  • 修复文件日志驱动可能报warning的问题

  • 修复特殊情况下注解扫描加载的问题

  • 修正注释问题