本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:Android平台上的性能测试对于确保应用性能至关重要,尤其是在硬件资源受限的移动设备上。本文深入探讨了如何利用 procrank 等专业工具来检测Android应用的性能,涵盖了CPU使用率和进程内存占用等关键指标。介绍了 procrank 的使用方法、输出结果的分析技巧以及其他辅助性能测试工具的介绍。同时,提供了一系列性能测试的策略和方法,旨在帮助开发者通过综合运用各种工具和技术,优化应用性能,提升用户体验和市场竞争力。
Android APK性能测试 procrank等工具

1. Android APK性能测试的重要性

1.1 性能测试的作用

在当今移动应用市场竞争激烈的背景下,用户对于应用程序的性能要求日益提高。性能测试成为确保应用流畅运行、提升用户体验的关键步骤。对于开发者而言,合理的性能测试能够帮助他们识别和解决在CPU、内存、网络等方面的性能瓶颈,确保应用的高效率和稳定性。

1.2 性能测试的挑战

由于Android设备的多样化,性能测试面对的挑战更加复杂。不同品牌、不同配置、不同操作系统的设备都可能对应用的性能产生影响。这就要求性能测试不仅要在硬件上具有广泛的覆盖性,还需要在软件层面制定详尽的测试策略。

1.3 性能测试的重要性总结

综上所述,对Android APK进行性能测试,不仅可以优化应用程序,避免资源浪费和潜在的性能问题,还可以提高产品在市场上的竞争力。随着用户对应用性能要求的不断增高,性能测试已经成为不可或缺的质量保证环节,是开发过程中的重要组成部分。

2. procrank 工具使用与分析技巧

procrank 是一个在 Android 平台下,由 Google 提供的用于查看进程内存使用情况的命令行工具。它可以帮助开发者分析应用的性能问题,特别是在内存占用方面。接下来,将详细探讨 procrank 的安装、操作以及如何通过它进行性能瓶颈的定位和分析。

2.1 procrank 工具概述

2.1.1 procrank 的定义和用途

procrank 是一个基于 Linux 的工具,它是 Android 系统中众多工具的一员,通常用于开发者模式下。该工具能够列出当前系统中所有进程的内存使用情况,包括 RAM(物理内存)和虚拟内存,以及每个进程的内存分配细节。这对于识别内存使用量过高的进程和潜在的内存泄漏非常有帮助。

2.1.2 procrank 在性能测试中的地位

在性能测试领域, procrank 是一个重要的诊断工具。它与 Android 的其他性能工具如 adb shell dumpsys meminfo 相比,提供了更为详细和针对性的内存信息。 procrank 在定位内存问题时,特别是对于理解多进程环境下的内存分配模式具有独特优势。开发者可以通过这个工具,为性能测试提供更为深入的分析和依据。

2.2 procrank 的安装和基本操作

2.2.1 安装 procrank 的系统要求和步骤

procrank 工具通常已经包含在 Android 的 SDK 平台工具中,因此在安装 Android Studio 或对应的 SDK 平台工具时, procrank 会被自动安装到 platform-tools 目录下。它的使用不需要特定的安装步骤,只需确保 SDK 平台工具已经被正确安装即可。

2.2.2 procrank 的界面解读和命令行使用

procrank 的使用基于命令行界面。在使用前,需要通过 ADB 将工具推送到目标设备上。使用该工具时,需要通过命令行输入 procrank 命令,它将输出当前所有进程的内存使用情况。输出的信息包括:

  • VSS :虚拟内存集大小。
  • RSS :实际驻留集大小,表示进程占用的物理内存。
  • PSS :按比例分配的内存,每个进程占用的实际物理内存除以该进程共享内存的页数。
  • USS :独立内存集大小,只计算该进程自身占用的物理内存。

输出信息的排序默认是按照 PSS 降序排列的,这对于识别内存占用最大的进程非常有帮助。

2.3 procrank 分析技巧和案例分析

2.3.1 procrank 输出信息的解读

理解 procrank 输出信息对于性能测试至关重要。每一条输出信息都包含以下字段:

  • PID :进程ID。
  • VSS RSS PSS USS :上述提及的内存使用指标。
  • NAME :进程名称。

