天天看点

前端面试题:如何做性能优化?

作者:科技树乱点
前端面试题:如何做性能优化?

#头条创作挑战赛#

前端面试最常见但是也最不好回答的一个问题:如何做性能优化?

为什么?

题目问得很宽泛:性能+优化(具体什么性能?渲染展示、加载、服务器响应?优化的手段和方式很多,开发的全链路和各个阶段都可以涉及)。

因此,这个问题既能考察出面试者的技术广度,也可以考察出面试者的技术深度来。

那么本文将尝试尽可能宽泛和深入的来回答下这个问题。

性能优化要做什么?

首先,需要确定当前的业务场景和系统架构。

业务场景,例如电商详情页面、交易付款页面;面试视频页面;直播页面等等。

系统架构,例如手机app、移动站点、PC站点等等。

抽象来说,可以分成:

  • 客户端:手机App或者页面
  • 网络层:CDN、HTTP/HTTPS、RPC、网关服务等
  • 服务端:Java、Node.js、PHP等服务器
  • 数据层:Redis、MongoDB、MySql等

对客户端进行性能优化:

  • 原生应用
  • Hybrid应用
  • HTML页面

原生应用性能优化:

启动时间过长:

应用启动时间是用户体验的重要指标,如果启动时间过长,会让用户感觉应用响应较慢。优化建议:

  • 减少启动时的初始化工作,只加载必要的资源。
  • 使用冷启动和热启动时的差异,优先加载核心功能和界面。
  • 考虑使用启动画面来给用户一个即时的反馈。

卡顿和掉帧:

当应用界面出现卡顿或掉帧,用户会感到操作不流畅。优化建议:

  • 将耗时操作放到后台线程执行,避免主线程阻塞。
  • 使用硬件加速和动画优化来提高界面绘制性能。
  • 减少不必要的布局和绘制操作。

内存泄漏:

内存泄漏会导致应用占用过多内存,可能引起应用崩溃或被系统终止。优化建议:

  • 定期检查和释放不再使用的对象和资源。
  • 使用内存分析工具来定位内存泄漏问题。

过度绘制:

过度绘制是指在每一帧中进行多余的绘制操作,浪费了系统资源。优化建议:

  • 使用Hierarchy Viewer工具来检查视图层次结构,避免重叠绘制。
  • 优化布局和绘制操作,减少不必要的绘制。

网络性能问题:

网络请求过多或网络请求过慢会影响应用的性能和用户体验。优化建议:

  • 合并多个网络请求为一个,减少请求次数。
  • 使用缓存技术,减少重复的网络请求。
  • 使用GZIP等压缩技术来减小网络传输数据量。

电量消耗过高:

应用的电量消耗是用户关注的一个重点。优化建议:

  • 减少后台任务和定时任务的频率和耗时。
  • 使用Doze模式和应用待机来降低应用在后台的能耗。

资源浪费:

使用过多的资源会占用设备存储和带宽。优化建议:

  • 压缩图片和音频资源,减小应用安装包的大小。
  • 使用WebP格式代替PNG或JPEG格式的图片,可以减少图片大小。

Hybrid应用性能优化:

