顶级 Swift 服务端框架对决 Node.js

简介: 本文讲的是顶级 Swift 服务端框架对决 Node.js,Swift 是一个可以被用来做包括服务端在内的任何事情,从他第一次开源并且移植到 Linux 上就一直很引人入胜。你们肯定有很多人像我一样好奇,所以我非常乐意来分享我的学习成果。
本文讲的是顶级 Swift 服务端框架对决 Node.js,

前言

最近我在做服务端 Swift 工作时,我被问到这样的问题:

「在服务端 Swift 能否击败 Node.js?」

Swift 是一个可以被用来做包括服务端在内的任何事情,从他第一次开源并且移植到 Linux 上就一直很引人入胜。你们肯定有很多人像我一样好奇,所以我非常乐意来分享我的学习成果。

最受欢迎的服务端 Swift 框架

在写这篇文章的时候,按照 Github 上获得 star 的数量顺序排列最受欢迎的服务端 Swift 框架如下:

本文组织形式

本文将以以下方式呈现:

  • 这份快速指引
  • 结果摘要
  • 方法学
  • 详细的结果
  • 结论和说明

结果摘要

以下是主要测试的结果摘要,我想说的是:

无论各项得分怎样,这些框架内所有的表现都非常棒

这张图片在 2016 年 9 月 1 日更新

方法学笔记

为什么使用博客和 JSON?

搭博客比打印 "Hello, World!" 到屏幕上有常见的用途,JSON 也是一种很常见的用例。良好的基准测试需要考虑每个框架在相似负载下的表现,它需要比简单的打印两个单词到屏幕上承载更多的压力。

保持做相同的事情

在每一个主题测试项目中我都会尽量保证博客尽可能相似,同时贴合每个框架的语法风格来完成。为了在许多数据结构中一字不差的使用不同框架生成相同的内容,让每个框架都使用相同的数据模型工作,但是有些方面例如 URL 路由等方式会有很大的差别来适应每个不同框架中的语法和风格。

一些微小的差别

在不同的 Swift 服务端框架直接有一些微小的差别需要注意。

  • 在 Kitura 和 Zewo 中,如果绝对路径中存在空格都会在构建时引发一些问题,在 Xcode 中构建任何框架也存在相同的问题。

  • Zewo 使用 05-09-a 的 Swift 快照版本,这意味着他在 release 模式下的构建存在一些问题,所以他运行在 debug 模式下。因为这个问题存在所以所有关于 Zewo 的测试都运行在 debug 模式下(这将不包含 release 优化)。

  • 静态文件的处理是一个众多服务端 Swift 框架争议的焦点。Vapor 和 Zewo 都建议使用 Nginx 来作为静态文件的代理,然后使用框架来作为后端使用。Perfect 的建议是使用其内置的处理程序,但我并没有有看见 IBM 对此相关的任何评论。由于这项研究不是为了探讨框架如何连接 Nginx 这样的服务器应用,所以静态文件都使用了每个框架本身来处理。你或许可以为了性能考虑而在选择 Vapor 和 Zewo 的时候考虑这个问题,这也是为什么我考虑包含 JSON 测试的一个原因。

  • [在 9 月 1 日更新的结果] Zewo 是一个单线程应用程序,你可以通过在每一个 CPU 上都运行一个实例来获得额外的性能提升,因为他们是并发运行而不是在多线程模式下工作。在本研究中,每个应用程序只会有一个实例运行。

  • 工具链 (Toolchains),每个框架都从 Apple 释出的工具链中选择了不同的快照版本,在本文发布时测试的版本如下:

    • DEVELOPMENT-SNAPSHOT-2016-08–24-a for Perfect
    • DEVELOPMENT-SNAPSHOT-2016-07–25-a for Vapor & Kitura
    • DEVELOPMENT-SNAPSHOT-2016-05–09-a for Zewo
  • Vapor 运行 release 特殊语法。如果你只是简单的去执行二进制包,你将会在控制台中获得一些可以帮助开发和调试过程的日志记录。这将会带来一些额外的性能开销,为了让 Vapor 运行在 release 模式下你需要添加 --env=production 来运行,例如:

    .build/release/App --env=production
  • [在 9 月 1 日更新的结果] 当使用 Zewo 的时候,即使你不能在 05-09-a 工具链上使用 release 模式,你依然可以通过添加以下代码来进行 release 优化:

    swift build -Xswiftc -O
  • Node.js / Express 没有构建编译,因为他没有 debug 和 release 的区别。

  • 静态文件处理包括了 Vapor 的默认中间件。如果你没有使用静态文件并且想要优化速度(译注:原作者的意思是如果没有用到它来处理静态文件,那么用这个方法来忽略掉 Vapor 默认的中间件以提高速度。),你必须包含如下代码(就像我在 VaporJSON 中所做的一样):

    drop.middleware = []

