如何科学的进行Android包体积优化

这篇文章会分享小厂如何做包体积优化相关主题,涉及内容包括:1) Android包体积优化的一种可能是比较标准的推进做法,2) 大致流程的心路历程和思考方式,3) 如何去总结和分享你们进行过的包体积优化项目。本文不仅仅是一篇分享,还是我个人比较喜欢的总结报告写法。

一、前言

移动 App 特别关注投放转化率指标,而 App 包体积是影响用户新增的重要因素,而 App 的包体积又是影响投放转化率的重要因素。

Google 2016 年公布的研究报告显示,包体积每上升 6MB 就会带来下载转化率降低 1%, 当包体积增大到 100MB 时就会有断崖式的下跌 。对于应用商店,普遍有一个流量自动下载的最大阈值,如 应用宝,下载的app超过100M,用流量下载时,会弹窗提示用户是否继续下载,这对下载转化率影响是比较大的。

现在流量虽然变得更廉价一点,但是用户的心理是不会变的,当 App 出现在应用市场的相同位置时,包体积越大,用户下载意愿可能越低。

而且包体积或直接或间接地影响着下载转化率、安装时间、运行内存、磁盘空间等重要指标,所以投入精力扫除积弊、发掘更深层次的体积优化项是十分必要的。

某手:

  • 1M = 一年kw级推广费

某条极速版:

  • Google 2016 年公布的研究报告显示,包体积每上升 6MB 就会带来下载转化率降低 1%,当包体积增大到 100MB 时就会有断崖式的下跌。
  • 通过插件化,将常规优化后达 120M+的包体积降到了 13M 左右,最小版本降至 4M,包体积缩小至原先的 3.33%。

某德:

  • 包体积大小,是俞xx直接拍的,就要求 x年x月x日 前削减到100M。

某淘:

  • 包大小做得比较“霸权”“独裁”,新业务超过 1M 要总裁审批,一般在平台组都卡掉了。

二、评估优化需求

在开展工作前,我们首先得先有两点判断:

  1. 是否需要进行优化
  2. 优化到多少算符合预期

那具体应该如何进行判断呢?有个比较简单的方法就是对标,找到对标对象进行对标。

对于小厂来说,一般对标对象有:

  1. 竞品App
  2. 业内人气App

基于对标对象,我们可以粗略的有如下判断:

  1. 如果我们App跟竞品App包体积差不多或略高,那就有必要进行包体积优化。
  2. 优化到跟业内人气App中包体积最小的那一档差不多即可。

上述判断还是基于用户视角,假如你的 用户需求 比较简单,好几个app都可以满足, 你会安装200M的产品,还是50M的产品。再有,假如用户在App商店无意间看到你们的App,有点兴趣体验体验,但是看到包体积是200M,他有多大概率会继续下载,换成50M呢?

三、包体积优化基本思想

我们在做包体积优化前,一定要定好我们的大方向,我们怎么优化,能做哪些,哪些可以现在做,哪些没必要现在做,

1. 抓各个环节

我们最终是要优化App的包体积,那么App包组成部分有哪些,我们针对每一个部分去研究如何减少其体积,就可以达到我们最终的效果。

2. 系统化方案先行,再来实操

优化Android包体积这个事情,有一定的探索性,但是很多内容或者说手段都是业内在广为流传的,既然如此,我们应该总结业内可优化手段,并逐一进行分析,研究是否适合你们App,是否需要应用到你们App。如果没有方案的埋头扎进去,往往会因为陷入细节,而丢失了全局视野。

3. 明确风险收益比及成本收益比

方案与方案之间是有区别的。如果一个方案能减少包体积2M,但是线上可能会崩溃,你会做吗? 如果一个方案能减少包体积2M,但是开发成本要一个月,你会做吗?

4. 明确指标以及形成一套监控防劣化体系

干任何一件以优化为目标的事情时,一定要明确优化的指标,我们要做App的包体积优化,那么我们的指标为:减少App安装包 apk 的大小。

当我们指标明确之后,我们还需要对现有指标进行监控,这样有两个好处:

  • 明确优化收益
  • 防止劣化

那我们就可以在某个关键的时间节点进行包体积的统计和上报,一般时间节点有:

  • App发版打包时(粒度更粗)
  • 开发分支有新的 commit 合入时(粒度更细)

