鸿蒙(HarmonyOS)性能优化实战-Trace使用教程

news2024/11/23 19:02:29

概述

OpenHarmony的DFX子系统提供了为应用框架以及系统底座核心模块的性能打点能力,每一处打点即是一个Trace,其上附带了记录执行时间、运行时格式化数据、进程或线程信息等。开发者可以使用SmartPerf-Host调试工具对Trace进行解析,在其绘制的泳道图中,对应用运行过程中的性能热点进行分析,得出优化方案。本文旨在介绍OpenHarmony中常用的Trace,解释它们的含义和用途,并阐述如何通过这些Trace来识别潜在的性能问题。同时,我们还将详细介绍Trace的工作原理,帮助读者更好地理解这些Trace及如何实现性能数据的采集和分析。通过本文的阅读,读者将对OpenHarmony中的Trace有一个深入的了解,为应用程序性能优化提供有力支持。

常用Trace及含义

下面将从渲染流程入手,配合常用场景介绍常用Trace。

渲染流程

与其他操作系统相同,OpenHarmony也是由Vsync信号控制每一帧绘制操作的时机。Vsync信号是一个垂直同步信号,它指示显示器在垂直空白期之后开始下一帧的刷新。设备的屏幕以固定的频率发送Vsync信号,以刷新率60Hz举例,则屏幕每隔16.6ms发送一次Vsync信号。在收到Vsync信号后,UI后端引擎开始准备屏幕的下一帧绘制,然后应用程序提交渲染命令,用于描述图形绘制、纹理设置、着色器使用等。一旦应用程序提交了渲染命令,UI后端引擎会将其添加到渲染队列中,并在合适的时机执行这些渲染命令,通常会在后台线程执行,以确保主线程不被长时间阻塞。当这些渲染命令被UI后端引擎执行时,它们会被传递给图形系统Render Service进行处理,图形系统会根据命令进行相应的图形计算和渲染操作,如顶点变换、光照、纹理贴图等。在图形系统完成渲染后,渲染结果将被写入帧缓冲区。帧缓冲区是一个内存区域,存储用于显示器输出的图像数据。一旦帧缓冲区更新完成,UI后端引擎会等待直到下一个Vsync信号到来,这个过程是为了确保渲染结果在显示器垂直消隐之前准备好。当下一个Vsync信号到来时,UI后端引擎将已经准备好的帧缓冲区的内容发送给显示器,显示器根据这些数据刷新自己的像素,至此完成一整个渲染周期。如图1所示。

图1 渲染流程图

从Trace角度来看,一帧的渲染流程如下:

(1)Vsync信号到达;
(2)UI后端引擎进行第一帧绘制;
(3)向Render Service通信,传输绘制命令并请求一帧;
(4)Render Service对多个图层进行合并,计算刷新区域,然后进行渲染和绘制本帧;
(5)完成一帧绘制后交给屏幕。

一帧的渲染流程中的UI后端引擎的常用Trace的含义如图2所示。

图2 UI后端引擎渲染Trace泳道图

序号Trace参数说明描述
1OnVsyncEvent now:%" PRIu64 "当前时间戳–纳秒级收到Vsync信号,渲染流程开始
2FlushVsync刷新视图同步事件,包括记录帧信息、刷新任务、绘制渲染上下文、处理用户输入
3UITaskScheduler::FlushTask刷新UI界面,包括布局、渲染和动画等
4FlushMessages发送消息通知图形侧进行渲染
5FlushLayoutTask执行布局任务
6FlushRenderTask %zu当前页面上的需要渲染的节点的数量总渲染任务执行
7Layout节点布局
8FrameNode::RenderTask单个渲染任务执行
9ListLayoutAlgorithm::MeasureListItem:%d当前列表项索引计算列表项的布局尺寸