分析时,首先应关注 PSS USS ,因为这两个指标能够反映进程真实的内存占用情况。如果发现某个进程的 USS 显著高于其他进程,可能意味着该进程存在内存泄漏问题。

2.3.2 性能瓶颈的定位方法和案例研究

在实际案例中,一个典型的性能瓶颈定位流程如下:

  1. 运行 procrank 获取当前内存使用情况。
  2. 利用 USS 指标识别内存占用异常高的进程。
  3. 对这些进程进行进一步的分析,比如通过 dumpsys meminfo 获取更详细的内存使用信息。
  4. 结合代码审查和内存分析工具(如 Android Studio 中的 Memory Profiler)进行问题定位。

通过这个流程,开发者可以有效地识别出内存使用中的性能瓶颈,并采取相应的优化措施。

接下来,为了更清晰地解释 procrank 的使用和分析技巧,我们通过一个具体的案例来展示。

案例研究

假设我们正在开发一款资源密集型的 Android 游戏。游戏发布前,需要通过 procrank 进行最后的性能审查。

  1. 检查命令执行
    首先在终端执行 adb shell procrank 命令,输出了进程的内存使用情况。

  2. 初步分析
    分析 procrank 的输出,我们特别关注 USS 列,观察到一个名为 “com.example.game” 的进程使用了大量内存。

  3. 详细检查
    使用 adb shell dumpsys meminfo com.example.game 命令来获取该进程更详细的内存信息。

  4. 问题识别
    通过 dumpsys meminfo 输出的详细信息,我们发现了一个较大的对象分配,这可能指向一个潜在的内存泄漏。

  5. 优化与改进
    根据这个分析结果,回到代码中进行详细审查,最后发现并修复了一个导致内存泄漏的 bug。

通过上述步骤,我们成功利用 procrank 定位并优化了性能瓶颈。这个案例说明了 procrank 在实际性能测试中的重要性和应用方法。

以上,我们已经讨论了 procrank 工具的基本概念、安装方法、基本操作和分析技巧。接下来,我们将介绍其他多种性能测试辅助工具,它们可以与 procrank 协同工作,为性能测试提供更全面的视角。

3. 多种性能测试辅助工具介绍

在现代的性能测试领域中,使用单一工具往往无法全面地评估一个应用的性能。因此,测试人员需要掌握多种工具来完成性能测试的不同方面。本章将详细介绍不同类型的性能测试辅助工具,并分析它们在性能测试中的应用。

3.1 系统资源监控工具

在性能测试过程中,了解系统资源的使用情况是至关重要的。这可以帮助测试人员快速定位性能瓶颈,进行有针对性的优化。

3.1.1 CPU和内存监控工具对比

CPU和内存是影响应用性能的两个关键资源,因此,监控工具必须能够提供详尽的数据以便于分析。

  • top/htop :top是一个常用的Linux系统监控工具,它提供实时的系统状态,包括CPU使用率、内存使用率以及进程信息。htop是top的一个增强版,提供更直观的界面和更多的交互功能。
  • Windows Task Manager :Windows任务管理器能够显示系统的CPU、内存使用情况,并提供进程管理等其他功能。
  • iostat :专门用于监控磁盘I/O性能的工具,对于理解磁盘活动和性能瓶颈很有帮助。

表格展示常见CPU和内存监控工具特性:

工具名称 平台支持 实时监控 进程管理 CPU信息 内存信息 I/O信息
top Linux
htop Linux
Task Manager Windows
iostat 多平台

3.1.2 I/O性能监控工具介绍

I/O性能监控工具专注于磁盘读写速度和I/O响应时间,这对于理解存储子系统的性能至关重要。

  • iotop :iotop是top的补充,专注于磁盘I/O。它能够显示进程的I/O使用情况,并且可以按使用量排序。
  • Perf :Linux内核提供的性能分析工具,可以用来收集系统性能数据,包括CPU和I/O。

3.2 应用性能分析工具

应用性能分析工具关注应用层面的性能数据,帮助开发者和测试人员了解应用在真实环境中的表现。

3.2.1 常用应用性能分析工具列表

  • Android Profiler :Android Studio中的工具,能够监控应用的CPU、内存和网络使用情况。
  • Xcode Instruments :苹果公司为iOS开发者提供的性能分析工具,提供了丰富的分析模板,包括内存泄漏、CPU使用等。
  • Dynatrace :一款商业性能分析工具,提供全栈监控和应用性能管理(APM)解决方案。
  • New Relic :另一款提供APM功能的商业解决方案,可用于监控应用性能并提供优化建议。