两种粒度各有各的好处,但是目标是一样的:

  • 监控每次打包的包体积,可以行成指标曲线进行持续观察
  • 在包体积增加超出预期时进行及时报警

5. 把包体积这个指标刻在脑子里

自动化能发现已经发生的问题,但是把包体积这个指标刻在脑子里,能避免问题的发生。

四、自家App包体积一览

1. Android Apk结构

APK 主要由五个部分组成,分别是:

  • Dex:.class 文件处理后的产物,Android 系统的可执行文件
  • Resource:资源文件,主要包括 layout、drawable、animator,通过 R.XXX.id 引用
  • Assets:资源文件,通过 AssetManager 进行加载
  • Library:so 库存放目录
  • META-INF:APK 签名有关的信息

2. 你们Apk各个部分都长啥样,长多大?

这里选取示例App某个版本的安装包来做举例分析,下面是包结构图:

浅浅分析一波包内内容

五、优化方案草案

通过调研业内常规、非常规手段,以及结合你们App的包体积现状,可以提前对优化包体积做出比较详尽的可实现、低风险、高收益方案,注意这几个点非常重要:

  • 可实现 - 可实现可以简单理解为实现成本低,一般各种性能稳定性指标都是循序渐进的推进,所以往往一期优化时,选的实操方案都是实现成本比较低的,这样能相对快速的得到比较符合心里预期的优化效果。
  • 低风险 - 线上风险必须控制在可接受的程度,这里的风险不仅仅是说App运行的性能稳定性风险,还需要判断是否会增加线上问题排查的难度,当然还会有其他的我没提到的风险项。
  • 高收益 - 不解释

所以基于我们需要的是可实现、低风险、高收益的方案,我们可以基于上面我贴的APK案例,来大致预演可能会采用哪些方案:

1. 缩减动态化方案内置代码包、资源包

一般的小厂都会比较大量的采用如RN、H5等动态化方案,不可避免的App内就会有一堆内置文件,我们看到我们示例的App中,RN内置包占了整个包体积超过 30%。当出现这种情况时,可以针对内置代码包、资源包单独立子项去推进。

那么如何进行推进呢?有同学就会说了,业务方不让我把这些玩意儿从APK里面删掉,说影响他们打开页面速度,影响页面打开速度就会影响一级指标影响收入

这时为了说服业务方,我们就得拿出一些证据,用来证明内置包的全部移除或者部分移除并不会对业务产生影响,或者说影响足够小。那就可以采取如下一些推进步骤:

  • 明确全部内置包或者部分内置包不内置的影响,假如内置包是 RN 的页面bundle,那给业务方两个数据基本上就能够说明影响
    • 页面bundle现下比例,假如因为本地没有内置的bundle,打开页面需要同步进行等待下载完成才能加载的话,现场下载比例是个比较有说服力的数据。
    • 线上bundle更新耗时,我们可以统计用户启动App后的一段指定时间,90分位能下载多少个bundle,50分位能下载多少个,10分位、5分位能下载多少个,来告诉业务方,老用户、新用户、老用户新登录等各种场景,到达业务页面的时候,有多少比例的用户能完成bundle更新。
  • 明确什么样的资源需要内置,同样用RN页面bundle举例,假如App的首页就是RN页面,那这玩意儿就必须内置了,假如一个页面在犄角旮旯,日pv才不到100,那就完全可以不需要内置。
  • 给出内置资源名单
  • 拿着内置名单和上面明确的不内置影响统计,找业务方拉会, 这一步最好是从上往下进行推进,而不是同级推进

2. 分架构打包

分架构打包能减少libs文件夹体积,libs文件夹里会包含不同架构的 so 库集合。

首先我们最终apk包是要上传到应用商店的,应用商店得支持双包上传。答案确实是支持,且应用商店推荐双包上传。

Android 官方也是有相关的api支持分架构打包:

splits {// 基于不同的abi架构配置不同的apkabi {// 必须为true,打包才会为不同的abi生成不同的apkenable true// 默认情况下,包含了所有的ABI。// 所以使用reset()清空所有的ABI,再使用include指定我们想要生成的架构armeabi-v7a、arm-v8areset()// 逗号分隔列表的形式指定 Gradle 应针对哪些 ABI 生成 APK。只与 reset() 结合使用,以指定确切的 ABI 列表。include "armeabi-v7a", "arm64-v8a"// 是否生成通用的apk,也就是包含所有ABI的apk。如果设为 true,那么除了按 ABI 生成的 APK 之外,Gradle 还会生成一个通用 APK。universalApk true}}

这里需要注意的是,线上并不是所有的手机都支持 64位 的安装包,应用商店可以双包上传,线上灰度更新可以下发32位的安装包或者是 32/64 兼容包。

3. So 压缩

分架构打包是减少so的数量,so压缩是减少so的单个体积。

android:extractNativeLibs="true"

android:extractNativeLibs = true时,gradle打包时会对工程中的so库进行压缩,最终生成apk包的体积会减小。

但用户在手机端进行apk安装时,系统会对压缩后的so库进行解压,从而造成用户安装apk的时间变长。

若开发人员未对android:extractNativeLibs进行特殊配置,android:extractNativeLibs默认值:

  • minSdkVersion < 23 或 Android Gradle plugin < 3.6.0情况下,打包时 android:extractNativeLibs=true

  • minSdkVersion >= 23 并且 Android Gradle plugin >= 3.6.0情况下,打包时android:extractNativeLibs=false

4. 大so动态下发

我们能看到有些so库单个体积超大,放在apk里,就算能压缩,压缩后体积仍然很大,可能会占到 app体积超过 10%。针对这种情况,选择动态下发。

动态下发的so如何进行加载

我们采用ASM的方案,对代码中所有的 System.load、System.loadLibrary 进行hook,进入到我们自己的逻辑,这样我们就可以走下面流程:

  1. 下载so库
  2. 解压so库
  3. 校验so库
  4. 加载so库

这里需要注意的一点就是,当动态下发的so没有下载、解压、校验、加载完之前,如果用户进入到了相关的业务场景,必须有兜底机制。比如在样例App的场景中,使用了 opencv 库来做图片的二维码识别,当so没下载下来时,要识别二维码就会被兜底到 zxing。

而且由于我们有较好的Hook框架的封装,所以我们需要hook时,仅仅需要进行配置即可:

5. 大文件压缩优化,对内置的未压缩大文件进行,压缩文件用高压缩率的压缩算法

假如apk里有内置的大文件,可以通过对其进行压缩从而减少包体积,压缩时可以选用高压缩率的算法。

6. 代码优化

  • 去除无用代码、资源

去除无用代码我们可以用官方的Lint检查工具

  • 去除无用三方库

  • 减少ENUM的使用

每减少一个ENUM可以减少大约1.0到1.4 KB的大小,假如有10000个枚举对象,那不就减少了14M?美滋滋啊,但实际上具体还是要看项目代码情况来考虑,毕竟不是所有的项目里都有 10000 个枚举。

7. 资源优化

  • 无用资源文件清理

去除无用资源文件可以通过lint工具来做,也可以通过微信开源的 ApkChecker来完成。

图片压缩、转webp

图片压缩可以使用TinyPng,AndroidStudio也有相关插件,官方术语就是:

使用智能的无损压缩技术来减少图片文件的大小,通过智能的选择颜色的数量,减少存储的字节,但是效果基本是和压缩前一样的。

图片着色器

相同图片只是颜色不同的话,完全可以只放一个图片,在内存里操作 Drawable,完成颜色替换。

图片动态下发

如果本地有大图,且使用要求为未压缩,或者压缩之后仍然很大,可以适当的选择动态下载该图。

resources.arsc资源混淆

resources.arsc这个文件是存放在APK包中的,他是由AAPT工具在打包过程中生成的,他本身是一个资源的索引表,里面维护者资源ID、Name、Path或者Value的对应关系,AssetManager通过这个索引表,就可以通过资源的ID找到这个资源对应的文件或者数据。

通过对apk 中的resources.arsc进行内容修改,来对apk进行深度压缩。这里可以采用微信的AndResGuard方案。

8. 三方库优化

移除无用三方库

移除无用三方库需要人肉扫描 build.gradle 文件,一个一个的去检查依赖的三方库是否被我们代码所使用。

功能重复的三方库整合

特别常见的case,RN 用的图片加载库是 Fresco,客户端用的图片加载库是 Glide,他们都是用来加载图片,可以通过删除一个库,让项目依赖的库少一个。

  • 修改三方库源码,不需要的代码进行剔除

XUtils是一个工具大杂烩,但是假如我只用它来加载图片,其他工具是不是就完全无用,可以进行剔除。

9. 去除 DebugItem 包含的 debug信息与行号信息

在讲解什么是 deubg 信息与行号信息之前,我们需要先了解 Dex 的一些知识。

我们都知道,JVM 运行时加载的是 .class 文件,而 Android 为了使包大小更加紧凑、运行时更加高效就发明了 Dalvik 和 ART 虚拟机,两种虚拟机运行的都是 .dex 文件,当然 ART 虚拟机还可以同时运行 oat 文件。

所以 Dex 文件里的信息内容和 Class 文件包含的信息是一样的,不同的是 Dex 文件对 Class 中的信息做了去重,一个 Dex 包含了很多的 Class 文件,并且在结构上有比较大的差异,Class 是流式的结构,Dex 是分区结构,Dex 内部的各个区块间通过 offset 来进行索引。

为了在应用出现问题时,我们能在调试的时候去显示相应的调试信息或者上报 crash 或者主动获取调用堆栈的时候能通过 debugItem 来获取对应的行号,我们都会在混淆配置中加上下面的规则:

-keepattributes SourceFile, LineNumberTable

这样就会保留 Dex 中的 debug 与行号信息。根据 Google 官方的数据,debugItem 一般占 Dex 的比例有 5% 左右

10. ReDex

ReDex 是 Facebook 开发的一个 Android 字节码的优化工具。它提供了 .dex 文件的读写和分析框架,并提供一组优化策略来提升字节码。官方提供预期优化效果:对dex文件优化为 8%

11. R 文件瘦身

当 Android 应用程序被编译,会自动生成一个 R 类,其中包含了所有 res/ 目录下资源的 ID。包括布局文件layout,资源文件,图片(values下所有文件)等。在写java代码需要用这些资源的时候,你可以使用 R 类,通过子类+资源名或者直接使用资源 ID 来访问资源。R.java文件是活动的Java文件,如MainActivity.java的和资源如strings.xml之间的胶水

通过R文件常量内联,达到R文件瘦身的效果。

12. 可能的更多方案

除了我上面列到的一些,市面上还有一些其他的方案,有复杂的有不复杂的,有收益高的有收益低的,大家可以在掘金上搜索Android包体积优化,就能搜到大部分了,当然,在大厂里,还会有很多很极致的方案,比如:

  • 去掉kotlin生成的许多模板代码、判空代码
  • 去除布局文件里不需要的冗余内容

思想是这么个思想,大家在实操的时候,思路就是先调研方案,调研完成之后再选型。

六、基于风险收益比及成本收益比敲定最终实现方案

这一步的重点是:明确风险收益比及成本收益比

方案与方案之间是有区别的。

  • 如果一个方案能减少包体积2M,但是线上可能会崩溃,你会做吗?
  • 如果一个方案能减少包体积2M,但是开发成本要一个月,你会做吗?

这里我们在示例App的基础上,对每个手段进行仔细分析,包括:

  1. 预期效果

  2. 成本

  3. 风险

就这样,当我们制定完成我们的目标方案之后,就可以放手干了。

手段预期效果成本是否要做进度备注
重点优化项
- 缩减RN 内置bundle预期效果:177.43M -> 114.43MRN 内置bundle缩减,xxxx版本带上
- 分架构打包,64位、32位分开打包预期效果:32位:117.43M -> 71.9M 64位:117.43M -> 87.6Mxxxx
- so压缩方案预期效果:32位:71.9M -> 55.5M 64位:87.6M -> 58.3Mxxxx
- 大so文件动态下发预期效果:32位:55.5M -> 50.7M 64位:58.3M -> 51.7Mxxxx
大文件优化
- zip优化,对内置的压缩文件替换压缩算法预期针对 assets 文件针对不同类型文件选取不同高压缩率算法
代码优化 (dex文件为 15.6M)
- 去除无用代码Android Lintxxx
- 减少ENUM的使用全部代码 enum类 一共60个,就算全删了也只是减少 84kxxx每减少一个ENUM可以减少大约1.0到1.4 KB的大小
资源优化 (目前res目录大小为 6.3M,emoji目录大小为 770k)
- 无用资源文件清理Android Lintxxx用ApkChecker再跑一次
- 图片压缩、转webpTinyPngxxx
- 图片着色器xxx
- 图片动态下发主要是针对比较大的图,实际上经过TinyPng 压缩后,图片大小已经大大减小xxx
- resources.arsc资源混淆AndResGuard两年不维护,花了一小时没完全跑起来,但看到了大致优化效果,1.3M -> 920kgithub.com/shwenzhang/…
三方库优化 (dex文件为 15.6M)
- 移除无用三方库检查一下
- 移除无用三方so库
- 功能重复三方库整合
- 修改三方库源码,不需要的代码进行剔除

七、确定优化效果

当我们进行了一系列的或大或小的改动之后,如何描述最终优化效果?给两张对比图不就行了,无图言X。

八、总结

大家在进行一些有挑战性或者是比较有意义的项目时,其实可以多进行总结,总结的好处有什么我就不多解释了,懂的都懂哈。

比如我们这里可以装模作样的这样总结一下:

做的好的方面
  1. 足够系统化
  2. 前置调研足够充分
  3. 风险、收益、成本考虑足够充分
  4. 各方面沟通足够充分
  5. 优化决心足够大
也可以告诉自己及读者几句话
  1. 这是一个系统的需要持续去投入人力的事情,万万不可有了一定结果之后放松警惕

  2. 别人能做的,我们也能做,只要有足够的决心去做

  3. 做事不能太讲究所谓的方法论,不然会掉入陷阱,但是确实要讲究方法论

  4. 有些事情你做好了,可能仅仅是因为做这个事情的人是你,如果是别人来做,也能将这件事情做好

九、展望

一般来说,进行总结之后,都得来一些展望,给未来的自己挖点坑,给总结的读者画点饼。比如我们这里就可以这样继续装模作样的展望一下:

上面已经反复提及了,当前这一期的优化工作,重点考量的指标是风险收益比及成本收益比,所以一些极致的或者成本收益比较高的优化手段并没有被采用,所以后续还是有很多事情可以深入的干下去。

  1. resources.arsc资源混淆

  2. 去除 DebugItem 包含的 debug信息与行号信息

  3. ReDex

  4. R 文件瘦身

  5. So unwind 优化

  6. kotlin相关优化

十、真正的总结

这里我就发散性的随便总结下吧。。。也不深入纠结了。

  1. 包体积优化是个庞大的工程项目,不仅仅需要优化,还需要防劣化,优化过程中还会涉及到业务冲突,说白了就是某些东西从APK包中移除了,或多或少会有些影响,还需要去跟业务方达成意见一致。
  2. 大家不管在做什么优化课题时,最好是分步骤分工期的去进行,不要一口吃成胖子,如果上来就追求完全极致的优化效果,往往会带来两个负面风险:1) 优化工期拉长,时间成本成倍增加,2)可能影响线上App或者线下各种工具的运行稳定性。
  3. 系统化的调研、成本 + 风险 + 收益的总和考虑非常重要,任何优化项目开始进行或者进行过程中,都需要牢牢的印在脑子里,每日三省你身。
  4. 遇到困难不要畏惧,各种优化项目往往会遇到很多阻力,比如方案实现太难、业务沟通太难等等,一块石头硬磕磕不动的时候换个方向磕,换方向也磕不动那就换块石头磕,比如假设业务方沟通不动,那就换个角度,把你和业务方放在同一角色上,给业务方找收益或者。
  5. 做的项目是啥或者说研究的方向是啥其实不是最重要的,我们这种普通程序员更重要的是解决问题的能力,因为你们做的事情,换个人用同样的时间成本或者更多的时间成本,往往也能做好,所以是你做好的这件事情其实没那么重要,更重要的是遇到其他问题或者有其他的疑难杂症和系统性问题时,知道你一定能做好。

