当前位置: 首页 > news >正文

每日 30 秒 ⏱ 谁敢与我一战

简介

benchmark、基准测试、jsPerf

在 优雅插入数组 一文中大家最多的评论就是 “能不能加个基准测试”。小二不是不喜欢加基准测试而是现在硬件设备的性能越来越快了,有时候一些操作不是性能问题的主要原因,当然这不是我们不写出好代码的理由。

书写代码还是应该在 优雅易读运行性能中做出平衡,适合的场景做适合的事情。不过既然大家都提到了 基准测试 碰巧我又刚好没有想到要写什么那就一起了解一下 基准测试 吧。

人非圣贤孰能无过,三两八哥常伴吾身。-- 嗯是我

测试 在中大型和和开源项目中算是 必备内容,好测试可以在假定的场景下找到项目的错误帮助我们写出质量更好的代码,也是协作开发中的调和剂。测试 是一门开发中的大学问不是一篇文章就能讲得明白的。

Talk is cheap, Show me the code. -- Linus Torvalds

本文选择的 基准测试 只是 测试 中一个小分支,本文简单帮助大家涉猎一些简单的概念和测试工具。学习后当遇到野生程序猿说出骚话:“废话少说,放马过来”,请抄起键盘打开 基准测试 工具大喊:“吾乃燕人张翼德,谁敢与我一战?”

抛硬币

抛一次硬币就得到 出现正面概率是百分百 的结论显然是错误的,数学老师教过我们 大数定律:“需要数据量足够多、样本足够打才能下结论”。当抛均匀硬币次数足够多时出现正面概率应该无限趋近于百分五十,对照抛硬币实验 基准测试 一样不能只记录一次代码运行时间就可以得出结果的,需要进行足够多的次数。

吓螃蟹

科学家从笼子里抓出一只螃蟹,放在地上,冲着它大吼大叫,螃蟹被吓得不轻,到处乱窜,慌不择路。然后科学家把螃蟹的腿拆卸下来重复之前的步骤,继续大吼大叫,螃蟹一动不动,非常的淡定从容,得到结论螃蟹的耳朵是长在腿上的

这个小笑话大家应该都听过,没有考虑螃蟹逃跑是需要用腿。在做生物对照实验时出现的三个概念 自变量因变量无关变量,控制好它们从而得到真实的结果。基准测试的影响变量可以是手机进入省电模式带来的运行速度降低,可以是电脑正在运行无关软件导致某一时刻测试环境不一致,也是可以是代码初始状态的不一致例子如下:

// 代码一
let a = [1, 2, 3, 4];
a.push(5);

// 代码二
let b = [1, 2, 3, 4, 5, 6, 7, 8];
b = [...b, 9];
复制代码

测试上面两个代码并不能得出谁的性能更好,因为初始数组的长度不一样存在数组越大操作越慢的情况。

Benchmark

上面简单两个例子帮助理解 基准测试 的一些基本要点。在开发中除了利用浏览器的特性来调优代码,有时候不同的代码写法也会带来不一样的性能表现。在 优雅插入数组 中把数据插入数组尾部就介绍了四种不一样的方法,利用哪一种写法会使得代码 优雅、易懂、跑得快呢,可以使用 Benchmark 来帮助测试得到结论。

安装

npm i --save benchmark
复制代码

使用

  • add 接口添加测试代码。
  • on 接口插入代码到测试周期中。
  • run 运行代码。

例子

代码
let suite = new Benchmark.Suite;

suite
    .add('#1 利用数组长度进行赋值', () => {
        let arr = [1, 2, 3, 4, 5];
        arr[arr.length] = 6;
    })
    .add('#2 利用 Array.prototype.push 方法', () => {
        let arr = [1, 2, 3, 4, 5];
        arr.push(6);
    })
    .add('#3 利用 Array.prototype.concat 方法', () => {
        let arr = [1, 2, 3, 4, 5];
        arr = arr.concat(6);
    })
    .add('#4 利用 spread 运算符', () => {
        let arr = [1, 2, 3, 4, 5];
        arr = [...arr, 6];
    })
    .on('start', (event) => {
        // 在整个测试运行前
        console.log('把数据插入数组尾部');
    })
    .on('cycle', (event) => {
        // 每个测试代码运行后
        console.log(String(event.target));
    }).on('complete', () => {
        // 测试完成后
        console.log('最快方法是 ' + suite.filter('fastest').map('name'));
    }).run({ 'async': true })
复制代码
输出
#1 利用数组长度进行赋值 x 3,590,121 ops/sec ±0.97% (87 runs sampled)
#2 利用 Array.prototype.push 方法 x 15,796,478 ops/sec ±0.61% (88 runs sampled)
#3 利用 Array.prototype.concat 方法 x 2,373,044 ops/sec ±1.00% (83 runs sampled)
#4 利用 spread 运算符 x 2,405,217 ops/sec ±0.72% (91 runs sampled)
最快方法是 #2 利用 Array.prototype.push 方法
复制代码

jsPerf

A benchmarking library. As used on jsPerf.com.

在 Benchmark 仓库中的项目简介中提到了 jsPerf 一个基于 Benchmark 的便捷基准测试站点。使用 Github 登录后,按照创建表格中的数据填写就能生成基准测试

