你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
有关优化代码成本的建议
适用于此 Azure Well-Architected 框架成本优化清单建议:
CO:11 | 优化代码成本。 评估和修改代码,以满足功能和非功能要求,资源更少或成本更低。 |
---|
本指南介绍优化代码成本的建议。 代码优化是提高应用程序代码的效率、性能和成本效益的过程。 有效的代码优化涉及对代码进行更改,以减少资源消耗、最小化执行时间并提高整体性能。
通过优化代码,可以识别并消除可能导致资源消耗增加和成本增加的低效问题。 你可以减少处理时间、内存使用量和网络开销,这可能会导致应用程序更快、响应能力更强。 改进的性能可增强用户体验,并使系统能够有效地处理更大的工作负载。
定义
术语 | 定义 |
---|---|
代码检测 | 将代码片段或库添加到在运行时收集数据和监视代码性能的代码中的做法。 |
并发 | 同时执行多个进程。 |
数据序列化 | 将数据对象转换为可以存储或传输的格式,然后在需要时重新构造为原始格式的过程。 |
热路径 | 需要高性能和低延迟的程序的关键或经常运行的部分。 |
关键设计策略
成本优化代码意味着改进代码,以使用更少的每个实例资源(例如 CPU 周期、内存和存储)实现相同的功能。 通过减少资源消耗,可以在应用程序处理大量数据或遇到高流量负载时节省资金。
在遵循有关缩放、权限大小、冗余和限制的其他成本优化工作时,代码改进最为有效。 处理这些基本元素后,可以考虑代码优化。
你可能不知道代码是否效率低下。 无服务器、自动缩放和可靠性功能可能会掩盖代码效率低下。 以下策略可帮助你识别和修复成本高于其应有成本的应用程序代码。
检测代码
检测代码是添加在运行时收集数据并监视代码性能的代码片段或库的做法。 它允许开发人员收集有关关键指标的信息,例如资源消耗 (CPU 或内存使用情况) 和执行时间。 通过检测代码,开发人员可以深入了解代码热路径、识别性能瓶颈并优化代码以提高效率和成本效益。
在理想环境中,应在软件开发生命周期的早期执行代码分析。 越早发现代码问题,修复成本越低。
尽可能自动执行此代码分析。 使用动态和静态工具进行代码分析,以减少手动工作量。 但是,请记住,此测试仍然是生产模拟。 生产可以最清楚地了解代码优化。
权衡:代码监视工具可能会增加成本。
识别和优化热路径
通过检测代码,可以测量代码路径的资源消耗。 这些度量值有助于识别热路径。 热路径对性能和资源使用情况有显著影响。 它们是关键或经常运行的程序部分,需要高性能和低延迟。
若要识别热路径,请考虑以下任务:
分析运行时数据:收集和分析运行时数据,以识别消耗大量资源(如 CPU、内存或 I/O 操作)的代码区域。 查找经常运行或需要很长时间才能完成的代码模式或部分。
度量性能:使用分析工具或性能测试框架来测量代码路径的执行时间和资源消耗量。 此度量有助于确定瓶颈和需要改进的领域。
考虑业务逻辑和用户影响:根据代码路径与应用程序功能或关键业务操作的相关性评估其重要性。 确定哪些代码路径对于向用户提供价值或满足性能要求至关重要。
查看特定于你正在使用的编程语言的性能建议。 根据这些建议评估代码,以确定需要改进的地方。 删除代码路径中可能影响性能的任何不必要的操作。
删除不必要的函数调用:查看代码。 确定对所需功能不是必需的、可能对性能产生负面影响的任何函数。 例如,如果函数调用执行之前在代码中发生的验证,则可以删除不必要的函数调用。
最大程度地减少日志记录操作:日志记录有助于调试和分析,但过多的日志记录可能会影响性能。 评估每个日志记录操作的必要性,并删除对性能分析不重要的任何不必要的日志记录调用。
优化循环和条件:分析代码中的循环和条件。 确定可以消除的任何不必要的迭代或条件。 简化和优化这些结构可以提高代码的性能。
减少不必要的数据处理:查看代码中是否有任何不必要的数据处理操作,例如冗余计算或转换。 消除这些不必要的操作以提高代码的效率。
最小化网络请求:如果代码发出网络请求,请尽量减少请求数并优化其使用情况。 尽可能批处理请求,避免不必要的往返以提高性能。
最大程度地减少分配:确定发生过多内存分配的区域。 通过尽可能减少不必要的分配和重用现有资源来优化代码。
通过最大程度地减少分配,可以提高内存效率和整体性能。 为编程语言使用适当的内存管理和垃圾回收策略。
减小数据结构大小:评估数据结构(如类)的大小,并确定可以缩减的区域。 查看数据要求并消除任何不必要的字段或属性。 通过选择适当的数据类型并有效地打包数据来优化内存使用情况。
评估跨领域实现:考虑交叉实现(如中间件或令牌检查)的影响。 评估它们是否对性能产生了负面影响。
权衡:优化代码和热路径需要开发人员在识别代码效率低下方面的专业知识。 这些高技能的人员可能需要花时间完成其他任务。
评估并发的使用
评估并发的使用涉及评估异步处理、多线程处理或多处理是否可以最大化资源利用率并减少费用。 通过使用异步处理、多线程处理或多处理,可以使用相同的资源处理更多任务。 但是,确保正确实施以避免更多开销并保持成本效益至关重要。
若要评估是否适合使用并发,可以遵循以下准则:
异步处理:异步处理允许非阻塞执行。 例如,可以启动一个进程,然后暂停它以允许第二个进程完成。
确定可以异步运行的代码组件或操作。 确定你正在使用的编程语言或框架,并了解它支持的异步编程模型,例如
async
/await
.NET 或 JavaScript 中的 promise。通过启用任务的非阻塞执行,重构代码以使用异步编程构造。 使用异步方法或回调将长时间运行的或 I/O 密集型操作与main执行线程分离。 使用编程语言或框架提供的异步 API 或库来处理异步工作流。
多线程处理:在多线程处理中,可以同时运行单个进程的多个线程。
确定可以同时独立运行的代码部分。 阅读特定于你用于多线程处理最佳做法的编程语言或框架的文档或指南。 创建多个线程或线程池来处理任务的并行执行。
实现同步机制,如锁、互斥体或信号灯,以确保线程安全,并在代码访问共享资源时防止争用条件。 请考虑使用更高级别的抽象(如线程池或基于任务的并行库)来简化多个线程的管理并简化并发控制。
多处理:多处理可以让进程并行运行。 与多线程相比,它可以更好地利用多个 CPU 核心。
确定代码中的工作负荷或操作是否适合并行处理。 确定你正在使用的编程语言或框架,并探索其多处理功能。 例如,考虑 Python 中的多处理模块或 Java 中的并行流。 将代码设计为将工作负载拆分为多个可并发处理的独立任务。
使用多处理 API 或库创建和管理并行进程。 在这些 API 或库之间分配工作负载。 若要在多个进程之间实现协调和数据共享,请根据编程语言或框架实现进程间通信 (IPC) 、共享内存或消息传递等通信机制。
使用正确的 SDK
对于成本优化,请选择旨在优化资源使用情况和提高性能的 SDK。 评估每个 SDK 的特性和功能非常重要。 请考虑它与编程语言和开发环境的兼容性。
以下指南可帮助为工作负载选择最佳 SDK:
执行性能测试:通过性能测试比较 SDK 的资源使用情况和性能。 选择最符合资源优化和性能改进需求的 SDK。 按照提供的文档和指南,将所选 SDK 集成到代码库中。
监视资源使用情况并优化代码:使用实现的 SDK 监视资源使用情况。 从监视和分析中收集见解以优化代码。
选择正确的操作系统
大多数编码语言可以在各种操作系统上运行,因此,根据更便宜的替代方法评估操作系统非常重要。 如果替代操作系统以更低的成本支持相同或类似的功能,则值得考虑。 通过选择更便宜的操作系统,可以降低许可费用和基础结构成本。
正确的操作系统有助于优化工作负荷的总体成本。 若要为工作负载选择正确的操作系统,请尝试以下活动:
评估要求:了解工作负载的特定需求,包括所使用的编码语言和框架。 考虑与其他系统的任何依赖关系或集成。
考虑兼容性:确保你选择的操作系统与编码语言、框架以及你使用的任何第三方库或工具兼容。 查看操作系统的文档和社区支持,确保它与技术堆栈具有良好的兼容性。
评估功能:确定备用操作系统是否支持与当前操作系统相同或类似的功能。 评估它是否提供工作负载所需的必要特性和功能。
比较成本:比较与操作系统相关的成本。 请考虑许可费用、支持成本和基础结构要求等因素。 寻找在不影响功能的情况下满足工作负载要求的更便宜的替代方案。
考虑性能和优化:评估备用操作系统的性能和优化功能。 查找基准、案例研究或性能比较,以了解它在实际场景中的表现。
查看安全性和稳定性:评估备用操作系统的安全性和稳定性。 查找安全更新、修补程序和社区支持,以确保操作系统得到积极维护,并且整体安全稳定。
考虑供应商支持:评估可用于备用操作系统的供应商支持级别。 检查是否有官方支持渠道、文档和用户可以在需要时提供帮助的用户社区。
优化网络遍历
优化网络遍历是尽量减少工作负载组件之间的网络流量。 数据传输通常具有相关的成本。 通过最大程度地减少网络流量,可以减少需要传输的数据量,同时降低成本。
分析工作负载并确定组件之间任何不必要的数据传输。 避免传输冗余或重复的数据,并仅传输基本信息。 例如,如果某个组件重复从另一个组件请求相同的数据,则它是优化的候选项。 可以重构代码以减少不必要的调用或批处理请求,从而最大程度地减少传输的数据。 当只需要几个字段时,应用程序可能会发送整个对象或数据结构。 通过优化代码以仅发送所需数据,可以最大程度地减小每次数据传输的大小。
优化网络协议
网络协议在网络通信的效率方面起着至关重要的作用。 通过优化网络协议,可以提高数据传输的整体效率并减少资源消耗。
请考虑以下建议:
选择高效协议:选择在数据传输速度和最小化开销方面以效率著称的协议。 例如,请考虑通过 HTTP/1.1 使用 HTTP/2 等协议。 这些协议旨在通过降低延迟和优化数据传输来提高性能。 在应用程序中使用库和框架来使用这些协议。
支持压缩:在网络协议中实现压缩机制,以减少要传输的数据的大小。 压缩可以显著减少通过网络传输的数据量,从而提高性能并减少带宽使用。 服务器端压缩通常在应用程序代码或服务器配置中启用。
利用连接池:连接池允许重复使用已建立的网络连接,以减少为每个请求建立新连接的开销。 连接池可以通过避免连接设置和拆解的开销来提高网络通信的效率。 选择连接池库或框架,并对其进行配置以满足工作负载需求。
实现其他优化:探索特定于工作负载和网络环境的其他优化。 例如,可以使用内容缓存、负载均衡和流量调整来进一步优化网络遍历。
最大程度地减少网络开销
最大程度地减少工作负载组件之间的网络流量和数据传输量。 通过减少网络开销,可以降低与数据出口和入口相关的成本,并提高整体网络性能。
请考虑以下方法:
减少冗余请求:分析代码以识别任何重复或不必要的请求。 可以修改代码以检索数据一次并根据需要重复使用,而不是对同一数据发出多个请求。
优化数据大小:查看在组件或系统之间传输的数据,并寻找最小化其大小的机会。 请考虑在传输前压缩数据或使用更高效的数据格式等技术。 通过减小数据大小,可以减少网络带宽使用量并提高整体效率。
批处理请求:如果适用,请考虑将多个较小的请求批处理成单个较大的请求。 批处理可减少建立多个连接的开销,并减少整体数据传输。
使用数据序列化:数据序列化是将复杂数据结构或对象转换为可通过网络轻松传输或存储在持久性存储系统中的格式的过程。 此策略涉及以标准化格式表示数据,因此可以在接收端有效地传输、处理和重新构造数据。
选择紧凑、快速且适合工作负载要求的序列化格式。
序列化格式 说明 协议缓冲区 (protobuf) 提供结构化数据的有效编码和解码的二进制序列化格式。 它使用类型化定义文件来定义消息结构。 MessagePack 用于通过线路进行紧凑传输的二进制序列化格式。 它支持各种数据类型,并提供快速的序列化和反序列化性能。 JavaScript 对象表示法 (JSON) 一种广泛使用的数据序列化格式,可人工阅读且易于使用。 JSON 基于文本,具有广泛的跨平台支持。 BSON) 二进制 JSON ( 二进制序列化格式,类似于 JSON,但专为高效序列化和反序列化而设计。 BSON 包括 JSON 中不可用的额外数据类型。 根据序列化格式,需要实现逻辑以将对象或数据结构序列化为所选格式,并将它们反序列化回其原始形式。 可以使用为格式提供序列化功能的库或框架来实现此逻辑。
优化数据访问
优化数据访问是指简化检索和存储数据的模式和技术,以尽量减少不必要的操作。 优化数据访问时,可以通过减少资源使用、减少数据检索和提高数据处理效率来节省成本。 请考虑数据缓存、高效数据查询和数据压缩等技术。
使用缓存机制
缓存涉及将经常访问的数据存储在离需要它的组件更近的组件。 此方法通过从缓存中提供数据而不是通过网络提取数据来减少对网络遍历的需求。
请考虑以下缓存机制:
使用外部缓存:一种常用的缓存解决方案是内容分发网络。 它通过将静态内容缓存在靠近使用者的距离,帮助最大程度地减少延迟并减少网络遍历。
优化缓存参数:配置缓存参数(例如生存时间 (TTL) ),以优化缓存的好处,同时最大程度地减少潜在的缺点。 设置适当的 TTL 可确保缓存的数据保持最新且相关。
使用内存中缓存:除了外部缓存解决方案外,还可以考虑在应用程序中实现内存中缓存。 内存中缓存可帮助利用空闲计算资源并提高已分配资源的计算密度。
优化数据库流量
可以提高应用程序与数据库通信的效率。 下面是用于优化数据库流量的一些关键注意事项和技术:
创建索引:索引是创建可提高数据检索速度的数据结构的过程。 通过在频繁查询的列上创建索引,可以显著减少运行查询所需的时间。 例如,如果你有一个用户表,其中包含用户名列,则可以在用户名列上创建索引,以加快搜索特定用户名的查询速度。
确定最常访问的列,并在这些列上创建索引,以加快数据检索速度。 定期分析和优化现有索引,以确保它们仍然有效。 避免过度编制索引,因为它会对插入和更新操作产生负面影响。
优化查询:通过考虑特定数据要求并尽量减少不必要的数据检索,设计高效的查询。 首先,根据表之间的关系使用适当的联接类型 (例如,内部联接和左联接) 。 使用查询优化技术(例如查询提示、查询计划分析和查询重写)来提高性能。
缓存查询结果:可以将频繁运行的查询的结果存储在内存或缓存中。 然后,可以从缓存提供同一查询的后续执行,这样就无需进行昂贵的数据库操作。
(ORM) 框架使用对象关系映射: 使用 ORM 功能(如延迟加载、缓存和批处理)来优化数据检索并最大程度地减少数据库往返。 使用 ORM 框架,例如用于 C# 的实体框架或适用于 Java 的 Hibernate。
优化存储过程:分析和优化存储过程的逻辑和性能。 目标是避免存储过程中不必要的计算或冗余查询。 优化临时表、变量和游标的使用,以最大程度地减少资源消耗。
组织数据
组织数据以实现高效访问和检索涉及以最大化性能并最大程度地减少资源消耗的方式构建和存储数据。 它可以缩短查询响应时间、降低数据传输成本并优化存储利用率。
下面是一些有效组织数据的方法:
分区:分区涉及将大型数据集划分为更小、更易于管理的子集(称为分区)。 可以单独存储每个分区,以允许并行处理并提高查询性能。 例如,可以根据特定值范围或跨服务器分布数据来对数据进行分区。 此方法可以增强可伸缩性、减少争用并优化资源利用率。
分片:分片是一种跨多个数据库实例或服务器水平划分数据的技术。 每个分片都包含一部分数据,查询可以跨这些分片并行处理。 分片可以通过分配工作负载并减少每个查询访问的数据量来提高查询性能。
压缩:数据压缩涉及减小数据大小,以最大程度地减少存储要求并提高数据传输效率。 由于压缩数据占用的磁盘空间较少,因此可以节省存储成本。 还可以通过网络更快地传输压缩数据,并降低数据传输成本。
例如,假设你有一个大型的客户信息数据集。 通过根据客户区域或人口统计数据对数据进行分区,可以在多个服务器之间分配工作负载并提高查询性能。 还可以压缩数据以降低存储成本并提高数据传输效率。
优化体系结构
评估工作负载体系结构,以确定资源优化的机会。 目标是使用正确的服务来完成正确的工作。
若要实现此目标,可能需要重新设计体系结构的各个部分,以使用更少的资源。 考虑无服务器或托管服务,并优化资源分配。 通过优化体系结构,可以满足功能和非功能性要求,同时减少每个实例的资源消耗量。
使用设计模式
设计模式是可重用的解决方案,可帮助开发人员解决反复出现的设计问题。 它们提供了一种结构化方法,用于设计高效、可维护且可缩放的代码。
设计模式通过提供高效资源分配和管理指南来帮助优化系统资源的使用。 例如,断路器模式通过提供一种以受控方式处理故障并从故障中恢复的机制来帮助防止不必要的资源消耗。
设计模式可通过以下方式帮助优化代码的成本:
缩短开发时间:设计模式为常见设计问题提供经过验证的解决方案,从而节省开发时间。 通过遵循既定模式,开发人员可以避免重复工作,并专注于实现其应用程序的特定要求。
改进的可维护性:设计模式可促进更易于理解、修改和维护的模块化和结构化代码。 它们可以在减少调试和维护工作方面节省成本。
可伸缩性和性能:设计模式有助于设计可缩放且高性能的系统。 Cache-Aside 模式等模式可以通过缓存频繁访问的数据来提高性能,以减少对昂贵计算或外部调用的需求。
若要实现设计模式,开发人员需要了解每种模式的原则和准则,并在代码中应用它们。 考虑确定问题的适当模式,了解其结构和组件,并将该模式集成到整体设计中。
提供了各种资源,例如文档、教程和示例代码。 这些资源可帮助开发人员有效地学习和实现设计模式。
更改配置
定期查看和更新工作负载配置,以确保它符合当前要求。 请考虑根据工作负载需求调整资源大小和配置设置。 通过优化配置,可以有效地分配资源并避免过度预配以节省成本。
重构体系结构
评估工作负载体系结构,并确定重构或重新设计组件以优化资源消耗的机会。 请考虑采用微服务体系结构、实现断路器模式和使用无服务器计算等技术。 通过优化体系结构,可以实现更好的资源利用率和成本效益。
修改资源大小
持续监视和分析工作负荷的资源利用率。 根据观察到的模式和趋势,调整资源大小和配置设置以优化资源消耗。
请考虑调整虚拟机大小、调整内存分配和优化存储容量。 通过对资源进行权限调整,可以避免与使用不足或过度预配相关的不必要的成本。
权衡:修改代码和体系结构可能与当前项目计划不相符,并可能导致计划和成本下滑。
Azure 简化
检测代码:Azure 提供监视和日志记录工具,如 Azure Monitor、 Application Insights 和 Log Analytics。 可以使用这些工具实时跟踪和分析代码的性能和行为。
识别热路径和优化路径:Application Insights 和 Application Insights 探查器 通过分析执行时间和资源使用情况来帮助识别和优化代码中的热路径。 可以使用 Profiler 最大程度地减少不必要的内存分配并优化内存使用情况。
使用正确的 SDK:Azure 以多种编程语言提供 SDK ,针对性能和易用性进行优化。 这些 SDK 提供与 Azure 服务交互的预生成函数和库,以减少对自定义实现的需求。
优化网络遍历:各种 Azure 服务支持 HTTP /2 和 QUIC 等高速网络协议,以便在服务和应用程序之间高效通信。
Azure Database for PostgreSQL灵活服务器等 Azure 服务支持连接池。
Azure 支持在各种服务中批处理,因此你可以将多个操作组合在一起,并在单个请求中运行它们。 批处理可以显著提高效率并减少网络开销。
关于数据序列化,Azure 支持各种序列化格式,包括 JSON 和 XML。 根据数据大小、性能要求和互操作性需求选择合适的序列化格式。
优化数据访问:Azure 提供Azure Cache for Redis等缓存服务。 可以使用缓存将经常访问的数据存储在离应用程序更近的距离,从而加快检索速度并减少后端负载。
索引编制和查询优化:Azure SQL 数据库和 Azure Cosmos DB 等 Azure 服务提供索引功能来优化查询性能。 通过选择正确的索引策略和优化查询,可以提高数据检索的整体效率。
对象关系映射 (ORM) : Azure 支持实体框架等 ORM 框架。 这些框架简化了面向对象的代码与关系数据库或 NoSQL 数据库之间的数据访问和映射。
优化存储过程:可以使用 Azure SQL Database 等 Azure 服务来创建和优化存储过程。 存储过程可以通过减少网络往返和预编译 SQL 语句来提高性能。
分区和分片:Azure 在 Azure Cosmos DB 和 Azure SQL Database 等服务中提供分区和分片功能。 可以使用分区跨多个节点分发数据,以优化可伸缩性和性能。
压缩数据: Azure 服务支持 GZIP 和 DEFLATE 等数据压缩技术。
优化体系结构:Azure 提供用于设计可缩放、可复原且高性能应用程序的体系结构指南和设计模式。 有关详细信息,请参阅 设计模式。
相关链接
- Azure Monitor
- Application Insights
- Log Analytics
- Application Insights Profiler
- 连接池
- Azure Database for PostgreSQL - 灵活服务器连接池
- Azure SQL数据库索引优化
- Azure Cosmos DB 索引编制策略
- Azure Cosmos DB 分区
- Azure SQL数据库分区
成本优化清单
请参阅完整的建议集。