为什么使用 Node.js / Express?

我决定使用 Node.js 的 Express 来作为一个对照包含在测试中。因为他和 Swift 服务端框架具有非常相似的语法并且被广泛应用。他有助于建立一个基线来展示 Swift 能够多么的让人印象深刻。

开发博客

在某些时候开始,我称之为「追逐弹球」。目前 Swift 服务端框架处于非常活跃的开发状态,因为 Swift 3 的每一个预览版相对于上一个都有成堆的改动。所以 Apple 的 Swift 团队导致所有的服务端 Swift 框架需要频繁的发布新版本。他们没有拥有完善的文档,所以我非常感谢框架的小组成员和广大 Swift 服务端框架社区。我也要对无数的社区成员和框架团队在我前进道路上给予的帮助表示感谢。这有很多的乐趣,我很乐意这样做。

一个额外声明,即使不需要许可说明,我也认为这个需要声明一下:所有包含在源码中的资源都来自 Pixbay 的无版权图片,这对于制作一个示例程序很有帮助。

环境和变量

为了尽量消除不同环境带来的影响,我使用了一个 2012 款的 Mac mini 并且重新安装了 El Capitan (10.11.6),然后下载了 Xcode 8 beta 6,并且设置 command-line-tools 为 Xcode 8。然后使用 swiftenv 安装了必要的快照版本,克隆仓库并且在 release 模式下清洁的编译每一个博客,并且不会同时进行两个测试。测试服务器的规格是这样的:

而在开发中我使用的是 2015 款的 rMBP。我在这里进行了构建测试,因为它是我现实生活中的开发设备所以更有意义。我用 wrk 来获得评分,并且我使用 Thunderbolt 2 线缆来连接两台设备,因为 Thunderbold 桥接能拥有一个令人难以置信的带宽使得你的路由器不会成为限制条件,他能更可靠的在博客单独运行在一台机器上的时候用另一个独立的机器去生成负载以压倒性的测试服务器。这提供了一个一致的测试环境,所以我可以说每个博客都是在相同的硬件和条件下运行,为了满足一些好奇心,我开发设备的规格是:

测试基准

在测试中,我决定使用 4 个线程各生成 20 个连接并持续 10 分钟。4 秒钟不能称之为测试,而 10 分钟是一个合理的时间,因为能获得大量的数据并且 4 个线程运行 20 个连接会对博客造成沉重的负担而不至于断开链接。

源代码

如果你想探索这个项目的源代码或者做任何自己的测试,我把这些测试代码都整合到了一个仓库中,你可以在这里找到:

https://github.com/rymcol/Server-Side-Swift-Benchmarking

详细结果

构建时间

我认为可能需要先看一眼构建时间。构建时间在日复一日的开发中占据了很大一部分开发时间,并且他也能算作是框架的性能表现,我觉得我在探索的是真实的数字和持续时间的感觉。

如何运行

对于每一个框架,

swift build --clean=dist

然后

time swift build

运行完之后,进行第二次测试

swift build --clean

最后

time swift build

这两次构建都使用了 SPM(Swift Package Manager, Swift 包管理器) 来管理依赖关系,包括常规的、清洁的依赖都已经下载好了。

怎么运行的

这运行在我本地的 2015 款 rMBP 上并且构建在 debug 模式,因为在使用 Swift 开发应用时这是正常的过程。

构建时间结果


内存使用

我第二在意的就是在框架运行时候内存的占用量。

如何运行

第一步 开始内存占用(单纯的启动进程)

第二步 测试我服务器上峰值内存占用

wrk -d 1m -t 4 -c 10

第三步 用下面的方法第二次测试内存占用

wrk -d 1m -t 8 -c 100

怎么运行的

这个测试在一个干净的 Mac mini 专用测试服务器上运行。反映了每个框架在 release 模式可能存在的状况。同一时间只有一个框架在命令行中运行并且会在下一次测试前重启。在测试期间唯一打开的窗口是活动监视器,我用它来可视化内存占用。在每个框架运行的时候,我只是简单的指出峰值出现在活动监视器中的时候。

内存占用结果


线程使用