图形图像子系统中的Render Service,是负责界面内容绘制的部件,处理由各个应用提交的统一渲染任务,将不同应用渲染的图层进行合并、送显。在收到每个Vsync周期信号时,首先处理应用提交的指令,包括应用渲染树节点的新增、删除、修改,然后进行动画计算和遮挡计算,以上是为了对统一渲染树进行更新。接下来开始对渲染树执行绘制,首先预处理每个节点,计算绝对位置和脏区信息,然后针对脏区进行绘制,优先使用硬件合成器进行绘制,当遇到无法合成绘制的,交由GPU执行重绘,绘制的所有结果都将存入屏幕缓冲区,最后将绘制结果提交送显、上屏展示。

当Vsync信号刷新时,如图3所示。

图3 RS侧渲染Trace泳道图

序号Trace描述
1RSMainThread::DoComposition合成渲染树上各节点图层
2RSMainThread::ProcessCommand处理client端指令
3Animate动画处理
4RSMainThread::CalcOcclusion遮挡计算
5ProcessDisplayRenderNode[x]单个显示器画面的绘制流程
6ProcessSurfaceNode:x单个节点的合成器处理
7Repaint硬件合成器合成绘制
8Redraw无法进行合成,则执行重绘
9RenderFrameGPU执行绘制
10SwapBuffers刷新屏幕缓冲区
11Commit绘制结果提交上屏

懒加载

懒加载使用LazyForEach实现,LazyForEach从提供的数据源中按需迭代数据,并在每次迭代过程中创建相应的组件。当LazyForEach在滚动容器中使用时,框架会根据滚动容器可视区域按需创建组件。当组件滑出可视区域外时,框架会进行组件销毁以降低内存占用。图4抓取的是懒加载过程中一帧的Trace。

图4 懒加载Trace泳道图

序号Trace参数说明描述
1OnIdle, targettime:%" PRId64 "时间戳,在这个时间之前完成该任务idle事件循环中检查是否有新的事件需要处理,如果有,则将任务调度器加入UI线程中并执行预测任务
2expiringItem_ count:[%zu]懒加载Item的个数预构建,包含处理所有懒加载项
3List predict添加预测布局任务
4Builder:BuildLazyItem [%d]需创建的项目索引在需要时创建项,并进行缓存
5Layout[%s][self:%d][parent:%d]tag标签,当前节点在UINode树中的索引,父节点在UINode树中的索引当前帧节点布局
6Build[%s][self:%d][parent:%d]tag标签,当前节点在UINode树中的索引,父节点在UINode树中的索引当前帧节点构建
7CustomNode:BuildRecycle %sJS视图名称触发复用渲染
8ExecuteJS执行JS代码

页面加载

当触发页面加载时,OpenHarmony会创建一个新的页面实例,然后按照特定的程序调用页面的生命周期方法。在生命周期方法中加载页面的布局,然后将数据绑定到页面上的视图元素,使页面能够显示和更新数据。图5抓取的是页面加载中一帧的Trace。

图5 页面加载帧Trace泳道图

序号Trace参数说明描述
1PageRouterManager::RunPage页面路由预处理及加载页面
2PageRouterManager::LoadPage加载页面并路由
3JsiDeclarativeEngine::LoadPageSource加载一个JavaScript文件并将其解析为ABC字节码
4JsiDeclarativeEngine::LoadJsWithModule Execute Page code : %s页面url地址执行页面代码
5Build[%s][self:%d][parent:%d]tag标签,当前节点在UINode树中的索引,父节点在UINode树中的索引当前帧节点构建
6CustomNode:BuildItem %sJS视图名称渲染子节点然后将其挂载到父节点上
7ViewChangeCallback(%d, %d)视图宽,视图高视图变化回调

Trace实践

以下示例采用LazyForEach的方式遍历列表,并借助SmartPerf-Host调试工具追踪代码执行流程。
在代码示例中,使用一个List容器组件,通过懒加载方式来创建出120个IconView自定义组件。在IconView组件中,使用了Flex容器组件包含Image和Text子组件,形成了图文混合列表。