3.2.2 各工具功能和使用场景分析

Android Profiler 的使用方法包括:

  • 打开Android Studio。
  • 连接一台Android设备或启动一个Android模拟器。
  • 运行你的应用,并点击顶部的Profiler标签。
  • 在Profiler中,你可以看到实时的CPU、内存和网络使用情况。
// 示例代码段,展示如何在Android代码中记录性能数据
Log.d("Performance", "CPU usage: " + cpuUsage + "%, Memory usage: " + memoryUsage + "%");

代码逻辑逐行解释:

  • Log.d("Performance", "CPU usage: " + cpuUsage + "%, Memory usage: " + memoryUsage + "%"); :这条代码记录了CPU和内存使用情况,并将其输出到Logcat中,方便开发者在Profiler中查看。

对于性能分析工具的使用场景,应根据应用需求和目标平台来选择合适的工具。例如,如果你正在开发Android应用,则Android Profiler可能是最佳选择。

3.3 性能测试工具的集成与管理

集成多个性能测试工具可以提供一个综合的性能分析平台,简化测试过程。

3.3.1 工具集成的方法和好处

集成方法包括使用脚本语言(如Python或Shell脚本)编写自动化测试流程,以及使用集成工具(如Jenkins)进行持续集成。

好处包括:

  • 提高测试效率
  • 减少重复工作
  • 易于管理和维护

3.3.2 性能测试流程的优化策略

优化策略包括:

  • 定期回顾和更新测试脚本。
  • 使用版本控制系统管理测试脚本和数据。
  • 定期进行性能测试培训和知识分享。
  • 利用云服务进行负载测试以模拟大规模用户访问。

通过这些策略的实施,性能测试流程将更加高效和可靠。

4. 性能测试策略与实践

4.1 性能测试的基本概念和方法

4.1.1 性能测试的目的和类型

性能测试是评估软件系统在特定条件下的行为和性能的过程,其主要目的是确保系统满足设计要求,并在各种环境下能够稳定运行。性能测试可以分为以下几种类型:

  • 负载测试(Load Testing) :通过模拟实际操作条件,测试系统在特定负载下的性能表现。
  • 压力测试(Stress Testing) :评估系统在极端负载条件下的行为,即超出正常工作负载的极限。
  • 稳定性测试(Soak Testing) :长时间运行系统以确定系统性能的持续性。
  • 配置测试(Configuration Testing) :测试不同软硬件配置下的系统性能。

4.1.2 性能测试流程的制定

制定性能测试流程是保证测试有效性的关键,一般来说,性能测试流程应该包括以下几个步骤:

  • 需求分析 :明确测试目标和性能指标,包括响应时间、吞吐量、资源利用率等。
  • 测试设计 :根据需求设计测试用例,确定测试场景。
  • 环境搭建 :搭建与生产环境相似的测试环境,确保测试数据的准确性。
  • 测试执行 :执行测试,收集性能数据。
  • 结果分析 :分析测试结果,识别性能瓶颈。
  • 报告编写 :编写性能测试报告,提出优化建议。

4.2 性能测试案例实操

4.2.1 选择合适的测试案例

为了确保性能测试的有效性,选择合适的测试案例至关重要。测试案例应覆盖主要的业务流程和用户操作,包括最常用的功能和最有可能成为性能瓶颈的场景。例如,对于一个电商应用,测试案例应包括商品浏览、搜索、下单、支付等关键操作。

4.2.2 测试案例的执行和结果分析

在执行测试案例时,需要确保测试环境的稳定性和一致性,使用自动化工具来提高测试效率。在测试执行完成后,分析工具产生的日志文件和性能数据至关重要。以下是分析性能测试结果的步骤:

  1. 数据收集 :使用性能测试工具收集数据,如响应时间、每秒请求数、CPU占用率等。
  2. 数据整理 :将收集到的数据进行整理,形成图表,以便于分析。
  3. 瓶颈分析 :对照性能指标,分析数据中的异常和瓶颈。
  4. 报告编写 :将分析结果整理成报告,并给出优化建议。

