60亿次for循环,原来这么多东西


60亿次for循环,原来这么多东西

文章插图
 
作者: Peter 谭老师
转发链接:https://mp.weixin.qq.com/s/Vs8CwdGJ6JUyH_Kp0H5l4Q
起因
  • 有人在思否论坛上向我付费提问
 
60亿次for循环,原来这么多东西

文章插图
 
  • 当时觉得 , 这个人问的有问题吧 。仔细一看 , 还是有点东西的
问题重现
  • 编写一段Node.js代码
var http = require('http');  http.createServer(function (request, response) {    var num = 0    for (var i = 1; i < 5900000000; i++) {        num += i    }    response.end('Hello' + num);}).listen(8888);
  • 使用nodemon启动服务,用time curl调用这个接口

60亿次for循环,原来这么多东西

文章插图
 
  • 首次需要7.xxs耗时
  • 多次调用后 , 问题重现

60亿次for循环,原来这么多东西

文章插图
 
  • 为什么这个耗时突然变高 , 由于我是调用的是本机服务 , 我看CPU使用当时很高 , 差不多达到100%了.但是我后面发现不是这个问题.
问题排查
  • 排除掉CPU问题 , 看内存消耗占用 。
var http = require('http');http  .createServer(function(request, response) {    console.log(request.url, 'url');    let used = process.memoryUsage().heapUsed / 1024 / 1024;    console.log(      `The script uses Approximately ${Math.round(used * 100) / 100} MB`,      'start',    );    console.time('测试');    let num = 0;    for (let i = 1; i < 5900000000; i++) {      num += i;    }    console.timeEnd('测试');    used = process.memoryUsage().heapUsed / 1024 / 1024;    console.log(      `The script uses approximately ${Math.round(used * 100) / 100} MB`,      'end',    );    response.end('Hello' + num);![](https://imgkr2.cn-bj.ufileos.com/13455121-9d87-42c3-a32e-ea999a2cd09b.png?UCloudPublicKey=TOKEN_8d8b72be-579a-4e83-bfd0-5f6ce1546f13&Signature=E3cF2kymC92LifrIC5IOfIZQvnk%253D&Expires=1598883364)![](https://imgkr2.cn-bj.ufileos.com/1e7b95df-2a48-41c3-827c-3c24b39f4b5b.png?UCloudPublicKey=TOKEN_8d8b72be-579a-4e83-bfd0-5f6ce1546f13&Signature=%252FANTTuhgbpIsXslXMc1qCkj2TMU%253D&Expires=1598883362)  })  .listen(8888);
  • 测试结果:
  • 内存占用和CPU都正常
  • 跟字符串拼接有关 , 此刻关闭字符串拼接(此时为了快速测试 , 我把循环次数降到5.9亿次)

60亿次for循环,原来这么多东西

文章插图
 
  • 发现耗时稳定下来了
定位问题在字符串拼接 , 先看看字符串拼接的几种方式
  • 一、使用连接符 “+” 把要连接的字符串连起来
var a = 'JAVA'var b = a + 'script'* 只连接100个以下的字符串建议用这种方法最方便
  • 二、使用数组的 join 方法连接字符串
var arr = ['hello','java','script']var str = arr.join("")
  • 比第一种消耗更少的资源 , 速度也更快
  • 三、使用模板字符串 , 以反引号( ` )标识
var a = 'java'var b = `hello ${a}script`
  • 四、使用 JavaScript concat() 方法连接字符串
var a = 'java'var b = 'script'var str = a.concat(b)五、使用对象属性来连接字符串function StringConnect(){    this.arr = new Array()}StringConnect.prototype.append = function(str) {    this.arr.push(str)}StringConnect.prototype.toString = function() {    return this.arr.join("")}var mystr = new StringConnect()mystr.append("abc")mystr.append("def")mystr.append("g")var str = mystr.toString()


推荐阅读