Android 学习笔录

Android 性能优化篇:https://qr18.cn/FVlo89
Android Framework底层原理篇:https://qr18.cn/AQpN4J
Android 车载篇:https://qr18.cn/F05ZCM
Android 逆向安全学习笔记:https://qr18.cn/CQ5TcL
Android 音视频篇:https://qr18.cn/Ei3VPD
Jetpack全家桶篇(内含Compose):https://qr18.cn/A0gajp
OkHttp 源码解析笔记:https://qr18.cn/Cw0pBD
Kotlin 篇:https://qr18.cn/CdjtAF
Gradle 篇:https://qr18.cn/DzrmMB
Flutter 篇:https://qr18.cn/DIvKma
Android 八大知识体:https://qr18.cn/CyxarU
Android 核心笔记:https://qr21.cn/CaZQLo
Android 往年面试题锦:https://qr18.cn/CKV8OZ
2023年最新Android 面试题集:https://qr18.cn/CgxrRy
Android 车载开发岗位面试习题:https://qr18.cn/FTlyCJ
音视频面试题锦:https://qr18.cn/AcV6Ap

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/153036.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深入探索 PaddlePaddle 中的计算图

**引言** 计算图是深度学习平台 PaddlePaddle 的核心组件之一&#xff0c;它提供了一种图形化的方式来表示和执行深度学习模型。通过了解和理解 PaddlePaddle 中的计算图&#xff0c;我们可以更好地理解深度学习的工作原理&#xff0c;并且能够更加灵活和高效地构建和训练复杂…