// src/main/ets/pages/LazyForEachPage.ets

@Entry
@Component
struct LazyForEachPage {
  private iconItemSourceList = new ListData();
  aboutToAppear() {
    // 添加120个IconItem的数据
     ......
  }
  build() {
    Column() {
      Text('懒加载示例')
        .fontSize(24)
        .fontColor(Color.Black)
        .fontWeight(FontWeight.Bold)
        .textAlign(TextAlign.Start)
        .width('90%')
        .height(50)
      List({ space: 20 }) {
        LazyForEach(this.iconItemSourceList, (item: IconItemModel) => {
          ListItem() {
            IconItem({ image: item.image, text: item.text })
          }
        }, (item: IconItemModel, index) => index.toString())
      }
      .divider({ strokeWidth: 2, startMargin: 20, endMargin: 20 }) // 每行之间的分界线
      .width('100%')
      .height('100%')
      .layoutWeight(1)
    }
    .width('100%')
    .height('100%')
    .alignItems(HorizontalAlign.Center)
  }
}

// src/main/ets/view/IconView.ets

@Component
export struct IconItem {
  image: string | Resource = '';
  text: string | Resource = '';
  build() {
    Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.Center, alignContent: FlexAlign.Center }) {
      Image(this.image)
        .height(40)
        .width(40)
        .objectFit(ImageFit.Contain)
        .margin({
          left: 15
        })
      Text(this.text)
        .fontSize(20)
        .fontColor(Color.Black)
        .width(100)
        .height(50)
        .textAlign(TextAlign.Center)
    }
    .width('100%')
    .height(50)
  }
}

下面使用SmartPerf-Host调试工具抓取htrace文件,并生成一个跟踪泳道分析图,来了解示例代码的加载流程。跟踪泳道分析图被分为五个部分,每个部分都标注数字并框选出相应的标签,从而使得整体的过程能够得到更好的理解。

图6 LazyForEach遍历的列表的泳道分析图

接下来,逐一解析这五个模块的详情:

1.加载并路由LazyForEach页面

图7 加载并路由LazyForEach页面泳道图

  • H:JsiDeclarativeEngine::LoadPageSource加载一个 JavaScript 文件,并且解析为 ABC 字节码;
  • H:FlushPipelineWithoutAnimation 清理渲染管道的操作;
  • H:CustomNode:OnAppear 用于构建当前 OnAppear 生命周期的操作,并执行aboutToAppear生命周期函数;
  • H:CustomNode:BuildItem LazyForEachPage 渲染子节点并挂载在 LazyForEachPage 页面上。

2.对当前帧节点Stage,执行布局任务、执行渲染任务并通知图形侧进行渲染

图8 对当前帧节点Stage,执行布局任务、执行渲染任务并通知图形侧进行渲染泳道图

  • H:Layout[stage][self:1][parent:0]对当前帧节点Stage,执行布局任务;(Stage作为框架,承载着页面Page节点。因此,标签的呈现会从Stage开始)
    • H:Measure[%s][self:17][parent:16] 对Page、Column、Row、Image、Text等组件布局尺寸计算;
    • H:Builder:BuildLazyItem [0]H:ListLayoutAlgorithm::MeasureListItem:0 分别为创建一个LazyItem项目和计算列表项的布局尺寸;
    • H:Layout[%s][self:38][parent:37] 对Page、Column、Row、Image、Text等组件执行布局任务;
  • H:FrameNode::RenderTask 执行渲染任务;
  • H:RequestNextVSync 请求下一帧Vsync信号。

3.对当前帧节点Flex,执行布局任务、执行渲染任务并通知图形侧进行渲染

图9 对当前帧节点Flex,执行布局任务、执行渲染任务并通知图形侧进行渲染泳道图

  • H:Layout[Flex][self:63][parent:62]对当前帧节点Flex,执行布局任务**;**
    • H:Measure[%s][self:17][parent:16] 对Image、Text等组件布局尺寸计算;
  • H:FrameNode::RenderTask Flex渲染任务执行;
  • H:RequestNextVSync 请求下一帧Vsync信号。