4.3 性能测试的优化策略

4.3.1 优化前的性能测试数据收集

在开始优化之前,需要有一个详细的性能测试数据基线,这包括:

  • 业务性能指标 :如交易处理时间、页面加载时间等。
  • 系统资源使用情况 :CPU、内存、网络、磁盘I/O等。
  • 应用日志 :跟踪应用程序的行为和错误信息。

4.3.2 针对性优化措施的制定和执行

针对性能测试中发现的问题和瓶颈,制定相应的优化措施:

  • 代码优化 :重构低效代码,优化算法。
  • 资源管理 :优化资源使用,如内存管理、数据库连接池配置。
  • 架构调整 :如果需要,对系统架构进行调整,比如引入缓存机制、负载均衡。
  • 硬件升级 :如果软件优化已经达到瓶颈,则可能需要硬件升级。

为了确保优化的效果,每个优化措施都应该经过严格的测试验证,确保优化后的性能有显著提升。

5. 针对性优化与性能监控

5.1 优化过程中的性能监控

性能监控在优化过程中扮演着至关重要的角色。它能够帮助开发者实时了解应用程序在运行时的状态,从而快速定位到性能瓶颈,并进行针对性的优化。在本节中,我们将深入探讨性能监控的重要性以及如何有效地使用实时性能监控工具。

5.1.1 性能监控的重要性

在应用程序的开发和维护过程中,性能问题往往是用户最直接感受到的问题之一。性能监控能够提供数据支撑,帮助团队评估应用程序在各种场景下的表现,并及时发现可能影响用户体验的性能瓶颈。

5.1.2 实时性能监控工具的使用

有许多实时性能监控工具可以帮助开发者对Android应用程序进行性能分析。例如, Android Profiler 是Android Studio自带的性能监控工具,它包含了CPU、内存和网络性能的实时监控功能。下面是使用 Android Profiler 的基本步骤:

  1. 打开Android Studio,选择正在运行的项目。
  2. 点击 View -> Tool Windows -> Android Profiler
  3. 在弹出的窗口中,选择 Start Recording 按钮开始监控。
  4. 在应用程序运行时, Android Profiler 将实时显示CPU、内存和网络的使用情况。
  5. 可以通过滑动时间轴来分析特定时间段的性能数据。

下面是 Android Profiler 捕获到的内存使用情况的示例代码块:

// 示例代码:查看内存分配情况
Memory Profiler > Allocation Tracker > Start Tracking
// 选择需要追踪的内存分配点
// 点击"Take Heap Snapshot"来获取当前的内存快照

在使用 Android Profiler 时,内存快照功能特别有用,它可以用来识别内存泄漏和优化内存使用。开发者可以通过比较不同内存快照来观察内存使用情况的变化,快速定位到问题所在。

5.2 常见性能瓶颈的优化方法

针对性能瓶颈的优化是提高应用程序运行效率的关键步骤。常见的性能瓶颈包括内存泄漏和CPU占用过高。

5.2.1 内存泄漏和优化技巧

内存泄漏是导致应用程序消耗过多内存资源的主要原因之一。为了避免内存泄漏,开发者需要养成良好的编程习惯:

  • 避免在后台线程上进行UI操作。
  • 尽早释放不再使用的资源,例如 InputStream OutputStream
  • 使用弱引用( WeakReference )来管理持有的对象,以便GC能够回收它们。

当发现内存泄漏时, MAT (Memory Analyzer Tool)可以用于分析内存泄漏的原因。该工具可以分析Java堆转储文件,帮助开发者找出内存泄漏点。

5.2.2 CPU占用过高和优化策略

CPU占用过高通常是由于应用程序中存在大量的计算操作或资源密集型任务。优化策略包括:

  • 优化算法和数据结构,减少不必要的计算。
  • 使用异步任务处理耗时操作,避免阻塞主线程。
  • 对于资源密集型的任务,考虑使用后台服务,例如使用 IntentService
  • 分析并减少不必要的广播接收器的使用。

使用 systrace 工具可以对CPU使用情况进行详细分析。 systrace 会记录系统中发生的所有事件,并以时间轴的形式展示出来,帮助开发者精确定位到耗时操作。

5.3 性能优化案例分析

5.3.1 案例选择和前期准备

