JS 时间格式化 api 的性能问题

哪种时间格式化 API 的性能最好,原生 API 性能一定好于第三方库吗

发现问题

在项目中有一个需求,需要绘制 CPU 占用和时间关系的 line chart ,数据量在几万到几十万级别。由于后台返回的是时间戳,需要在前端进行格式化。在前端进行时间格式化,下面几种都是常用的 API :

// 使用 moment 第三方库
moment(new Date()).format("hh::mm");
// 使用 getHours + getMinutes
let now = new Date();
[now.getHours(), now.getMinutes()].join(":");
// 使用 toLocaleString
new Date().toLocaleString('zh-CN', {
	hour: "numeric",
	minute: "numeric",
	hour12: false
});
// 使用 Intl.DateTimeFormat
Intl.DateTimeFormat('zh-CN', {
	hour: "numeric",
	minute: "numeric",
	hour12: false
}).format(new Date());

本人在查阅 MDN 文档对 toLocaleTimeString 介绍的时候看到,Intl.DateTimeFormat API 的性能较好,因此项目中使用 Intl.DateTimeFormat 进行格式化。
请添加图片描述
在实际测试的时候,line chart 渲染出现较长时间(5 秒以上)卡顿的情况,还阻塞了同一页面上 pie chart 的渲染(这没多少数据,原本应该很快的)。

在对比同事使用 moment 格式化的 line chart 时,同事的数据量没有本人的大,但是可以明显感觉到性能要好。因此本人也改用了 moment 进行尝试,结果性能提升明显。

对比测试

事后本人对 API 的性能感到非常好奇,moment 究竟比 Intl.DateTimeFormat 快多少。因此本人把常用的 API 都进行了测试,代码如下:

const moment = require("moment");

let base = +new Date(1968, 9, 3);
let oneDay = 24 * 3600 * 1000;

console.time("moment");
for (let i = 1; i < 20000; i++) {
  let now = new Date(base += oneDay);
  moment(now).format("hh:mm");
}
console.timeEnd("moment");

console.time("getHours and getMinutes");
for (let i = 1; i < 20000; i++) {
  let now = new Date(base += oneDay);
  [now.getHours(), now.getMinutes()].join(":");
}
console.timeEnd("getHours and getMinutes");

console.time("Date.prototype.toLocaleString");
for (let i = 1; i < 20000; i++) {
  let now = new Date(base += oneDay);
  now.toLocaleString('zh-CN', {
    hour: "numeric",
    minute: "numeric",
    hour12: false
  })
}
console.timeEnd("Date.prototype.toLocaleString");

console.time("Intl.DateTimeFormat");
for (let i = 1; i < 20000; i++) {
  let now = new Date(base += oneDay);
  Intl.DateTimeFormat('zh-CN', {
    hour: "numeric",
    minute: "numeric",
    hour12: false
  }).format(now);
}
console.timeEnd("Intl.DateTimeFormat");

大家也可以复制上面的代码自己跑一下,需要安装 moment 依赖。

本人这边给大家公布一下结果:
请添加图片描述
结果有点出乎意料,格式化两万个时间,moment 仅仅耗时 77.15ms ,但是 Intl.DateTimeFormat 却花了 3.574s ,性能差距近 50 倍。还有一个 Date.prototype.toLocaleString 更夸张了,花了 3.863s ,反倒是 getHoursgetMinutes 性能最好,只需要 12.141ms ,相比 Intl.DateTimeFormat 性能提升近 300 倍。

那么格式化 20 万个时间性能如何呢?
请添加图片描述
从结果上看,moment 以及 getHoursgetMinutes 性能依旧出色,循环次数增加 10 倍,耗时大约只增加了 5 倍,时间复杂度约为 O(logn)Date.prototype.toLocaleString 耗时 37.536s ,可以看出时间成线性增长,时间复杂度 O(n) 。而 Intl.DateTimeFormat 有点夸张,不仅比 Date.prototype.toLocaleString 更慢了,而且花了 40.308s ,远高于线性的 35.74s ,时间复杂度高于 O(n)

总结

  1. 原生 API 性能不一定比第三方库好;
  2. 在格式化大量时间时推荐使用 moment 或者 getHoursgetMinutes ,不要使用 Date.prototype.toLocaleStringIntl.DateTimeFormat ,不仅性能很烂,配置项也很难用;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值