Node.js框架fastify为什么这么快(nodejs的fs的方法)

boyanx5个月前技术教程27

fastify是目前Node.js web框架中最快的,为什么会这么快?今天就带大家看看fastify中优化性能的技术点.


路由

fastify中路由底层是 find-my-way 库, find-my-way是基于Radix Tree(Prefix Tree)数据结构,RadixTree在储存具有大多相同前缀的字符串查找效率很高.而大多web框架都是使用字典(map)的数据结构.在路由不是很多情况下两者的效率相差不大,但是随着路由的增多,特别是相同前缀的路由增多,效率就相差起来了.

 └── /
   ├── test (GET)
   │   └── /hello (GET)
   └── hello/world (GET)

Radix Tree

└── /
   ├── test (GET)
	 ├── test/hello (GET)
   └── hello/world (GET)

Map

fast-json-stirngify

fastify在json序列化操作使用了fast-json-stringify库,fast-json-stringify使用JSONSchema描述了序列化的对象的数据类型,遍历对象使用字符串拼接来构建json数据,后使用flatstr这个hack操作使v8底层的树形字符串扁平化在转化为Buffer中提高效率.在实际测试中,在数据量很小的情况下可以比JSON.stringify提高2倍性能,极端的时候能提高10倍.这种性能优势会随着数据量增大而缩小.

官方测试结果:

FJS creation x 8,951 ops/sec ±0.51% (92 runs sampled)

JSON.stringify array x 5,146 ops/sec ±0.32% (97 runs sampled)
fast-json-stringify array x 8,402 ops/sec ±0.62% (95 runs sampled)
fast-json-stringify-uglified array x 8,474 ops/sec ±0.49% (93 runs sampled)

JSON.stringify long string x 13,061 ops/sec ±0.25% (98 runs sampled)
fast-json-stringify long string x 13,059 ops/sec ±0.21% (98 runs sampled)
fast-json-stringify-uglified long string x 13,099 ops/sec ±0.14% (98 runs sampled)

JSON.stringify short string x 6,295,988 ops/sec ±0.28% (98 runs sampled)
fast-json-stringify short string x 43,335,575 ops/sec ±1.24% (86 runs sampled)
fast-json-stringify-uglified short string x 40,042,871 ops/sec ±1.38% (93 runs sampled)

JSON.stringify obj x 2,557,026 ops/sec ±0.20% (97 runs sampled)
fast-json-stringify obj x 9,001,890 ops/sec ±0.48% (90 runs sampled)
fast-json-stringify-uglified obj x 9,073,607 ops/sec ±0.41% (94 runs sampled) 

装饰器

我们在express中,在扩展框架功能是,都是通过中间件给请求上下文(req, res)添加一个属性/方法,这样每次请求都会改变res,res的结构,v8底层不能优化为hidden class.而fastify中使用了decorate* api扩展请求上下文时直接把扩展添加到请求上下文的构造函数的prototype中.从而使v8更好优化.

源码:

function decorateReply (name, fn, dependencies) {
  decorate(this[kReply].prototype, name, fn, dependencies)
  return this
}

function decorateRequest (name, fn, dependencies) {
  assertNotStarted(this, name)
  decorate(this[kRequest].prototype, name, fn, dependencies)
  return this
}
function decorate (instance, name, fn, dependencies) {
  if (instance.hasOwnProperty(name)) {
    throw new FST_ERR_DEC_ALREADY_PRESENT(name)
  }

  if (dependencies) {
    checkDependencies(instance, dependencies)
  }

  if (fn && (typeof fn.getter === 'function' || typeof fn.setter === 'function')) {
    Object.defineProperty(instance, name, {
      get: fn.getter,
      set: fn.setter
    })
  } else {
    instance[name] = fn
  }
}

对象池化(复用)

在fastify中间件处理上,使用middie库,其使用了reusify库做对象复用.在每次新请求进来,会创建请求上下文对象(req,res),循环调用每个中间件,执行中间件时会包装一个包含req,res,url,context的对象,在请求量很大的时候,就要频繁的创建回收.使用了对象池化可以把这个对象使用以后进行属性清空,丢回池中.下次请求可以复用.

缓存

在fastify请求主体解析上(ContentTypeParser),使用了tiny-lru库,fastify内置了application/json和text/plain解析方法,但是在判断Content-Type消息头上不能是等于(===),比如
Content-type:application/json;charset=utf8头,需要正确解析需要使用是否包含(indexOf),但是每次判断都有消耗,fastify使用lru算法把相同的content-type头都缓存起来,下次请求直接定位ContentTypeParser处理器.典型的空间换时间.

总结

fastify能做到Node.js web框架最快,就是作者这种锱珠必较.很多性能优化的技巧也值得我们学习.

标签: tree.js

相关文章

SpriteJS:图形库造轮子的那些事儿

从 2017 年到 2020 年,我花了大约 4 年的时间,从零到一,实现了一个可切换 WebGL 和 Canvas2D 渲染的,跨平台支持浏览器、SSR、小程序,基于 DOM 结构和支持响应式的,高...

初识three.js,搭建three.js+vue.js项目

作者:前端藏经阁转发链接:https://www.yuque.com/xwifrr/uxqg5v/ggxx2bWebGL简介:WebGL(全写Web Graphics Library)是一种3D绘图协...

Bun:一体化的 JavaScript 运行时(javascript可不可以单独运行)

Bun 是一个功能丰富的 JavaScript 运行时,它自带包管理功能,还具有工程常用的打包、测试等功能。Bun 使用 Zig 编程语言开发,基于 Safari 浏览器的 JavaScriptCor...

一次性搞定JS的DOM操作(js中dom)

一.什么是DOM我们知道,无论是现在的开发框架(底层还是操作DOM)还是传统的开发都离不开DOM的操作,所以了解和学习DOM是必须的,也是成为一个全面的前端开发的必备知识和内容,那接下来我们就来看下什...

来了!JavaScript 最强大的 8 个 DOM API

作为前端开发者,我们每天都在操作 DOM,但 DOM API 中隐藏着许多鲜为人知却极其实用的方法。本文将介绍一些「冷门但能显著提升开发效率」的DOM操作技巧。1. Element.checkVisi...

是时候抛弃 chokidar 了?Node.js 原生支持 HMR 热更新!

大家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!1. 为什么需要模块热加载提高开发效率的关...

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。