选择具有代表性的性能瓶颈案例是进行优化分析的第一步。案例的选择应基于用户反馈、性能监控数据和性能测试结果。前期准备工作包括:

  • 准备测试设备和环境。
  • 确保测试设备具备足够的资源来复现性能问题。
  • 确保有完整的应用程序版本和相关的性能监控工具。

5.3.2 案例优化过程的详解和结果展示

以一个典型的内存泄漏案例为例,当应用程序运行一段时间后,内存使用量持续增加,最终导致应用崩溃。优化过程可能如下:

  1. 使用 MAT 分析内存转储文件,找出内存泄漏的对象和它们的引用链。
  2. 根据分析结果,修改代码,移除或替换掉不再需要的资源引用。
  3. 重新进行性能监控,验证内存使用情况是否有显著改善。

在优化过程中,可以结合使用 Android Profiler 的内存追踪功能,观察内存分配和回收的行为,确保优化措施奏效。

上图是一个假设的性能优化前后对比图,从图中可以明显看出内存使用量的降低。

通过以上分析和优化过程,开发者能够有效地对应用程序的性能瓶颈进行诊断和修复,最终达到提升用户体验的目标。在未来的章节中,我们将进一步探讨自动化性能测试的实施和性能测试的未来趋势与挑战。

6. 自动化性能测试的实施

6.1 自动化测试的原理和优势

6.1.1 自动化测试与手动测试的对比

自动化测试是指使用特定的测试工具或脚本,由计算机自动执行测试用例的过程,与之相对的是手动测试,即测试人员手动执行测试用例。两者之间的对比主要体现在以下几个方面:

  • 效率提升 :自动化测试可以快速执行大量重复的测试用例,相比手动测试效率大幅提升。
  • 准确性和一致性 :自动化测试避免了人为因素导致的测试遗漏或错误,确保了测试的准确性和一致性。
  • 维护成本 :虽然自动化测试的初始设置成本较高,但长期来看,对测试用例的修改和维护成本较低。
  • 资源占用 :自动化测试允许测试人员将时间投入到更复杂的测试和分析工作中,而不是重复性劳动。

6.1.2 自动化测试的环境搭建和配置

搭建和配置自动化测试环境涉及多个步骤,以下是基本流程:

  1. 选择合适的自动化测试工具 :根据项目需求、测试类型和预算选择合适的自动化测试工具,如Selenium、Appium等。
  2. 准备测试硬件和软件环境 :确保测试环境具备所有运行测试所需的软硬件资源。
  3. 安装测试工具 :按照工具文档进行安装,并完成相关配置,例如驱动安装、环境变量设置等。
  4. 编写测试脚本 :根据需求编写测试脚本,包括测试用例的选择、测试数据的准备和断言的设置等。
  5. 测试脚本的执行和维护 :执行测试脚本,并在需要时进行维护和更新。

6.2 自动化测试工具的选择和应用

6.2.1 常用自动化测试工具的对比分析

目前市场上有多种自动化测试工具,以下是几种常见工具的对比分析:

工具 适用平台 语言支持 特点 难易程度
Selenium Web应用 Java, Python, C#, Ruby等 开源且社区活跃,支持多种浏览器 中等
Appium 移动应用 Java, Python, JavaScript等 支持跨平台自动化测试 较高
JMeter 性能测试 Java 主要用于压力测试 较低
LoadRunner 性能测试 C 功能全面,但成本较高

6.2.2 自动化测试用例的设计和编写

设计和编写自动化测试用例时,需要遵循以下步骤:

  1. 需求分析 :分析需求,确定哪些功能需要自动化测试。
  2. 用例设计 :设计测试用例,涵盖正常流程和异常流程。
  3. 编写测试脚本 :根据设计的测试用例编写脚本,脚本需要包括初始化、操作步骤和结果验证三部分。
  4. 测试数据准备 :准备测试数据,包括测试输入数据和预期结果数据。
  5. 脚本的维护和优化 :根据执行结果对脚本进行调整,优化脚本的可读性和可维护性。
// 示例:Selenium自动化测试用例的Python代码段
from selenium import webdriver
from selenium.webdriver.common.keys import Keys

# 初始化Chrome驱动
driver = webdriver.Chrome()

# 打开网页
driver.get("http://www.example.com")

