大厂总爱问性能优化? 是时候学习有什么js性能优化点了

94 阅读3分钟

一:网络服务(优化前置原理)

1. http 与 TCP

  1. 区别:http是应用层网络协议,TCP是传输层的协议
  2. 关联:http基于TCP实现连接。http发起连接的时候依赖TCP建立通道
    • 优化点:1.0 1.1 2.0
      • 1.1添加keep-alive - 保持TCP的连续畅通 - 不用反复地建立连接(2.0没有)
      • 2.0多条并发请求复用同一条通路 - 复用通路 无并发限制
    • UDP vs TCP
      • UDP面向连接传输(不确认是否收到) TCP面向连接确认
      • UPD性能快, TCP准确性高
  3. 差异:http是无状态连接, TCP是有状态的
    • 优化点: socket连接,封装华的TCP。 让我们的应用更加方便地使用调用
http 和 https
  1. https = http + SSL(TLS) => 位于TCP协议与各种应用层协议之间
  2. 实现原理:

image.png

  1. HTTPS多次连接:导致网络请求加载时间延长: 增加开销和功耗
    • 优化:
    • 合并请求 长链接

2. 域名解析

流程 url => ip
  1. 浏览器缓存中 - 查找域名对应的ip 浏览器中会缓存DNS一段时间
  2. 系统缓存 - 系统中找缓存 => HOST: 修改域名对应的ip的映射
  3. 路由器缓存 - 每个层级路由器缓存的域名信息
  4. 运营商地方站点的缓存信息
  5. 根域名服务器
    • 优化:
    • CDN:(面试方向:缓存)
        1. 为同一个主机配置多个IP地址
        1. LB - 负载均衡 根据IP机器负载量,引导请求到地理位置上最近的IP机器上

3. web服务器

apache、ngnix

    1. 接收请求 => 传递给服务端代码
    1. 通过反向代理 => 传递给其他服务器
    1. 不同域名 => 指向相同ip的服务器 => ngnix域名解析 => 引导到不同的服务监听端口

二:服务涉及到的网络优化

手写并发 -QPS

    // 场景:有十个请求 由于后台或者业务需求只能同时执行三个,最快执行完的同时三个三个去请求
    // 分析:
    // 输入: promise数组、limit参数
    // 存储:requirePool - 并发池
    // 思路: 塞入 + 执行
    function qpsLimit (requestPipe, limitMax = 3){
        let reqpool = [];
        
        // 往并发池里塞入promise
        const add = () => {
            let _req = requestPipe.shift();
            reqpool.push(_req);
        }
        
        // 执行实际请求
        const run = () => {
            if(requestPipe.length === 0) return;
            // 池子满了发车后 直接race
            let _finish = Promise.race(reqPool);
            _finish.then(res => {
                let _done = reqPool.indexOf(_finish);
                reqPool.splice(_done, 1);
                add();
            })
            run();
        }
        
        while(reqPool.length < limitMax){
            add();
        }
        run();
    }

三: 浏览器在渲染时

浏览器执行顺序:

主线:URL => HTML解析 - JS + DOM + CSSOM => render tree / JS + css执行 => layout module => painting

支线:

  1. repaint - 改变文本、颜色等 (无需计算)
  2. reflow - 元素集合尺寸变了 (时间性能成本高)

优化点: 减少repaint,避免reflow

  • display: none => reflow; visiblity: hideen => repaint

四: 脚本执行时 - JS

mark & sweep => 触达标记、锁定清空、未触达直接抹掉

内存泄露
  1. 莫名其妙的全局变量
    function foo(){
        bar1 = '';
        this.bar2 = '';
    }
    // 二者都是挂载到window
  1. 未清理的定时器以及监听事件
  2. 使用后的闭包

打包配置优化

  1. 懒加载 - 非必要不加载
  2. 按需引入 - 非必要不引入
  3. 抽离公共 - 相同项目合并公用