开机时间分析

news2024/10/7 20:29:01

一、 开机各个阶段分析

1、Bootloader 阶段

Bootloader 阶段 该阶段分为(preloader 和Ik 阶段)

从按电源键振动到 kernel 开始启动,这部分高通平台暂无好的方法确认时间,可以从总时间推算大概时间。MTK 项目可以从bootprof 确认

2、kernel 阶段

1.Linux boot -> init first stage started!

主要耗时为电池驱动以及 TP 初始化部分

MTK 项目可从bootprof 中看到各驱动初始化时间,高通平台暂无法确认

2.init first stage started! -> boot_progress_stat

系统进入用户空间,标志着kemel 启动完成

主要是内核访问根文件系统来启动init 进程,包括 apexd、加载 sepolicy (Coldboot)、挂载各个分区

kerne_log:

若以上阶段有差异可联系测试单独给bsp提单确认

3、Android 阶段

在eventlog中搜索boot_progress |sf_stop| wm_boot_animation_done关键字分析日志,粒度较大,只能定位出大概的耗时流程,之后还需分析流程内部具体的耗时情况。开机各流程内部也有相应的日志,可以进行更加细致的分析。

每个阶段如下表所示:

阶段

描述

boot_progress_start

系统进入用户空间,标志着kernel启动完成

boot_progress_preload_start

Zygote启动

boot_progress_preload_end

Zygote结束

boot_progress_system_run

SystemServer ready,开始启动Android系统服务

boot_progress_pms_start

PMS开始扫描安装的应用

boot_progress_pms_system_scan_start

PMS先行扫描/system目录下的安装包

boot_progress_pms_data_scan_start

PMS扫描/data目录下的安装包

boot_progress_pms_scan_end

PMS扫描结束

boot_progress_pms_ready

PMS就绪

boot_progress_ams_ready

AMS就绪

boot_progress_enable_screen

AMS启动完成后开始激活屏幕,从此以后屏幕才能响应用户的触摸,它在WindowManagerService发出退出开机动画的时间节点之前

sf_stop_bootanim

SF设置service.bootanim.exit属性值为1,标志系统要结束开机动画了

wm_boot_animation_done

开机动画结束,这一步用户能直观感受到开机结束

开机流程Trace如下图所示:

1.boot_progress_start

系统进入用户空间,标志着kernel启动完成

/frameworks/base/core/jni/AndroidRuntime.cpp

void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
    for (size_t i = 0; i < options.size(); ++i) {
        if (options[i] == startSystemServer) {
            primary_zygote = true;
           /* track our progress through the boot sequence */
           const int LOG_BOOT_PROGRESS_START = 3000;
           LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START,  ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
        }
    }
}

2.boot_progress_preload_start

Zygote启动

/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

public static void main(String[] argv){
    if(!enableLazyPreload){
        bootTimingsTraceLog.traceBegin("ZygotePreload");
        EventLog.writeEvent(BOOT_PROGRESS_PRELOAD_START, SystemClock.uptimeMillis());
        preload(bootTimingsTraceLog);
        EventLog.writeEvent(BOOT_PROGRESS_PRELOAD_END, SystemClock.uptimeMillis());
        bootTimingsTraceLog.traceEnd();
    }
}

trace

3.boot_progress_system_run

SystemServer ready,开始启动Android系统服务,如PMS、AMS等

/frameworks/base/services/java/com/android/server/SystemServer.java

private void run() {
   Slog.i(TAG, "Entered the Android system server!");
   final long uptimeMillis = SystemClock.elapsedRealtime();
   EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, uptimeMillis);
   if (!mRuntimeRestart){
            FrameworkStatsLog.write(FrameworkStatsLog.BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
FrameworkStatsLog.BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__SYSTEM_SERVER_INIT_START,uptimeMillis);
      }
    }

trace

4.boot_progress_pms_start

PMS开始扫描安装的应用

/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

public PackageManagerService(Injector injector, boolean onlyCore, boolean factoryTest) {
    LockGuard.installLock(mLock, LockGuard.INDEX_PACKAGES);
    EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,SystemClock.uptimeMillis()
    );
}