stable diffusion十七种controlnet详细使用方法总结

个人网站&#xff1a;https://tianfeng.space 前言 最近不知道发点什么&#xff0c;做个controlnet 使用方法总结好了&#xff0c;如果你们对所有controlnet用法&#xff0c;可能了解但是有点模糊&#xff0c;希望能对你们有用。 一、SD controlnet 我统一下其他参数&#…

PLC梯形图实操——风扇正反转

文章目录 1.项目内创建函数块&#xff08;FB&#xff09;2.项目内创建数据块&#xff08;DB&#xff09;2.1去除优化块访问2.2去除优化块的访问后对数据块进行编译 3.在函数块&#xff08;FB&#xff09;内实现正转反转的自锁与互锁3.1在函数块内实现电机正反转的梯形图 4.主函…

2 Redis的高级数据结构

1、Bitmaps 首先&#xff0c;最经典的应用场景就是用户日活的统计&#xff0c;比如说签到等。 字段串&#xff1a;“dbydc”&#xff0c;根据对应的ASCII表&#xff0c;最后可以得到对应的二进制&#xff0c;如图所示 一个字符占8位&#xff08;bit&#xff09;&#xff0c;…

HTTP1.1升级HTTP2.0

HTTP1.1升级HTTP2.0 一&#xff0c;前言介绍 1.为什么要升级http2.0 HTTP2.0相比于HTTP1.x有以下几个优点&#xff1a; 二进制分帧&#xff1a;HTTP2.0将所有传输的信息分割为更小的消息和帧&#xff0c;并采用二进制格式对它们进行编码&#xff0c;这样可以更好地对数据进行…

