当前位置: 首页 > news >正文

Android 应用开发 | 一种限制拷贝速率解决因 IO 过高导致系统卡顿的方法

文章目录

  • 一、问题背景
  • 二、代码实现

一、问题背景

经常做 Android 应用的小伙伴应该会有经验,就是如果应用在写入文件的时候,即使写文件的动作是在子线程,也会出现 UI 上的卡顿,这是因为文件的 IO 是由内核去完成的,此时 CPU 会从 用户态 切换到 内核态,应用将无法获得 CPU 时间片。如果 IO 较少的时候,这个切换不频繁,应用能有足够的时间片去执行绘制。但如果 IO 频繁,例如高速写入的场景下,此时 IO 占用的时间片增加,而我们知道 CPU 资源是有限的,此时会导致应用获得 时间片 将减少,导致 UI 绘制线程出现卡顿,进而影响 UI 上的卡顿。

我们可以使用 top 命令,查看 IO 占用 CPU 的时间片(即 iow):
在这里插入图片描述

因此,如果不能从其它方式去解决此问题(内核层的 IO 调度 和 CPU 调度机制),可以运用简单的方式:在写入文件的时候,限制写入速度,减缓 IO 占用率。

二、代码实现

例如,一个标准的拷贝文件的 Kotlin 方法如下:

originFile.inputStream().buffered().use { inputStream ->targetFile.outputStream().buffered().use { outputStream ->val buffer = ByteArray(1024)var bytesRead: Intwhile (inputStream.read(buffer).also { bytesRead = it } != -1) {outputStream.write(buffer, 0, bytesRead)}outputStream.flush()}
}

这个方法对 源文件 开启了 InputStream,并转换为 BufferInputStream,而对 目标文件 开启了 OutputStream,并转换为 BufferOutputStream,然后再从 InputStream 读取流,输出到 OutputStream,完成文件的读写。

而我们为了实现限制其写入速度,我们可以定义一个速率,例如每秒写入 20M,即每秒写入的字节数为 20 * 1024 * 1024 = 20, 971, 520 。在每次写入量达到 20M 的时候,检查一次写入这 20M 使用的时长,如果这个时长 < 1s ,则表示在这 1s 的时间里,写入的速率已经超过了 20M,需要等待一定时长,使其满足 1s 内只写入 20M 的需求。代码如下:

// 限制拷贝时的速率, 每秒最多拷贝的字节数
val MAX_COPY_SPEED = 20 * 1024 * 1024L// 记录已拷贝的文件大小
var copiedSize = 0L// 记录上次检查性能的时间 (用来计算拷贝速率 限制拷贝速率)
var lastCheckPerformanceTime = System.currentTimeMillis()
// 记录上次检查时 已拷贝的数据量
var lastCheckPerformanceSize = 0LoriginFile.inputStream().buffered(1024 * 1024).use { inputStream ->targetFile.outputStream().buffered().use { outputStream ->val buffer = ByteArray(DEFAULT_BUFFER_SIZE)var bytesRead: Intwhile (inputStream.read(buffer).also { bytesRead = it } != -1) {outputStream.write(buffer, 0, bytesRead)// 增加已拷贝文件的大小copiedSize += bytesRead// 计算拷贝速率 每满 MAX_COPY_SPEED 计算一次速率if (copiedSize - lastCheckPerformanceSize >= MAX_COPY_SPEED) {lastCheckPerformanceSize = copiedSizeval time = System.currentTimeMillis()// 计算写入 MAX_COPY_SPEED 字节数所使用的时间val deltaTime = time - lastCheckPerformanceTimelastCheckPerformanceTime = time// 如果速率大于 MAX_COPY_SPEED 则暂停 等待下次计算if (deltaTime < 1000) {// 延迟 1000 - deltaTime 使满足 1s 内只写入指定量delay(1000 - deltaTime)}}}outputStream.flush()}
}
http://www.dtcms.com/a/267853.html

相关文章:

  • java ThreadLocal源码分析
  • 深度学习6(多分类+交叉熵损失原理+手写数字识别案例TensorFlow)
  • 高效处理大体积Excel文件的Java技术方案解析
  • 安卓之service
  • QT 菜单栏设计使用方法
  • 基于AndServer的RPC架构:Android原生SO文件远程调用实战指南
  • Python 机器学习核心入门与实战进阶 Day 4 - 支持向量机(SVM)原理与分类实战
  • 深度学习图像分类数据集—蘑菇识别分类
  • plantuml用法总结
  • Java设计模式之行为型模式(策略模式)介绍与说明
  • 利用低空无人机影像进行树种实例分割
  • 深入解析Vue中v-model的双向绑定实现原理
  • 牛客周赛99
  • 关于 栈帧变化完整流程图(函数嵌套)
  • 大模型面试:RAG与Agent相关
  • 《Redis》集群
  • 【Note】《Kafka: The Definitive Guide》 第二章 Installing Kafka:Kafka 安装与运行
  • Redis--主从复制详解
  • 【Docker基础】Docker容器挂载方式深度解析:--volume与--mount参数对比
  • QT6 源(155)模型视图架构里的列表视图 QListView:接着学习成员函数,信号函数,附上本类的源代码带注释。
  • HCIA-网络地址转换(NAT)
  • CppCon 2018 学习:Woes of Scope Guards and Unique_Resource
  • 抖音小游戏(IAA)巨量引擎投放指南
  • [shadPS4] 内存管理 | 权限管理 |文件系统 | 挂载和句柄
  • 【BTC】数据结构
  • 7,TCP服务器
  • JavaScript基础语法之运算符和控制流
  • 李宏毅NLP-8-语音模型
  • 【管理学】组织纪律性与创新性的失衡导致的问题
  • Redis事务机制