基准测试 例子 在 jsPerf 中链接为 数据插入数组尾部,利用 jsPerf 可以很方便的进行分享(就像现在),还可以在不同浏览器中打开测试。下面对页面名称进行简单翻译方便英语不好的同学使用:

个人信息

名词解释
Your details个人信息,可选填
Name作者名字
Email作者邮箱,由于生成头像
URL项目地址

案例信息

名词解释
Test case details案例信息
Title标题
Slug网站 slug,会被拼接成 jsperf.com/slug
Description项目描述

预加载

名词解释
Preparation code预加载
Preparation code HTML项目需要的 DOM 结构 和 引入外部脚本
Define setup for all tests每次测试前将会执行的操作即 Benchmark.setup 中的配置,例如初始化变量。
Define teardown for all tests每次测试后会执行的操作即 Benchmark.teardown 中的配置,例如清除变量。

需要比较的代码段

如果有不需要的测试代码框只需要放空内容并保存就会自己删除。

名词解释
Code snippets to compare需要比较的代码段
Title测试代码段标题
Async代码段是否异步
Code需要测试的代码
Add code snippet添加测试代码
Save test case保存

测试页面

名词解释
Run test运行测试
Testing in ...测试所在的浏览器及其版本、操作系统及其版本
Ops/sec每秒钟代码执行次数,数值越大越好
You can edit these tests or add even more tests to this page by appending /edit to the URL.点击该链接可以修改测试代码,但是 slug 这些是改不了的
Compare results of other browsers所有浏览器测试结果
Chart type数据展示方式:条形图、折线图、饼图、表格
Filter浏览器环境

结尾

还不赶紧带上键盘与野生程序员大战三百回合,打满经验升级飞仙成为上古程序员。

一起成长

在困惑的城市里总少不了并肩同行的 伙伴 让我们一起成长。

  • 如果您想让更多人看到文章可以点个 点赞
  • 如果您想激励小二可以到 Github 给个 小星星
  • 如果您想与小二更多交流添加微信 m353839115

本文原稿来自 PushMeTop

转载于:https://juejin.im/post/5c9695bfe51d45457e6561f0

相关文章:

  • 用Python爬取王者农药英雄皮肤
  • 杂记:Python 两坑
  • Sass预处理器常用功能(OneLine周分享)
  • Java程序设计第一次作业
  • mysql 原理 ~ 线程与IO
  • 牛客挑战赛30 简要题解
  • 【复习笔记】---java基础
  • 运维工作钱少、事多而且杂?年轻人,你这个思想很危险吶
  • centos7下关闭sshd的tcp6
  • Media Queries实现屏幕适配
  • SkyWalking Liunx 环境搭建NetCore接入
  • 死磕 java集合之HashMap源码分析
  • CocoaPods使用小结
  • js 中异步处理
  • 92. Reverse Linked List II 反转链表 II
  • Google 是如何开发 Web 框架的
  • 【划重点】MySQL技术内幕:InnoDB存储引擎
  • 4月23日世界读书日 网络营销论坛推荐《正在爆发的营销革命》
  • dva中组件的懒加载
  • EOS是什么
  • Java,console输出实时的转向GUI textbox
  • Joomla 2.x, 3.x useful code cheatsheet
  • jquery ajax学习笔记
  • laravel5.5 视图共享数据
  • Travix是如何部署应用程序到Kubernetes上的
  • 安卓应用性能调试和优化经验分享
  • 从零到一:用Phaser.js写意地开发小游戏(Chapter 3 - 加载游戏资源)
  • 简单实现一个textarea自适应高度
  • 理解IaaS, PaaS, SaaS等云模型 (Cloud Models)
  • 聊聊springcloud的EurekaClientAutoConfiguration
  • 使用阿里云发布分布式网站,开发时候应该注意什么?
  • 微信开源mars源码分析1—上层samples分析
  • 一道闭包题引发的思考
  • 译米田引理
  • 中文输入法与React文本输入框的问题与解决方案
  • MPAndroidChart 教程:Y轴 YAxis
  • (11)MSP430F5529 定时器B
  • (2)MFC+openGL单文档框架glFrame
  • (MonoGame从入门到放弃-1) MonoGame环境搭建
  • (第61天)多租户架构(CDB/PDB)
  • (附源码)springboot 基于HTML5的个人网页的网站设计与实现 毕业设计 031623
  • (转)C#开发微信门户及应用(1)--开始使用微信接口
  • (转)Unity3DUnity3D在android下调试
  • .NET / MSBuild 扩展编译时什么时候用 BeforeTargets / AfterTargets 什么时候用 DependsOnTargets?
  • .NET LINQ 通常分 Syntax Query 和Syntax Method
  • .net 前台table如何加一列下拉框_如何用Word编辑参考文献
  • .vimrc php,修改home目录下的.vimrc文件,vim配置php高亮显示
  • /usr/local/nginx/logs/nginx.pid failed (2: No such file or directory)
  • [HarekazeCTF2019]encode_and_encode 不会编程的崽
  • [LeetCode] 178. 分数排名
  • [ListView.View=List]的垂直滚动条
  • [nlp] id2str的vocab.json转换为str2id
  • [node] Node.js的Web 模块
  • [Oh My C++ Diary]operator++()和operator++(int)的区别
  • [POI2007] ZAP-Queries (莫比乌斯反演)