4.构建前预处理数据及添加预测布局任务

图10 构建前预处理数据及添加预测布局任务泳道图

  • H:Builder:BuildLazyItem [11]构建前预处理数据了11条数据;
  • H:Layout[ListItem][self:76][parent:-1] 添加一条Flex、Image、Text的预测布局;
  • H:FlushMessages 发送消息通知图形侧进行渲染。

5.合成渲染树上各节点图层任务

图11 合成渲染树上各节点图层任务泳道图

  • H:AcquireBufferH:ProcessSurfaceNode:EntryView XYWH[0 0 720 1280]获取屏幕缓冲区并绘制EntryView、SystemUi_StatusBar、SystemUi_NavigationBar等;
  • H:Repaint 硬件合成器合成绘制当前节点树。

自定义Trace

开发者可以根据业务需求,使用hiTraceMeter进行自定义Trace打点跟踪,目前支持ArkTS和Native,具体使用细节可参考下方链接:

性能打点跟踪开发指导(ArkTS)
性能打点跟踪开发指导(Native)

添加自定义Trace后,可在SmartPerf-Host调试工具上查看,自定义Trace将以独立泳道的形式呈现在对应打点的进程下。
下图两条泳道使用了startTrace和finishTrace方法,表示程序运行过程中,指定标签从调用startTrace到调用finishTrace的耗时统计。图中记录了CUSTOM_TRACE_TAG_1和CUSTOM_TRACE_TAG_2两个标签,先后呈现了2个标签的耗时统计。

图12 自定义Trace示例

下图两条泳道使用了TraceByValue方法,表示程序运行过程中,指定Trace在对应时间段内的状态值,状态值含义可按需传参,开发者可以通过鼠标放置在对应数据块上,来查看具体的状态值。图中记录了CUSTOM_TRACE_TAG_2标签在红色方框标识的时间段内,打点状态值为2001。

图13 自定义状态值示例

性能打点原理

Trace的生成依赖了DFX子系统中的HiTrace组件,其中包含的hiTraceMeter模块为开发者提供系统性能打点接口,具体细节可参考下方链接:

HiTrace组件
hiTraceMeter模块

hiTraceMeter拥有两套开始和结束打点接口,实现对逻辑行为的耗时统计。由于耗时统计大多数以方法为单位,所以hiTraceMeter也提供了快速打点单个方法执行耗时的宏定义HITRACE_METER、HITRACE_METER_NAME、HITRACE_METER_FMT,使用它们,只需要在方法起始位置调用即可。这些宏定义依赖了方法内局部变量的生命周期,其原理是在方法开始时构造了一个打点实例,在实例构造函数中调用开始打点接口,当方法执行完毕,打点实例随着方法结束而执行析构,在实例析构函数中调用结束打点接口。

App中的打点示例

ArkUI框架子系统应用hiTraceMeter的例子,来源于ArkUI开发框架源码。
以下代码对hiTraceMeter进行接口封装,其原理与HITRACE_METER等相同,依赖方法内局部变量的生命周期实现快速打点。

// frameworks/base/log/ace_trace.h

#define ACE_SCOPED_TRACE(fmt, ...) AceScopedTrace aceScopedTrace(fmt, ##__VA_ARGS__)
#define ACE_FUNCTION_TRACE() ACE_SCOPED_TRACE(__func__)

class ACE_FORCE_EXPORT AceScopedTrace final {
public:
    explicit AceScopedTrace(const char* format, ...) __attribute__((__format__(printf, 2, 3)));
    ~AceScopedTrace();

    ACE_DISALLOW_COPY_AND_MOVE(AceScopedTrace);

private:
    bool traceEnabled_ { false };
};