# 输入搜索词并提交
search_box = driver.find_element_by_name('q')
search_box.send_keys('自动化测试')
search_box.send_keys(Keys.RETURN)

# 等待页面加载完成
driver.implicitly_wait(30)

# 验证标题是否正确
assert "自动化测试结果" in driver.title

# 关闭浏览器
driver.quit()

6.3 自动化测试的监控和结果评估

6.3.1 自动化测试过程的监控方法

自动化测试过程监控是确保测试质量和进度的关键环节,常用方法包括:

  • 日志记录 :记录测试过程中的关键信息,包括测试用例执行情况、系统响应等。
  • 事件通知 :通过邮件、短信或即时通讯工具,在测试出现错误时及时通知相关人员。
  • 实时监控系统 :使用专门的监控工具,如Selenium Grid,来实现测试过程的实时监控。

6.3.2 测试结果的分析和评估标准

自动化测试结果的分析和评估包括以下几个方面:

  • 执行报告 :生成详细的测试执行报告,包括执行时间、成功用例数、失败用例数等。
  • 问题跟踪 :记录和跟踪发现的问题,包括缺陷的状态、严重程度、影响范围等。
  • 性能指标 :评估应用性能指标,如响应时间、吞吐量等。
  • 测试覆盖率 :计算测试覆盖率,确保测试用例覆盖了所有重要功能。
指标 评估标准
测试覆盖率 100%功能覆盖
通过率 >95%用例通过
平均响应时间 <2s
平均成功率 >98%
缺陷密度 <1/1000 LOC

通过以上评估标准,可以对自动化测试的效果进行量化分析,从而指导后续的测试和优化工作。

7. 性能测试的未来趋势与挑战

随着移动互联网的迅猛发展,性能测试在移动领域的应用变得越来越重要。这不仅带来了新的挑战,同时也为性能测试领域带来了新的机遇。本章节将深入探讨性能测试在移动领域的挑战与机遇,以及性能测试技术的创新方向。

7.1 性能测试在移动领域的挑战与机遇

7.1.1 移动互联网的发展对性能测试的影响

移动互联网的普及使得移动应用性能成为用户体验的关键因素之一。移动设备的多样性和复杂性导致了性能测试的复杂性。从不同的操作系统到多样化的硬件配置,再到网络条件的不稳定性,这些都给性能测试带来了挑战。

7.1.2 性能测试在移动领域的未来趋势

随着5G技术的推广和IoT设备的增多,移动性能测试将变得更加多维和综合。我们需要考虑的不仅是应用本身,还有设备和网络之间的互动。自动化测试的智能化,以及持续集成和持续部署(CI/CD)的结合,将是未来移动性能测试的趋势。

7.2 性能测试技术的创新与展望

7.2.1 新兴技术对性能测试的影响

随着云计算、大数据和人工智能技术的发展,性能测试也趋向于智能化和自动化。例如,AI可以通过机器学习模型来预测应用的性能瓶颈,并给出优化建议。云计算提供的弹性资源可以帮助我们轻松应对大规模的性能测试需求。

7.2.2 性能测试技术的创新方向和发展路径

未来的性能测试技术将更加注重用户体验的预测和优化。我们可能会看到更多基于用户行为模拟的测试场景,以及对用户真实环境的模拟测试。此外,随着DevOps文化的普及,性能测试将更加紧密地融入开发流程,实现快速反馈和持续优化。

在性能测试领域,工具和方法的不断创新将帮助我们更好地应对挑战,抓住机遇。我们可以期待,在不久的将来,性能测试不仅能够提供静态的性能数据,还能提供动态的性能趋势预测和优化建议,从而使得应用更加高效、稳定和安全。

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:Android平台上的性能测试对于确保应用性能至关重要,尤其是在硬件资源受限的移动设备上。本文深入探讨了如何利用 procrank 等专业工具来检测Android应用的性能,涵盖了CPU使用率和进程内存占用等关键指标。介绍了 procrank 的使用方法、输出结果的分析技巧以及其他辅助性能测试工具的介绍。同时,提供了一系列性能测试的策略和方法,旨在帮助开发者通过综合运用各种工具和技术,优化应用性能,提升用户体验和市场竞争力。


本文还有配套的精品资源,点击获取
menu-r.4af5f7ec.gif

更多推荐