一般情况下该阶段耗时差异不大 50ms 之内若耗时差异较大

1请确认 BootAnimation 进程是否跑小核心详情见<开机时间checklist>

2耗时主要差异在 read user settings

trace

5.boot_progress_pms_system_scan_start

PMS先行扫描/system目录下的安装包

/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

public PackageManagerService(Injector injector, boolean onlyCore, boolean factoryTest) {
   long startTime = SystemClock.uptimeMillis();
   EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START, startTime);
}

6.boot_progress_pms_data_scan_start

PMS扫描/data目录下的安装包

/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

public PackageManagerService(Injector injector, boolean onlyCore, boolean factoryTest) {
        final long systemScanTime = SystemClock.uptimeMillis() - startTime;
        final int systemPackagesCount = mPackages.size();
        Slog.i(TAG, "Finished scanning system apps. Time: " + systemScanTime
                    + " ms, packageCount: " + systemPackagesCount
                    + " , timePerPackage: "
                    + (systemPackagesCount == 0 ? 0 : systemScanTime / systemPackagesCount)
                    + " , cached: " + cachedSystemApps);
        if (mIsUpgrade && systemPackagesCount > 0) {
            FrameworkStatsLog.write(FrameworkStatsLog.BOOT_TIME_EVENT_DURATION_REPORTED,                
BOOT_TIME_EVENT_DURATION__EVENT__OTA_PACKAGE_MANAGER_SYSTEM_APP_AVG_SCAN_TIME,
     systemScanTime / systemPackagesCount);
            }
            if (!mOnlyCore) {
            EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
            SystemClock.uptimeMillis());
            scanDirTracedLI(sAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0,
                        packageParser, executorService);
            }
}

7.boot_progress_pms_scan_end

PMS扫描结束

/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

该阶段差异小,可忽略

 public PackageManagerService(Injector injector, boolean onlyCore, boolean factoryTest) {
        mPackageUsage.read(mSettings.mPackages);
        mCompilerStats.read();
        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
                    SystemClock.uptimeMillis());
            Slog.i(TAG, "Time to scan packages: "
                    + ((SystemClock.uptimeMillis()-startTime)/1000f)
                    + " seconds");
}

8.boot_progress_pms_ready

PMS就绪

/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

 public PackageManagerService(Injector injector, boolean onlyCore, boolean factoryTest) {
        t.traceBegin("write settings");
        mSettings.writeLPr();
        t.traceEnd();
        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY, SystemClock.uptimeMillis());
    }

startWifi R/Q差异,verifyclass比Q多

9.boot_progress_ams_ready

AMS就绪

/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

public void systemReady(final Runnable goingCallback, @NonNull TimingsTraceAndSlog t) {
        t.traceEnd();
        EventLog.writeBootProgressAmsReady(SystemClock.uptimeMillis());
    }

trace

10.boot_progress_enable_screen

AMS启动完成后开始激活屏幕,从此以后屏幕才能响应用户的触摸,它在WindowManagerService发出退出开机动画的时间节点之前

/frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java

 @Override
public void enableScreenAfterBoot(boolean booted) {
        writeBootProgressEnableScreen(SystemClock.uptimeMillis());
        mWindowManager.enableScreenAfterBoot();
        synchronized (mGlobalLock) {
            updateEventDispatchingLocked(booted);
        }
 }

11.sf_stop_bootanim

SF设置service.bootanim.exit属性值为1,标志系统要结束开机动画了

/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp

void SurfaceFlinger::bootFinished()
{
         property_set("service.bootanim.exit", "1");
         LOG_EVENT_LONG(LOGTAG_SF_STOP_BOOTANIM, ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
}

12.wm_boot_animation_done

开机动画结束,这一步用户能直观感受到开机结束

/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java

private void performEnableScreen() {
        EventLogTags.writeWmBootAnimationDone(SystemClock.uptimeMillis());
        Trace.asyncTraceEnd(TRACE_TAG_WINDOW_MANAGER,   "Stop bootanim");
}

可以将测试机与对比机抓取的此log数据制作成表格,制作成折线图,可以更加直观的观察到耗时异常的流程。

二、开机日志抓取

不同厂商可能暗码进入MTKLog的方式不同,打开MTKLog之后,重启手机,等开机后关闭Log

1、抓取流程:

MTKLog 拨号盘输入*#*#9646633#*#*-->EngineerMode-->log and Debugging-->DebugLoggerUI-->打开mobilelog-->重启-->停止抓取-->拉取adb pull /data/debuglogger

2、分析开机日志

Android的log系统是独立于Linux内核log系统的. Android系统把Log分为了四类,不同的类别记录不同的Log信息,默认通过logcat抓取的是main信息,开机日志主要看event.log跟kernel.log:

Log名称

作用

获取命令

system.log

低级别的系统调试Log信息,包含CPU信息,大量系统服务输出的信息

adb logcat –b system

main.log

主要的Log信息,大部分应用级别的Log信息都在这里

adb logcat –b main

event.log

系统事件相关的Log信息,包含AMS与WMS输出的应用程序声明周期信息

adb logcat –b event

kernel.log

包含kernel打出的信息,LowMemoryKiller杀进程、内存碎片化或内存不足,mmc驱动异常都可以在这里找到。

mtk log抓取

3、日志地址

抓取成功后有个boot_normal文件夹,开机过程跟开机结束后Log是分开的,在boot过程可以看到里面有相应过程的Log,如下所示:

1.APLog_2023_0814_135856__4

2.boot__normal

4、查看是否第一次开机

persist.sys.device_provisioned开机向导是否完成

persist.sys.device_first_boot是否第一次开机

三、开机trace抓取

1、MTK 平台

mtk 平台抓取开机 trace 可以不改代码,只需要 user root 版本即可

抓取非首次开机信息,需要 root 权限

1. 打开 google systrace: adb shell setprop persist.traced.enable 1

2.打开 mtk systrace工具设置: adb shell setprop persist.vendor.boot_trace 1

3.联网对时,普通重启两次,再打开 开机 log(#80#-其它-重启)

4.锁屏出现后,adb shell atrace --async_stop -z -c -o /data/local/tmp/boot_trace,抓取trace

5.adb pull /data/local/tmp/boot_trace,关闭 log,导出log(/storage/ermulated/0/Android/data/com.oplus.logkit/files/Log 目录下对应时间1og)

注意:需要抓取init阶段的 trace需要修改对应项目的代码修改完代码跟高通抓取一样,需要验证代码之类的

打开抓取的开机trace如下所示:

如以上方式抓取不了,则需要在代码中修改:

2、代码修改

在 frameworks/native/cmds/atrace/atrace.rc 中,更改以下行:

write /sys/kernel/debug/tracing/tracing_on 0
write /sys/kernel/tracing/tracing_on 0

更改为:

#write /sys/kernel/debug/tracing/tracing_on 0
#write /sys/kernel/tracing/tracing_on 0

这将启用跟踪功能(默认处于停用状态)。

在 device.mk 文件中,添加以下行:

PRODUCT_PROPERTY_OVERRIDES +=    debug.atrace.tags.enableflags=802922
PRODUCT_PROPERTY_OVERRIDES +=    persist.traced.enable=0

在设备 BoardConfig.mk 文件中,添加以下行:

BOARD_KERNEL_CMDLINE := ... trace_buf_size=64M trace_event=sched_wakeup,sched_switch,sched_blocked_reason,sched_cpu_hotplug

如果是详细的 I/O 分析,还要添加块以及 ext4 和 f2fs。

在设备专属 init.rc 文件中,添加以下行:

on property:sys.boot_completed=1          // This stops tracing on boot complete
write /d/tracing/tracing_on 0
write /d/tracing/events/ext4/enable 0
write /d/tracing/events/f2fs/enable 0
write /d/tracing/events/block/enable 0

在设备启动后,提取跟踪记录:

adb root && adb shell atrace --async_stop -z -c -o /data/local/tmp/boot_trace
adb pull /data/local/tmp/boot_trace
$ANDROID_BUILD_TOP/external/chromium-trace/systrace.py --from-file=boot_trace

四、 开机速度优化实践

在Android S升级Android T的过程中,同一个项目的手机,在升级Android T之后,比之前的开机时间大概要多18秒左右。
首先在手机开机之后,查看boot_progress相关日志如下

07-15 04:13:35.244 I/boot_progress_start( 1059): 4040
07-15 04:13:35.934 I/boot_progress_preload_start( 1059): 4730
07-15 04:13:37.255 I/boot_progress_preload_end( 1059): 6051
07-15 04:13:37.636 I/boot_progress_system_run( 2221): 6432
07-15 04:13:38.260 I/boot_progress_pms_start( 2221): 7056
07-15 04:13:38.473 I/boot_progress_pms_system_scan_start( 2221): 7269
07-15 04:13:38.797 I/boot_progress_pms_data_scan_start( 2221): 7593
07-15 04:13:38.803 I/boot_progress_pms_scan_end( 2221): 7599
07-15 04:13:38.894 I/boot_progress_pms_ready( 2221): 7690
07-15 04:13:58.006 I/boot_progress_ams_ready( 2221): 26802
07-15 04:13:59.164 I/boot_progress_enable_screen( 2221): 27960

发现,在boot_progress_pms_ready到boot_progress_ams_ready之间,耗时近20秒,严重超时。
确定了大体的耗时异常点之后,我们抓取boottrace再进行进一步的分析。
由于PMS和AMS服务军运行再SystemServer进程当中,所以我们重点关注SystemServer进程的运行情况。

查看trace文件发现,主要是因为在启动AudioService的时候耗时较长。startService相关的日志也表明了这一点。

可见,启动AudioService耗时15.5秒左右。通过在AudioService相关的代码里面添加log,最终定位到为AudioService驱动在Android T上的问题。转交Audio模块处理之后,开机时间正常。

谷歌官方开机优化资料

https://source.android.com/devices/tech/perf/boot-times

五、开机时间拆解澄清

1、平台信息

项目信息

测试机

对比机1

对比机2

Android版本

13

12

13

硬件平台

mt6769

mt6769mt6769

内存

4+128

4+128

4+128

网络制式

LTE

WIFI

LTE

2、测试差异

测试机

对比机1

差值

开机时间

25.294s

26.243s

-1s

测试机

对比机2

差值

开机时间

23.57s

23.97s

-0.4s

3、开机各阶段时间拆解

prloader->kernel启动阶段

测试机(ms)

对比机1(ms)

差值(ms)

prloader

1173

1099

74

bl2_ext

1233

1041

192

lk

1556

1555

1

阶段

测试机(ms)

对比机1(ms)

差值(ms)

boot_progress_start

7504

7135

1601

1347

254

boot_progress_preload_start

9105

8482

1756

1597

159

boot_progress_preload_end

10861

10079

832

1904

-1072

boot_progress_system_run

11693

11983

1422

938

484

boot_progress_pms_start

13115

12921

322

280

42

boot_progress_pms_system_scan_start

13437

13201

702

886

-184

boot_progress_pms_data_scan_start

14139

14087

113

268

-155

boot_progress_pms_scan_end

14252

14355

181

227

--46

boot_progress_pms_ready

1443

14582

2484

2597

-113

boot_progress_ams_ready

16917

17179

3104

4268

-1164

boot_progress_enable_screen

20021

21447

2545

2214

331

sf_stop_bootanim

22566

23661

-1095

对boot_progress_system_run->boot_progress_pms_start各阶段进一步拆解,各阶段耗时无异常

从拆解表查看,各阶段耗时无异常,Android13相比Android12,Preload classes较多,开机多耗时400ms左右

4、结论:

从分解结果看,测试机优于对比机,各阶段耗时正常,因为平台能力,达不到标准,予以澄清说明。

优化措施汇总:

1.解决开机时mtkcam-devicemgr:initialze一直在后台运行影响开机时间

2.优化lcd初始化时延

六、总结

1.先对开机时间进行拆解,然后根据差异大的过程进行拆解分析

2.MTK平台可以直接看 bootprof文件,查看整个开机时间以及对应做的事件

3.如果是preloader、lk、kernel阶段的耗时需要跟BSP确认

4.折解开机 log在event和 kemel里面获取对应时间

5.可以在Log里面搜索一些关键词(took duration)因为 Android是多进程有些in background即使消耗时间也可能不会影响开机时间

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

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

相关文章

day18 内部类、包、垃圾回收机制

匿名内部类 // Animal a new Animal(){ // Override // public void eat() { // System.out.println("动物在吃饭"); // } // }; abstract class Animal{ public abstract void eat(); }

git 配置网络代理

提高 git 访问 github 速度 网络代理前提: 请开启代理&#xff08;梯子&#xff09;检查代理端口&#xff08;可能会有所不同&#xff09; 文章目录 1. git 配置参数列表命令&#xff1a;2. git 添加 http 代理3. git 取消 http 代理 1. git 配置参数列表命令&#xff1a; gi…

【AI】《动手学-深度学习-PyTorch版》笔记(十八):卷积神经网络模型

AI学习目录汇总 1、LeNet 1.1 介绍 发布时间:1989年 模型目的:识别手写数字 1.2 网络结构 1.3 定义模型 1.3.1 相关函数原型 1)nn.Conv2d:卷积层 torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, paddin

集群、负载均衡集群、高可用集群简介,LVS模式和haproxy/nginx模式拓扑介绍

一.集群的定义 1.定义 2.分类 &#xff08;1&#xff09;负载均衡集群 &#xff08;2&#xff09;高可用集群 二.使用集群的意义 1.高性价比和性能比 2.高可用性 3.可伸缩性强 4.持久和透明性高 三.常见的两种集群模式拓扑 1.LVS集群模式 2.haproxy/nginx模式 四.常…

Java并发编程(六)线程池[Executor体系]

概述 在处理大量任务时,重复利用线程可以提高程序执行效率,因此线程池应运而生。 它是一种重用线程的机制,可以有效降低内存资源消耗提高响应速度。当任务到达时&#xff0c;任务可以不需要的等到线程创建就能立即执行线程池可以帮助我们更好地管理线程的生命周期和资源使用,…

Jmeter-压力测试工具

文章目录 Jmeter快速入门1.1.下载1.2.解压1.3.运行 2.快速入门2.1.设置中文语言2.2.基本用法 Jmeter快速入门 1s内发送大量请求&#xff0c;模拟高QPS&#xff0c;用以测试网站能承受的压力有多大 Jmeter依赖于JDK&#xff0c;所以必须确保当前计算机上已经安装了JDK&#xff0…

DAY2,ARM(特殊功能寄存器,数据操作指令,跳转指令)

1.cmp、sub、b指令的使用&#xff1b; 代码&#xff1a; .text .global _start _start:mov r0,#9mov r1,#15b funfun:cmp r0,r1beq stopsubcc r1,r1,r0subhi r0,r0,r1b funstop:b stop .end结果&#xff1a; 2.汇编指令计算1~100之间和&#xff1b; 代码&#xff1a; .text …

echart 词云图

const graphOut ref(null); const optionGraph reactive({series: [{type: graph,shape: circle,symbolSize: [215, 50],//散点形状设置symbol: circle’, ‘rect’, ‘roundRect’, ‘triangle’, ‘diamond’, ‘pin’, arrow’symbol: rect,layout: force,force: {repulsio…

Docker安装elasticsearch分布式搜索

文章目录 ☀️安装elasticsearch☀️1.部署单点es&#x1f338;1.1.创建网络&#x1f338;1.2.下载镜像&#x1f338;1.3.运行 ☀️2.部署kibana&#x1f338;2.1.部署&#x1f338;2.2.DevTools ☀️3.安装IK分词器&#x1f338;3.1.在线安装ik插件&#xff08;较慢&#xff0…

逗号操作符

逗号表达式&#xff0c;就是用逗号隔开的多个表达式。 逗号表达式&#xff0c;从左向右依次执行。整个表达式的结果是最后一个表达式的结果。 运用&#xff1a;

【字典学习+稀疏编码Sparse Encoding】简单介绍与sklearn的实现方式

文章目录 1、字典学习与稀疏编码2、sklearn的实现3、示例 1、字典学习与稀疏编码 简单来说&#xff0c;稀疏编码就是把输入向量&#xff08;信号&#xff09;/ 矩阵&#xff08;图像&#xff09;表示为稀疏的系数向量和一组超完备基向量&#xff08;字典&#xff09;的线性组合…

BeanFactory与Applicationcontext(1)

BeanFactory是接口&#xff0c;提供了IOC容器最基本的形式&#xff0c;给具体的IOC容器的实现提供了规范。BeanFactory是spring的“心脏”&#xff0c;核心容器&#xff0c;它也是Applicationcontext的父接口。 BeanFactory实质上并未提供过多的方法&#xff0c;spring容器的I…

Mr. Cappuccino的第63杯咖啡——Spring之AnnotationConfigApplicationContext源码分析

Spring之AnnotationConfigApplicationContext源码分析 源码分析 源码分析 以上一篇文章《Spring之Bean的生命周期》的代码进行源码分析 AnnotationConfigApplicationContext applicationContext new AnnotationConfigApplicationContext(SpringConfig02.class); LifeCycleBe…

通达信接口调用过程需要借助什么?

通达信接口是一种用于获取、传输和处理股票市场相关数据的软件接口&#xff0c;以提供了一种连接股票市场数据源和数据使用者之间的通道&#xff0c;允许开发者通过编程方式获取股票行情数据、交易数据和相关信息等。如果调用通达信接口&#xff0c;需要借助以下几个方面的工具…

9-AJAX-1入门

AJAX 目录 AJAX 概念和 axios 使用认识 URLURL 查询参数常用请求方法和数据提交HTTP协议-报文接口文档案例 - 用户登录form-serialize 插件 01.AJAX 概念和 axios 使用 目标 了解 AJAX 概念并掌握 axios 库基本使用 讲解 什么是 AJAX ? mdn 使用浏览器的 XMLHttpRequest…

前后端分离------后端创建笔记(06)新增接口页面布局

本文章转载于【SpringBootVue】全网最简单但实用的前后端分离项目实战笔记 - 前端_大菜007的博客-CSDN博客 仅用于学习和讨论&#xff0c;如有侵权请联系 源码&#xff1a;https://gitee.com/green_vegetables/x-admin-project.git 素材&#xff1a;https://pan.baidu.com/s/…

[PyTorch][chapter 50][创建自己的数据集 2]

前言&#xff1a; 这里主要针对图像数据进行预处理.定义了一个 class Pokemon(Dataset) 类&#xff0c;实现 图像数据集加载,划分的基本方法. 目录&#xff1a; 整体框架 __init__ load_images save_csv divide_data __len__ denormalize __g…

[NepCTF 2023] crypto 复现

这个赛很不理想&#xff0c;啥都不会。 拿了WP看了几个题&#xff0c;记录一下 random_RSA 这题不会是正常情况&#xff0c;我认为。对于论文题&#xff0c;不知道就是不知道&#xff0c;基本没有可能自己去完成论文。 题目不长&#xff0c;只有两个菜单&#xff0c;共可交…

Springboot 在 redis 中使用 BloomFilter 布隆过滤器机制

一、导入SpringBoot依赖 在pom.xml文件中&#xff0c;引入Spring Boot和Redis相关依赖 <!-- Google Guava 使用google的guava布隆过滤器实现--><dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><vers…

IPv4分组

4.3.1 IPv4分组 IP协议定义数据传送的基本单元——IP分组及其确切的数据格式 1. IPv4分组的格式 IPv4分组由首部和数据部分&#xff08;TCP、UDP段&#xff09;组成&#xff0c;其中首部分为固定部分&#xff08;20字节&#xff09;和可选字段&#xff08;长度可变&#xff0…