以下代码是刷新视图同步事件,包括记录帧信息、刷新任务、绘制渲染上下文、处理用户输入。在方法开头调用宏定义ACE_FUNCTION_TRACE,将函数名FlushVsync作为Trace名称记录下来,并记录函数开始时间,在函数结束时记录函数结束时间,得出执行耗时。

// frameworks/core/pipeline/pipeline_context.cpp

void PipelineContext::FlushVsync(uint64_t nanoTimestamp, uint32_t frameCount)
{
    ACE_FUNCTION_TRACE();

    // 此处省略方法内的其他业务逻辑
    // ...
}

RS中的打点示例

图形子系统应用hiTraceMeter的例子,来源于图形子系统源码。
以下代码对hiTraceMeter进行接口封装。

// utils/log/rs_trace.h

#include "hitrace_meter.h"
#define ROSEN_TRACE_BEGIN(tag, name) StartTrace(tag, name)
#define RS_TRACE_BEGIN(name) ROSEN_TRACE_BEGIN(HITRACE_TAG_GRAPHIC_AGP, name)
#define ROSEN_TRACE_END(tag) FinishTrace(tag)
#define RS_TRACE_END() ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP)
#define RS_TRACE_NAME(name) HITRACE_METER_NAME(HITRACE_TAG_GRAPHIC_AGP, name)
#define RS_TRACE_NAME_FMT(fmt, ...) HITRACE_METER_FMT(HITRACE_TAG_GRAPHIC_AGP, fmt, ##__VA_ARGS__)
#define RS_ASYNC_TRACE_BEGIN(name, value) StartAsyncTrace(HITRACE_TAG_GRAPHIC_AGP, name, value)
#define RS_ASYNC_TRACE_END(name, value) FinishAsyncTrace(HITRACE_TAG_GRAPHIC_AGP, name, value)
#define RS_TRACE_INT(name, value) CountTrace(HITRACE_TAG_GRAPHIC_AGP, name, value)
#define RS_TRACE_FUNC() RS_TRACE_NAME(__func__)

以下代码在显示器画面绘制方法。在方法开头调用宏定义RS_TRACE_NAME,将函数名ProcessDisplayRenderNode与对应的显示器id组合后,作为Trace名称记录下来,同时由于其本质是使用了快速打点单个方法的宏定义HITRACE_METER_NAME,于是只需要调用一次,即可收集到ProcessDisplayRenderNode函数的执行起终点时间,得出执行耗时。

// rosen/modules/render_service/core/pipeline/rs_surface_capture_task.cpp

void RSSurfaceCaptureVisitor::ProcessDisplayRenderNode(RSDisplayRenderNode &node)
{
    RS_TRACE_NAME("RSSurfaceCaptureVisitor::ProcessDisplayRenderNode:" +
        std::to_string(node.GetId()));

    // 此处省略方法内的其他业务逻辑
    // ...
}

为了能让大家更好的学习鸿蒙(HarmonyOS NEXT)开发技术,这边特意整理了《鸿蒙开发学习手册》(共计890页),希望对大家有所帮助:https://qr21.cn/FV7h05

《鸿蒙开发学习手册》:

如何快速入门:https://qr21.cn/FV7h05

  1. 基本概念
  2. 构建第一个ArkTS应用
  3. ……

开发基础知识:https://qr21.cn/FV7h05

  1. 应用基础知识
  2. 配置文件
  3. 应用数据管理
  4. 应用安全管理
  5. 应用隐私保护
  6. 三方应用调用管控机制
  7. 资源分类与访问
  8. 学习ArkTS语言
  9. ……

基于ArkTS 开发:https://qr21.cn/FV7h05

  1. Ability开发
  2. UI开发
  3. 公共事件与通知
  4. 窗口管理
  5. 媒体
  6. 安全
  7. 网络与链接
  8. 电话服务
  9. 数据管理
  10. 后台任务(Background Task)管理
  11. 设备管理
  12. 设备使用信息统计
  13. DFX
  14. 国际化开发
  15. 折叠屏系列
  16. ……