Hybrid应用是指同时使用Web技术(HTML、CSS、JavaScript等)和原生代码(通常是通过WebView或类似组件加载Web页面)开发的移动应用。性能优化对于Hybrid应用尤为重要,因为它们需要在Web视图和原生代码之间进行交互,同时需要处理两种不同的技术栈。以下是针对Hybrid应用的性能优化建议:

  1. 减少HTTP请求: Hybrid应用通常依赖于远程加载的Web资源,减少HTTP请求可以加快加载速度。将CSS和JavaScript文件进行合并和压缩,减小文件体积,同时使用缓存策略,减少重复请求。
  2. 优化Web视图性能: 在Web视图中,避免使用过多的动画效果和复杂的CSS样式,因为它们可能导致性能下降。使用硬件加速来提高动画性能,避免频繁的重绘和重排操作。
  3. 使用本地组件:在Hybrid应用中,尽量使用原生组件代替Web视图,因为原生组件通常比WebView更高效。例如,可以使用原生的滚动视图、列表视图等来替代Web中的滚动容器。
  4. 懒加载和预加载:对于Hybrid应用,可以使用懒加载和预加载技术来优化页面加载速度。懒加载是指延迟加载某些资源,直到用户需要访问它们,而预加载是指提前加载下一个页面的资源,以便在用户切换时能够更快地展示。
  5. 避免内存泄漏:在Hybrid应用中,特别需要注意内存泄漏问题。及时释放不再使用的JavaScript对象和原生组件引用,避免造成内存泄漏。
  6. 使用WebView缓存: 合理配置WebView的缓存策略,可以减少对远程资源的重复请求,提高页面加载速度。
  7. 优化JavaScript性能:JavaScript是Hybrid应用的核心,优化JavaScript性能非常重要。避免使用过多的全局变量,减少不必要的DOM操作,优化JavaScript的算法和循环,使用事件委托等技术来优化性能。
  8. 合理使用本地存储:Hybrid应用可以使用本地存储(如localStorage)来缓存数据,但要注意不要存储过多的数据,以免影响应用性能和设备存储空间。
  9. 利用WebView和原生通信:在WebView和原生代码之间建立高效的通信机制,避免频繁的数据传递和转换,提高应用的响应速度。
  10. 定期检查性能:对Hybrid应用进行性能测试和监测是保持应用性能的好方法。使用性能分析工具来检查性能瓶颈,并根据结果进行优化。

网络层优化:

  1. 减少网络请求次数: 尽量合并多个请求为一个,减少网络请求的次数。使用资源合并和压缩,将多个资源文件(如CSS、JavaScript)合并为一个,减少请求次数。
  2. 缓存策略: 合理设置缓存策略,对于不经常变化的资源,使用合适的缓存过期时间,避免重复的网络请求。对于需要经常更新的资源,可以使用版本号或时间戳来确保客户端获取到最新的资源。
  3. 使用CDN加速: 使用内容分发网络(CDN)可以将静态资源分布到全球多个服务器节点,加速资源的传输和加载速度。
  4. 异步加载: 使用异步加载来提高页面加载速度,尤其是对于非关键资源,可以在页面加载完成后再进行加载,而不会影响页面的渲染和交互。
  5. 压缩数据: 使用GZIP等压缩技术来减小网络传输的数据量,加快数据的传输速度。
  6. 避免重复请求: 在应用中,尽量避免重复请求相同的数据,可以通过缓存、本地存储或全局变量来避免重复请求。
  7. 优化网络请求: 合理设计网络请求,避免不必要的数据传输和处理。使用GET请求来获取数据,使用POST请求来提交数据。
  8. 使用HTTP/2协议: HTTP/2协议支持多路复用和头部压缩等功能,可以提高网络传输的效率。
  9. 处理超时和错误: 对网络请求进行超时设置和错误处理,避免长时间等待和无响应的情况。
  10. 分批加载: 对于大量数据的加载,可以使用分批加载的方式,逐步加载数据,而不是一次性加载所有数据。
  11. 移动端优化: 对于移动端应用,尽量减小数据量和请求次数,因为移动网络条件可能不稳定和较慢。
  12. 性能监控和分析: 使用性能监控工具来分析网络请求的性能指标,定位性能瓶颈,并根据结果进行优化。

