亚马逊AWS官方博客

查找最昂贵的代码行 – Amazon CodeGuru 现已正式发布

将新应用程序引入生产环境、随着代码的增长和发展维护其代码库,同时响应运营问题是一项艰巨的任务。出于这个原因,您可以发现许多关于如何组建团队、采用哪种方法以及如何安全地自动执行软件交付管道的想法。

在去年的 re:Invent 大会上,我们推出了预览版 Amazon CodeGuru,这是一种由机器学习提供支持的开发人员工具,可通过基于运行时数据的自动代码审查和性能建议帮助您改进应用程序并解决问题。 在过去几个月里,我们已经发布了多项改进,包括更具成本效益的定价模型对 Bitbucket 存储库的支持以及使用命令行开关启动分析代理的功能,因此您无需再修改代码应用程序或添加依赖项以运行代理。

您可以通过两种方式使用 CodeGuru:

  • CodeGuru Reviewer 使用程序分析和机器学习来检测开发人员难以发现的潜在缺陷,并就 Java 代码中的修复方法提出建议。可以将代码存储在 GitHub(现在也可以存储在 GitHub Enterprise)、AWS CodeCommitBitbucket 存储库中。在与 CodeGuru Reviewer 关联的存储库上提交拉取请求时,它会提供有关如何改进代码的建议。每个拉取请求都对应一次代码审查,每个代码审查可以包含多个建议,这些建议显示为对拉取请求的注释。
  • CodeGuru Profiler 提供交互式的可视化内容和建议,可帮助您使用实时应用程序中的运行时数据微调应用程序性能并解决操作问题。它目前支持以 Java、Scala、Kotlin、Groovy、Jython、JRuby 和 Clojure 等 Java 虚拟机 (JVM) 语言编写的应用程序。CodeGuru Profiler 可以帮助您找到在 CPU 使用率或引入延迟方面最昂贵的代码行,并提供提高效率和消除瓶颈的方法。您可以在生产环境中,以及在有意义的工作负载下(例如在生产前环境中)测试应用程序时使用 CodeGuru Profiler。

今天,Amazon CodeGuru 全面推出并新增了多项功能。

CodeGuru Reviewer 中包括以下功能:

  • 支持 Github Enterprise – 现在,您可以在 Github Enterprise 本地存储库上扫描拉取请求并针对源代码获取建议,并且提供导致问题的原因以及解决方法的说明。
  • 用于解决缺陷和改进代码的新型建议 – 例如,检查输入验证,避免可能损害安全性和性能的问题以及查找具有相同功能的多个代码副本。

CodeGuru Profiler 中有以下新功能:

  • 自动检测 – 我们会在应用程序配置文件中自动检测那些 CPU 时间或延迟比例最高的方法的异常。
  • 支持 Lambda 函数 – 现在,您可以对 AWS Lambda 函数进行分析,其方法与分析在 Amazon Elastic Compute Cloud (EC2) 上托管的应用程序以及在 Amazon ECSAmazon Elastic Kubernetes Service 上运行的容器化应用程序(包括使用 AWS Fargate 的应用程序)一样。
  • 建议报告中的问题的成本 – 建议包含可操作的解决步骤,其中说明了具体的问题、CPU 影响以及如何解决问题。为了帮助您更好地确定活动的优先级,现在,您可以通过应用建议来估算节省的费用。
  • 为我的代码着色 – 在可视化内容中,为了帮助您轻松找到自己的代码,我们为您的方法进行了着色,使其有别于与您可能使用的框架和其他库。
  • CloudWatch 指标和警报 – 用于跟踪和监视已发现的效率问题。

让我们看看运行时的这些新功能!

将 CodeGuru Reviewer 与 Lambda 函数配合使用
我在 GitHub 账户中创建了一个新的存储库,目前暂时将其留空。 在本地,我使用 Java 11 runtime 开发 Lambda 函数、初始化 Git 存储库,并且仅向 master 分支添加 README.md 文件。这样,我稍后可以将所有代码添加为拉取请求,并通过 CodeGuru 进行代码审查。

git init
git add README.md
git commit -m "First commit"

现在,我将 GitHub 存储库添加为原始存储库,并将更改推送到新存储库:

git 远程添加原始存储库 https://github.com/<my-user-id>/amazon-codeguru-sample-lambda-function.git
git push -u origin master

我在 CodeGuru 控制台中关联存储库:

关联存储库后,我将创建一个新的 dev 分支,向其添加所有本地文件,然后远程推送它:

git checkout -b dev
git add .
git commit -m "Code added to the dev branch"
git push --set-upstream origin dev

在 GitHub 控制台中,我通过比较 masterdev 这两个分支中的更改来打开一个新的拉取请求。我确认拉取请求能够合并,然后创建它。

由于存储库与 CodeGuru 关联,因此 CodeGuru 控制台的代码审查部分会将一个代码审查列为待定

几分钟后,代码审查状态为已完成,并且 CodeGuru Reviewer 会在创建拉取请求的同一个 GitHub 页面上发布建议。

糟糕! 我正在函数调用方法内创建 Amazon DynamoDB 服务对象。这样,就不能在不同调用中重复使用它。这种做法效率不高。

为了提高 Lambda 函数的性能,我遵循 CodeGuru 的建议,并将 DynamoDB 服务对象的声明移到 Java 应用程序对象的静态最终属性中,以便在函数初始化期间仅实例化一次。然后,我按照建议中的链接学习了更多使用 Lambda 函数的最佳实践

将 CodeGuru Profiler 与 Lambda 函数配合使用
CodeGuru 控制台中,我创建了一个 MyServerlessApp-Development 分析组,并选择了 Lambda 计算平台。

接下来,我向 Lambda 函数所使用的 AWS Identity and Access Management (IAM) 角色授予了向分析组提交数据的权限。

现在,控制台将为我提供分析 Lambda 函数所需的所有信息。为配置分析代理,我使用了几个环境变量:

  • AWS_CODEGURU_PROFILER_GROUP_ARN,用于指定要使用的分析组的 ARN
  • AWS_CODEGURU_PROFILER_ENABLED,用于启用 (TRUE) 或禁用 (FALSE) 分析。

按照说明(适用于 MavenGradle)添加依赖项,并在生成中包括分析代理。然后,我更新 Lambda 函数的代码以将处理程序函数包装在代理提供的 LambdaProfiler 中。

为了生成一些负载,我启动了几个脚本,以使用 Amazon API Gateway 作为触发器来调用我的函数。几分钟后,分析组开始显示描述我的 Lambda 函数的运行时行为的可视化内容。

例如,我可以看到在我的函数在不同方法中花费的 CPU 时间。底部有入口点方法。向上滚动时,会发现在堆栈跟踪更深层调用的方法。我右键单击并隐藏 LambdaRuntimeClient 方法以专注于我的代码。 请注意,我的方法的颜色有别于我使用的程序包(例如适用于 Java 的 AWS 开发工具包)中的方法。

我对 Lambda 平台调用的处理程序方法中发生的事情非常感兴趣。我选择了处理程序方法,现在,它成为了可视化内容的新“基础”。

我将指针指向每种方法时,都会获得更多信息,包括基于分析代理在选定的时间段内所承受的负载得出的在生产环境中运行该代码的特定部分的估算年度成本。就我而言,处理程序函数的成本估计为 6 美元。如果我选择了上面两个主要函数,则每个函数估计为 3 美元。成本估算适用于在 Lambda 函数、EC2 实例和容器化应用程序上运行的代码。

同样,我可以显示延迟,以了解我的代码中的方法花费了多少时间。我保持选定 Lambda 函数处理程序方法,以深入了解我所控制的内容,并查看在哪些方面花费的时间最多。

CodeGuru Profiler 还将基于收集的数据提供建议。我在管理加密方面花费了太多时间(超过 4%)。我可以使用更高效的加密提供程序,例如本博客文章中介绍的开源 Amazon Corretto Crypto Provider。这样应该可以将花费的时间降至预期水平,即约为我的配置文件的 1%。

最后,我将编辑分析组以启用通知。这样,如果 CodeGuru 在我的应用程序配置文件中检测到异常,则会在一个或多个 Amazon Simple Notification Service (SNS) 主题中通知我。

现已推出
Amazon CodeGuru 现已在 10 个区域推出,我们正致力于在未来几个月内增加更多区域。有关区域可用性,请参阅 AWS 区域表

CodeGuru 通过提供智能建议的自动化代码审查器和应用程序分析器,帮助您改进应用程序代码并降低计算和基础架构成本。通过使用基于运行时数据的可视化内容,可以快速找到应用程序中最昂贵的代码行。通过 CodeGuru,只需按实际使用量付费。定价基于 CodeGuru Reviewer 分析的代码行以及 CodeGuru Profiler 的采样时间(小时数)。

要了解更多信息,请参见相关文档

Danilo