鸿蒙开发面试真题(含参考答案):https://qr18.cn/F781PH

鸿蒙开发面试大盘集篇(共计319页):https://qr18.cn/F781PH

1.项目开发必备面试题
2.性能优化方向
3.架构方向
4.鸿蒙开发系统底层方向
5.鸿蒙音视频开发方向
6.鸿蒙车载开发方向
7.鸿蒙南向开发方向

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

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

相关文章

yudao-cloud微服务系统系统模块+后台管理系统成功运行

🌹作者主页:青花锁 🌹简介:Java领域优质创作者🏆、Java微服务架构公号作者😄 🌹简历模板、学习资料、面试题库、技术互助 🌹文末获取联系方式 📝 系列文章目录 第一章 芋…

精酿啤酒:酿造工艺的自动化与智能化发展

随着科技的不断进步,自动化与智能化已成为啤酒酿造工艺的重要发展方向。Fendi Club啤酒紧跟时代潮流,积极推动酿造工艺的自动化与智能化发展,旨在提高生产效率、确保产品品质和满足市场需求。 Fendi Club啤酒引入自动化生产设备。他们采用自动…

rabbitmq集群配置

1,配置环境变量 MY_POD_NAME:当前Pod的名称 RABBITMQ_ERLANG_COOKIE:设置Erlang Cookie用于节点间通信安全验证,值来自/nfs/rabbitmq/lib/.erlang.cookie文件内容 RABBITMQ_NODENAME:根据Pod名称动态生成了RabbitMQ…

Typora for Mac:轻量级Markdown编辑器

Typora for Mac是一款专为Mac用户设计的轻量级Markdown编辑器,它以其简洁的界面和强大的功能,成为了Markdown写作爱好者的首选工具。 Typora for Mac v1.8.10中文激活版下载 Typora的最大特色在于其所见即所得的编辑模式,用户无需关心复杂的M…

【软件】ERETCAD-Env:在轨空间环境3D动态仿真软件

文章介绍了Extreme-environment Radiation Effect Technology Computer-Aided Design – Environment (ERETCAD-Env)软件,文章的介绍和展示了ERETCAD-Env软件的功能和特点,这是一款用于动态模拟在轨卫星所处空间环境的计算机辅助设计软件。强调了该软件在…

TCP关闭连接时的一些思考

TCP协议是TCP/IP栈中最复杂的协议,它最大的优点是传输的可靠性,这通过面向连接、按序传输、超时重传、流量控制等机制保证其传输的可靠性。但这并不是我们今天要讨论的重点! TCP通信的过程分别是三个阶段:建立连接、传输数据、关…

SpringCloud Hystrix 实战

一、配置 1.引入jar包 单独使用hystrix ,不配合openFegin使用的话,单独使用hystrix,需要引入spring-cloud-starter-netflix-hystrix包。要使用的hystrix-dashboard 界面的话需要引入spring-boot-starter-actuator 包和spring-cloud-starter-netflix-hy…

SpringBoot中多数据源灵活切换解决方案

本篇内容介绍了“SpringBoot中如何使用Dynamic Datasource配置多数据源”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成! 源码地址/文档说明 功能特性: 支持 数据源分组…

通信原理(2)--随机过程

通信原理(2)–随机过程 3.1随机过程的基本概念 随机过程{x(t)}由一族时间函数 x i ( t ) x_i(t) xi​(t),i1,2.3…组成,每一个时间函数 x i ( t ) x_i(t) xi​(t)称为随机过程{x(t)}的一个样本函数(一个实现) 每个样本函数在时间…

python-opencv实现最近邻插值和双线性插值对图片上采样

使用背景 当我们需要把图像进行放大或者缩小的时候,第一反应是使用resize()实现。很多情况下,我们会调用最近邻插值和双线性插值去放大图片,当然要说没有分辨率的损失那是不可能的,只能说在放大图片的过程中尽可能增加了图片的分…