【Rust】快速教程——模块mod与跨文件

前言 道尊&#xff1a;没有办法&#xff0c;你的法力已经消失&#xff0c;我的法力所剩无几&#xff0c;除非咱们重新修行&#xff0c;在这个世界里取得更多法力之后&#xff0c;或许有办法下降。——《拔魔》 \;\\\;\\\; 目录 前言跨文件mod多文件mod 跨文件mod //my_mod.rs…

单机版-redis(手动部署)

单机版-redis部署 部署模式:单机版-redis部署 Redis版本&#xff1a;redis-4.0.1 部署redis方式&#xff1a;手动部署 解决GCC问题 linux升级gcc版本详细教程_gcc升级-CSDN博客 在完成第三步时已完成配置&#xff0c;后续为操作命令以及注意事项&#xff1b; 在进行操作数…

【数据结构】——双链表(增删查改)

目录 前言&#xff1a; 一&#xff1a;双链表的定义 ​编辑 二&#xff1a;双向链表的实现 2.1&#xff1a;链表的构造 2.2&#xff1a;创建头节点 2.3&#xff1a;创建节点 2.4&#xff1a;链表的尾插 2.5&#xff1a;链表的打印 2.6&#xff1a;链表的尾删 2.7&a…

[计算机网络]网络层概述