我第三看重的事情是每个框架在负载下的线程使用情况

如何运行

第一步 开始内存占用(单纯的启动进程)

第二部 在我的测试服务器上用下面的命令来产生线程使用:

wrk -d 1m -t 4 -c 10

怎么运行的

这是一个用干净的 Mac mini 来搭建的专用测试服务器,每个框架都尽可能的在 release 模式下执行的。同一时间只有一个框架在命令行中运行并且会在下一次测试前重启。在测试期间唯一打开的窗口是活动监视器,我用它来可视化内存占用。在每个框架运行的时候,我只是简单的指出峰值出现在活动监视器中的时候。

对于这些结果的说明

这里没有「胜出」这一类。许多不同的应用程度对于线程的管理方式不同,并且这些框架也不例外。例如 Zewo 就是一个单线程应用程序,他永远不会使用大于一个线程(如果你没有主动在每一个 CPU 上运行的话)。而 Perfect 则会使用每一个可用的 CPU,Vapor 则是为每个线程模型使用一个 CPU。因此该图的目的是使线程负载峰值更容易看到。

线程使用结果


博客测试

第一个基准测试是处理 /blog 的路由,这是一个为每个请求返回 5 个随机图片的假博客文章接口。

如何运行

wrk -d 10m -t 4 -c 20 http://169.254.237.101:(PORT)/blog

从我的 rMBP 上用 Thunderbolt 桥接运行每个博客。

怎么运行的

在内存测试中,每个框架都在 release 模式运行,每次测试之前都会被重新启动。同一时间只有一个框架会被运行在服务器上。所有的活动都保持在最小的改变以保证环境尽可能相似。

结果

这张图片在 2016 年 9 月 1 日得到更新

这张图片在 2016 年 9 月 1 日得到更新


JSON 测试

由于每个人对于静态文件的处理方法都各有风格,所以看上去更加公平的方式是使用简单的接口来进行相同的测试,所以我增加了 /json 路由来测试每个应用从沙盒内返回 0~1000 之间的随机数。这个测试是单独进行的,以保证静态文件处理程序和中间件不会影响到接结果。

如何运行

wrk -d 10m -t 4 -c 20 http://169.254.237.101:(PORT)/json

对每个 JSON 项目都运行

怎么运行的

在其他测试中,每个框架都在 release 模式运行,每次测试之前都会被重新启动。同一时间只有一个框架会被运行在服务器上。所有的活动都保持在最小的改变以保证环境尽可能相似。

Results

这张图片在 2016 年 9 月 1 日得到更新

这张图片在 2016 年 9 月 1 日得到更新

结论

我的问题得到的回答是压倒性的 。Swift 能做的不仅能作为服务端框架使用,并且所有的 Swift 服务端框架性能都表现得令人难以置信的好,而 Node.js 在每个测试中都排在最后两名。

由于服务端 Swift 框架可以和其它 Swift 应用共享基本代码库,所以它可以为你节省大量的时间。而从这里的结果可以看出,服务端 Swift 框架在编程领域是非常强有力的竞争者。我个人会在编程中(特别是在服务端)尽可能的使用 Swift。我也迫不及待地想看到社区涌现出更多令人感到惊奇的项目。

参与其中

如果你对服务端 Swift 感兴趣,现在是时候参与其中了!这些框架还有大量的工作需要完成,比如说他们的文档。并且有一些非常炫酷的应用程序作为示例(有开源也有闭源)。你可以在这里了解更多信息:

保持联系

如果你有任何问题,可以在 Twitter 上和我取得联系 @rymcol

需要额外说明的信息:这段内容增加于 2016 年 9 月 1 日,为 Zewo 使用 swift build -c release 方法构建而优化并修正了一些数据。PerfectlySoft 公司提供的经费为我进行这项研究提供了动力。我同时也在 Github 上 Perfect & Vapor 的团队中,我不是其中任何一个的雇员,我的意见也不代表他们的观点。我尽力保持绝对的公平公正,因为我同时在所有的四个平台上开发,我是真的想看到结果 用于研究的所有代码都是公开,你可以随时检查测试方式或者自己重复一些测试。





原文发布时间为:2016年09月28日

