Node.js vs Amp vs Swoole vs Go helloworld web server performance

server.js

const http = require('http');

const hostname = '0.0.0.0';
const port = 1337;

const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.end('Hello World!');
});

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

server.php

<?php
require __DIR__ . '/vendor/autoload.php';
error_reporting(-1);
use Amp\Http\Server\RequestHandler\CallableRequestHandler;
use Amp\Http\Server\Server;
use Amp\Http\Server\Request;
use Amp\Http\Server\Response;
use Amp\Http\Status;
use Amp\Socket;
use Psr\Log\NullLogger;

// Run this script, then visit http://localhost:1337/ in your browser.

Amp\Loop::run(function () {
    $sockets = [
        Socket\listen("0.0.0.0:1338"),
    ];
    
    $server = new Server($sockets, new CallableRequestHandler(function (Request $request) {
        return new Response(Status::OK, [
        ], "Hello World!");
    }), new NullLogger());

    yield $server->start();

});

swoole.php

<?php
$http = new swoole_http_server("127.0.0.1", 9501);
$http->on("start", function ($server) {
    echo "Swoole http server is started at http://127.0.0.1:9501\n";
});

$http->on("request", function ($request, $response) {
    $response->end("Hello World");
});

$http->start();

server.go

package main

import (
    "fmt"
    "log"
    "net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello World")
}

func main() {
    http.HandleFunc("/", handler)
    log.Fatal(http.ListenAndServe(":8080", nil))
}

测试命令为:ab -c1000 -n30000 http://127.0.0.1:1337/

最后结果对比如下:

结论:AMP异步非阻塞框架实现的web server性能最差,swoole和go性能相当。本测试只供参考。

WARN com.mchange.v2.async.ThreadPoolAsynchronousRunner – com.mchange.v2.async.ThreadPoolAsynchronousRunner$DeadlockDetector@43502400 — APPARENT DEADLOCK!!! Complete Status:

可能是数据服务器连接不上,请确认数据库配置先。

flowable 配置运行在 MySQL 数据库

flowable 下载下来后有五个war文件直接放到 Tomcat webapps 目录下即可使用,默认使用h2内存数据库,如果尝试更改配置文件使用MySQL会提示 com.mysql.jdbc.Driver 这个类不存在或找不到。

(更优解决方案请参考本文评论。)

解决方法是重新编译打包,步骤如下:

下载 flowable 源代码后,分别进去 flowable-app-rest , flowable-ui-modeler, flowable-ui-idm, flowable-ui-task 等目录使用

命令进行编译打包,进入 flowalbe-ui-admin 目录使用

命令进行编译打包,将 war 放到 Tomcat webapps 目录下,启动Tomcat会自动解压得到同名目录,然后修改对应数据库配置即可。

将图片由 RGB 转为 CMYK 格式

 

PHP-PM 执行原理

大体流程如下:主进程监听两个socket,一个接收外部 http 请求(web 服务器),另一个与子进程通信。主进程通过 proc_open 调用创建子进程,每个子进程会监听一个 socket(http 服务器),主进程将 http 请求转发给子进程进行处理。子进程在 bootstrap 阶段会 new 一个 Application (假设是 symfony 框架),后面所有的请求都不会再重复初始化 Application (因此比传统 PHP-FPM 执行速度快)。

画了一个图

PHP7 的高性能来自于哪些改进

  • 变量容器 zval 结构体定义改变,减少内存占用,减少引用计数相关操作。
  • zend_string。字符串复制的时候,采用引用赋值,zend_string可以避免的内存拷贝。
  • zend_array。数组的value默认为zval。
    HashTable的大小从72下降到56字节,减少22%。
    Buckets的大小从72下降到32字节,减少50%。
    数组元素的Buckets的内存空间是一同分配的。
    数组元素的key(Bucket.key)指向zend_string。
    数组元素的value被嵌入到Bucket中。
    降低CPU Cache Miss。
  • 改进函数调用机制。
  • 通过宏定义和内联函数(inline),让编译器提前完成部分工作

参考链接:

  1. http://www.csdn.net/article/2015-09-16/2825720
  2. PHP’s new hashtable implementation
  3. Internal value representation in PHP 7 – Part 2

MyISAM 和 InnoDB 存储引擎区别及各自使用场景

InnoDB 主要优势

  • 事务支持:事务提交回滚以及错误恢复。
  • 行级锁
  • 聚合索引
  • 外键支持

InnoDB 在 MySQL 5.6.4 后支持全文索引。

MySQL 5.5 后默认存储引擎为InnoDb。

如果不能使用到索引,行级锁会失效。

如何选择两种存储引擎

大量读,几乎没有写请求 和 小于5.6.4版本需要全文索引,选择 MyISAM,其他情况选择InnoDB。

我的性能测试结果,仅供参考

单进程插入10万条记录,MyISAM 1.8348009586334 秒, InnoDB 2.0098528862 秒

6个进程同时各插入10万条记录,MyISAM 3.860533952713 秒, InnoDB 2.9386329650879 秒(每个进程运行时间差不多,文章中给出的是其中一进程的运行时间,下同)

12个进程同时各插入10万条记录,MyISAM 7.4965870380402 秒, InnoDB 5.0007991790771 秒

单进程插入1万条记录,MyISAM 4.3874440193176 秒, InnoDB 3.8677229881287 秒

6个进程同时各插入1万条记录,MyISAM 9.7532279491425 秒, InnoDB 6.4886889457703 秒(平均每个进程运行时间)

12个进程同时各插入1万条记录,MyISAM 22.401536941528 秒, InnoDB 8.3166329860687 秒(平均每个进程运行时间)

12个进程同时主键SELECT1万次,MyISAM 3.3773090839386 秒, InnoDB 3.3466641902924 秒(平均每个进程运行时间)

30个进程同时主键SELECT1万次,MyISAM 8.7141139507294 秒, InnoDB 8.6588280200958 秒(平均每个进程运行时间)

总结:从这个测试结果来看,InnoDB几乎是完胜啊。(结果仅供参考,或许完全没有参考价值,毕竟与真实业务中的查询情况相差巨大)