呼,写了这么久终于重新开始啦! 自己落下了太多东西了.....是时候应该重新拾掇起来了. 关于后面的代码项目,我的想法是vilas.js仍然使用js来进行编写,但是后续其他的项目会开始尝试使用ts来进行书写了. 就算是前端也需要点规范吧..... 0.写在前面 这篇文章要和大家道个歉,首…

2023年中职“网络安全“—Linux系统渗透提权③

2023年中职"网络安全"—Linux系统渗透提权③ Linux系统渗透提权任务环境说明&#xff1a;1. 使用渗透机对服务器信息收集&#xff0c;并将服务器中SSH服务端口号作为flag提交&#xff1b;2. 使用渗透机对服务器信息收集&#xff0c;并将服务器中主机名称作为flag提交…

​软考-高级-系统架构设计师教程(清华第2版)【第13章 层次式架构设计理论与实践(P466~495)-思维导图】​

软考-高级-系统架构设计师教程&#xff08;清华第2版&#xff09;【第13章 层次式架构设计理论与实践&#xff08;P466~495&#xff09;-思维导图】 课本里章节里所有蓝色字体的思维导图

Figma 插件学习(一)

一.插件介绍 插件在文件中运行&#xff0c;执行一个或多个用户操作&#xff0c;并允许用户自定义其体验或创建更高效的工作流程。 插件通过专用插件API与Figma的编辑器交互。还可以利用外部Web API。 1.插件API 插件API支持读写功能&#xff0c;允许查看、创建和修改文件的…

打破传统束缚,释放服务潜能:本地生活服务商聚合系统引领行业新风向!

本地生活服务商聚合系统是一种集合多平台、多项目的创新型服务系统&#xff0c;它打破了传统服务商系统的一对一限制&#xff0c;为创业者和运营商带来了诸多优势。小多将深入探讨本地生活服务商聚合系统的优势。 随着互联网的快速发展&#xff0c;本地生活服务也迎来了蓬勃的发…

el-tree 与table表格联动

html部分 <div class"org-left"><el-input v-model"filterText" placeholder"" size"default" /><el-tree ref"treeRef" class"filter-tree" :data"treeData" :props"defaultProp…

彻底删除的文件如何恢复?分享正确方法!

“求救&#xff01;我在清理电脑的过程中&#xff0c;把一些比较久远的文件彻底删除了。但是我突然想起好像有些非常重要的数据也一同被删掉了&#xff0c;这可怎么办&#xff1f;有方法恢复彻底删除的文件么&#xff1f;” 在日常使用电脑的过程中&#xff0c;很多用户或许都会…

机器学习-笔记

绪论 参考期刊 ICCV 偏向视觉CVPR 偏向MLIAAA AI原理ICML 参考链接 CSDN 机器学习知识点全面总结 课堂内容学习-0912-N1 对于特征提取&#xff0c;简而言之就是同类聚得紧&#xff0c;异类分得开&#xff1b;   detection研究的是样本二分类问题&#xff0c;即分为正样本…

Rockdb简介

背景 最近在使用flink的过程中&#xff0c;由于要存储的状态很大&#xff0c;所以使用到了rockdb作为flink的后端存储&#xff0c;本文就来简单看下rockdb的架构设计 Rockdb设计 Rockdb采用了LSM的结构&#xff0c;它和hbase很像&#xff0c;不过严格的说&#xff0c;基于LS…

设计模式-行为型模式-责任链模式

一、什么是责任链模式 责任链模式是一种设计模式。在责任链模式里&#xff0c;很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递&#xff0c;直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求&…

VS2019编译安装GDAL(C++)程序库

一、GDAL简介 GDAL&#xff0c;全称Geospatial Data Abstraction Library&#xff0c;即地理空间数据抽象库&#xff0c;是一个在X/MIT许可协议下读写空间数据的开源库&#xff0c;可以通过命令行工具来进行数据的转换和处理。而在调用中我们常用的OGR&#xff08;OpenGIS Simp…

MATLAB中std函数用法

目录 语法 说明 示例 矩阵列的标准差 三维数组的标准差 指定标准差权重 矩阵行的标准差 数组页的标准差 排除缺失值的标准差 标准差和均值 标准差 std函数的功能是得到标准差。 语法 S std(A) S std(A,w) S std(A,w,"all") S std(A,w,dim) S std(A…