本文来自云栖社区合作伙伴掘金,了解相关信息可以关注掘金网站。
目录
相关文章
|
20天前
|
Web App开发 JavaScript 前端开发
深入浅出Node.js后端框架
【10月更文挑战第34天】在数字化时代,后端开发如同一座桥梁,连接着用户界面与数据处理的两端。本文将通过Node.js这一轻量级、高效的平台,带领读者领略后端框架的魅力。我们将从基础概念出发,逐步深入到实战应用,最后探讨如何通过代码示例来巩固学习成果,使读者能够在理论与实践之间架起自己的桥梁。
|
2月前
|
JavaScript 前端开发 中间件
探索后端技术:Node.js与Express框架的完美融合
【10月更文挑战第7天】 在当今数字化时代,Web应用已成为日常生活不可或缺的一部分。本文将深入探讨后端技术的两大重要角色——Node.js和Express框架,分析它们如何通过其独特的特性和优势,为现代Web开发提供强大支持。我们将从Node.js的非阻塞I/O和事件驱动机制,到Express框架的简洁路由和中间件特性,全面解析它们的工作原理及应用场景。此外,本文还将分享一些实际开发中的小技巧,帮助你更有效地利用这些技术构建高效、可扩展的Web应用。无论你是刚入门的新手,还是经验丰富的开发者,相信这篇文章都能为你带来新的启发和思考。
|
10天前
|
缓存 负载均衡 JavaScript
构建高效后端服务:Node.js与Express框架实践
在数字化时代的浪潮中,后端服务的重要性不言而喻。本文将通过深入浅出的方式介绍如何利用Node.js及其强大的Express框架来搭建一个高效的后端服务。我们将从零开始,逐步深入,不仅涉及基础的代码编写,更会探讨如何优化性能和处理高并发场景。无论你是后端新手还是希望提高现有技能的开发者,这篇文章都将为你提供宝贵的知识和启示。
|
24天前
|
JavaScript 前端开发 中间件
JS服务端技术—Node.js知识点
本文介绍了Node.js中的几个重要模块,包括NPM、Buffer、fs模块、path模块、express模块、http模块以及mysql模块。每部分不仅提供了基础概念,还推荐了相关博文供深入学习。特别强调了express模块的使用,包括响应相关函数、中间件、Router和请求体数据解析等内容。文章还讨论了静态资源无法访问的问题及其解决方案,并总结了一些通用设置。适合Node.js初学者参考学习。
33 1
|
27天前
|
JavaScript 中间件 API
Node.js进阶:Koa框架下的RESTful API设计与实现
【10月更文挑战第28天】本文介绍了如何在Koa框架下设计与实现RESTful API。首先概述了Koa框架的特点,接着讲解了RESTful API的设计原则,包括无状态和统一接口。最后,通过一个简单的博客系统示例,详细展示了如何使用Koa和koa-router实现常见的CRUD操作,包括获取、创建、更新和删除文章。
39 4
|
29天前
|
开发框架 JavaScript 前端开发
Node.js日记:客户端和服务端介绍、Node.js介绍
Node.js日记:客户端和服务端介绍、Node.js介绍
|
2月前
|
Web App开发 JavaScript 中间件
构建高效后端服务:Node.js与Express框架的完美结合
【10月更文挑战第21天】本文将引导你走进Node.js和Express框架的世界,探索它们如何共同打造一个高效、可扩展的后端服务。通过深入浅出的解释和实际代码示例,我们将一起理解这一组合的魅力所在,并学习如何利用它们来构建现代Web应用。
52 1
|
22天前
|
Web App开发 JavaScript 前端开发
构建高效后端服务:Node.js与Express框架的实践
【10月更文挑战第33天】在数字化时代的浪潮中,后端服务的效率和可靠性成为企业竞争的关键。本文将深入探讨如何利用Node.js和Express框架构建高效且易于维护的后端服务。通过实践案例和代码示例,我们将揭示这一组合如何简化开发流程、优化性能,并提升用户体验。无论你是初学者还是有经验的开发者,这篇文章都将为你提供宝贵的见解和实用技巧。
|
23天前
|
Web App开发 JavaScript 中间件
构建高效后端服务:Node.js与Express框架的融合之道
【10月更文挑战第31天】在追求快速、灵活和高效的后端开发领域,Node.js与Express框架的结合如同咖啡遇见了奶油——完美融合。本文将带你探索这一组合如何让后端服务搭建变得既轻松又充满乐趣,同时确保你的应用能够以光速运行。
27 0
|
3月前
|
JavaScript
NodeJs的安装
文章介绍了Node.js的安装步骤和如何创建第一个Node.js应用。包括从官网下载安装包、安装过程、验证安装是否成功,以及使用Node.js监听端口构建简单服务器的示例代码。
NodeJs的安装