Hybrid Homomorphic Encryption:SE + HE

参考文献: [NLV11] Naehrig M, Lauter K, Vaikuntanathan V. Can homomorphic encryption be practical?[C]//Proceedings of the 3rd ACM workshop on Cloud computing security workshop. 2011: 113-124.[MJS16] Maux P, Journault A, Standaert F X, et al. To…

Matlab|交直流系统潮流计算(含5种控制模式)

目录 1 主要内容 程序参考流程图 2 部分代码 3 程序结果 4 下载链接 1 主要内容 该程序参考文献《交直流系统潮流计算及相互关联特性分析》,采用5种交直流潮流控制方式:1.定电流定电压 2.定电流定熄弧角 3.定功率定电压 4.定功率定熄弧角 5.定触发角…

Stable Diffusion 常用放大算法详解

常用放大算法 图像放大算法大致有两种: 传统图像放大算法(Lantent、Lanczos、Nearest)AI图像放大算法(4x-UltraSharp、BSRGAN、ESRGAN等) 传统图像放大算法是基于插值算法,计算出图像放大后新位置的像素…

用友政务财务系统 FileDownload 任意文件读取漏洞复现

0x01 产品简介 用友政务财务系统具有多项核心功能,旨在满足各类组织的财务管理需求。首先,它提供了财务核算功能,能够全面管理企业的总账、固定资产、现金、应付应收等模块,实时掌握企业的财务状况,并通过科目管理、凭证处理、报表分析等功能为决策提供有力支持。 0x02 …

Elcomsoft iOS Forensics Toolkit: iPhone/iPad/iPod 设备取证工具包

天津鸿萌科贸发展有限公司是 ElcomSoft 系列取证软件的授权代理商。 Elcomsoft iOS Forensics Toolkit 软件工具包适用于取证工作,对 iPhone、iPad 和 iPod Touch 设备执行完整文件系统和逻辑数据采集。对设备文件系统制作镜像,提取设备机密&#xff08…

13.电子产品拆解分析-插排带3USB

13.电子产品拆解分析-插排带3USB 一、功能介绍二、电路分析以及器件作用1、三个插座之间通过电线连接,总开关控制火线2、通过FSD3773低待机功耗原边反馈AC/DC驱动芯片控制5V的输出一、功能介绍 ①一键控制总电源开关;②带三路USB输出;③最大支持2500W输出,10A输出电流;④8…

STM32自己从零开始实操01:原理图

在听完老师关于 STM32 物联网项目的所有硬件课程之后,就是感觉自己云里雾里,明明课程都认真听完了,笔记也认真记录,但是就是感觉学到的知识还不是自己。 遂决定站在老师的肩膀上自己开始设计项目,将知识变成自己的&am…

【机器学习】集成学习:强化机器学习模型与创新能的利器

集成学习:强化机器学习模型预测性能的利器 一、集成学习的核心思想二、常用集成学习方法Bagging方法Boosting方法Stacking方法 三、集成学习代表模型与实现四、总结与展望 在大数据时代的浪潮下,机器学习模型的应用越来越广泛,而集成学习作为…

微信小程序简单实现购物车功能

微信小程序简单实现购物车结算和购物车列表展示功能 实现在微信小程序中对每一个购物车界面的商品订单,进行勾选结算和取消结算的功能,相关界面截图如下: 具体实现示例代码为: 1、js代码: Page({/*** 页面的初始数…

Windows下搭建Flutter开发环境

IDE:VS code Flutter官网:Flutter: 为所有屏幕创造精彩 - Flutter 中文开发者网站 - Flutter 下载&安装 下载Flutter SDK,如图,建议自行下载安装: SDK还是挺大的,近1G,使用迅雷下载会快不少。 下载完成,解压缩到指定目录即可! 设置Local SDK,按下面步骤操作即…