服务端优化:

  1. 数据库优化: 合理设计数据库表结构和索引,优化复杂查询语句,使用数据库缓存技术,减少数据库访问次数和查询开销。
  2. 缓存技术: 使用缓存来存储常用的数据或计算结果,减少对数据库或外部接口的重复请求。可以使用内存缓存(如Redis、Memcached)或分布式缓存来提高性能。
  3. 异步处理: 将耗时的操作和后台任务放入消息队列或异步任务中处理,减少请求响应时间。
  4. 负载均衡: 使用负载均衡技术将请求分散到多个服务器上,确保每台服务器的负载均衡,提高系统的可扩展性和容错性。
  5. 并发处理: 使用多线程、多进程或异步处理来支持并发请求,充分利用多核处理器和资源,提高系统的吞吐量和并发能力。
  6. 数据库连接池: 使用数据库连接池来管理数据库连接,避免频繁地创建和销毁连接,提高数据库访问的效率。
  7. 代码优化: 优化代码逻辑,减少不必要的计算和循环,避免过度的嵌套和复杂的条件判断。
  8. 资源合并和压缩: 将多个资源文件(如CSS、JavaScript)合并为一个,减少网络请求次数,同时对静态资源进行压缩,减小文件体积。
  9. 定期清理和优化数据库: 定期清理无用数据,进行数据库索引优化和碎片整理,保持数据库的健康状态。
  10. 使用CDN加速: 使用内容分发网络(CDN)来分发静态资源,减少服务器的负载和加快资源传输速度。
  11. 请求合并: 将多个小请求合并为一个大请求,减少网络请求的次数。
  12. 服务拆分: 将大型服务拆分成小的微服务,按需启动和部署,提高系统的灵活性和可维护性。
  13. 使用缓存代理: 使用缓存代理服务器,将部分请求直接由缓存返回,减少对后端服务的压力。
  14. 监控和分析: 使用性能监控工具来监控系统的性能指标,定位性能瓶颈,并根据结果进行优化。

数据层优化:

  1. 合理设计数据库表结构: 对于关系型数据库,合理设计表结构可以提高查询效率。使用适当的数据类型和索引来优化数据库查询。
  2. 使用缓存: 对于频繁读取的数据,可以使用缓存来减少数据库查询次数,提高读取性能。可以使用内存缓存(如Redis、Memcached)或分布式缓存来存储常用的数据。
  3. 分库分表: 对于大型数据量的数据库,可以考虑将数据进行分库分表,将数据分散存储在多个数据库中,提高数据库读写性能。
  4. 异步处理: 对于耗时的数据处理操作,可以使用异步处理或消息队列来减少用户请求的响应时间。
  5. 批量处理: 对于大量数据的处理,可以使用批量处理方式,而不是逐条处理数据,减少数据库事务和IO操作的开销。
  6. 数据压缩: 对于大量的文本数据或日志数据,可以使用数据压缩技术减小存储空间和网络传输数据量。
  7. 定期清理: 定期清理无用的数据,减少数据库存储空间占用。
  8. 使用索引: 在数据库中使用合适的索引可以提高查询效率,加快数据检索速度。
  9. 冗余数据: 对于频繁查询的数据,可以在多个位置进行冗余存储,减少查询的复杂度。
  10. 数据预处理: 对于常用的查询,可以在数据插入或更新时进行预处理,以减少查询时的计算开销。
  11. 分级存储: 对于历史数据或不常访问的数据,可以将其存储在低成本的存储介质中,以减少高成本存储的负担。
  12. 使用NoSQL数据库: 根据应用场景选择合适的数据库类型,对于复杂的查询和海量数据的存储,NoSQL数据库可能更适合。
  13. 压缩和序列化: 在数据传输过程中,可以使用压缩和序列化技术来减小数据传输量,提高数据传输效率。
  14. 使用缓存代理: 对于一些经常请求的数据,可以使用缓存代理服务器,直接返回缓存数据,减少后端服务器的负载。

总结

可以看到,上面很多内容是可以通用的,例如减少请求、使用缓存。但是具体到每一层的具体措施又不一样。因此,性能优化问题可以很好地考察技术深度和广度。具体到面试过程中,我们可以先分类总结出一些优化技巧,再加以细节的补充和完善。面试官希望能通过这个题目对面试者的技术能力有一个大概的把握,这也是这道题目最大的意义。

性能优化严格来说是没有终点的。所以我们在回答的时候,如果面试官问到了一些具体的优化指标,我们需要给出一些对比的数据,例如优化前页面加载时间xx秒,优化后加载时间xx秒。优化前单机QPSxx,优化后单机QPSxx。

继续阅读