深度剖析iOS渲染

news2024/11/13 3:48:03

iOS App 图形图像渲染的基本流程:

1.CPU:完成对象的创建和销毁、对象属性的调整、布局计算、文本的计算和排版、图片的格式转换和解码、图像的绘制。

2.GPU:GPU拿到CPU计算好的显示内容,完成纹理的渲染, 渲染完成后将渲染结果放入帧缓冲区。

简单来说,CPU就像科学家要进行繁琐的计算、GPU就像小学生进行简单的1+1计算,但是 GPU是通过并行执行大量的线程来完成计算任务的。GPU的并行计算能力是CPU的几倍甚至几十倍,可以处理大量的数据和计算任务,提高计算效率和速度。所以GPU主要应用在图像处理中,因此,大多数CALayer的属性都是用GPU来绘制。

3.帧缓冲区(Frame Buffer)(双缓冲机制,不再赘述)

正常情况下,在当前屏幕显示的内容,由 GPU 渲染完成后放到当前屏幕的帧缓存区,不需要额外的渲染空间。我们知道 iPhone 的屏幕刷新率是 60Hz,也就是刷新一帧的时间是 16.67 ms, 每隔这段时间视频控制器就会去读一次缓存区的内容来显示。 

假如 GPU 遇到性能瓶颈,导致无法在一帧内更新渲染结果到帧缓存区,那么从缓存区读到的会是上一帧的内容,导致帧率降低界面卡顿。

4.视频控制器:用来读取Frame Buffer中的数据的,GPU开始会绘制后缓存里的画面,然后视频控制器读取完前缓存的画面, 就会去读取后缓存里的画面,然后GPU再去绘制前缓存里的画面。

以上简单介绍了下iOS图像渲染。

接下来我们进一步深入了解。。。。。

CPU和GPU是如何渲染的?

首先给出一张图:iOS的渲染流水线。

上述图像渲染流水线中,除了第一部分 Application 阶段,后续主要都由 GPU 负责,为了方便后文讲解,先将 GPU 的渲染流程图展示出来:

上图就是一个三角形被渲染的过程中,GPU 所负责的渲染流水线。可以看到简单的三角形绘制就需要大量的计算,如果再有更多更复杂的顶点、颜色、纹理信息(包括 3D 纹理),那么计算量是难以想象的。这也是为什么 GPU 更适合于渲染流程。

接下来介绍的是iOS的渲染流水线(渲染管道)

1.Application 应用处理阶段:得到图元

这个阶段具体指的就是图像在应用中被处理的阶段,此时还处于 CPU 负责的时期。在这个阶段应用可能会对图像进行一系列的操作或者改变,最终将新的图像信息传给下一阶段。这部分信息被叫做图元信息,通常是三角形、线段、顶点等。见下图海豚就很直观了。

2.Geometry 几何处理阶段:处理图元

进入这个阶段之后,以及之后的阶段,就都主要由 GPU 负责了。此时 GPU 可以拿到上一个阶段传递下来的图元信息,GPU 会对这部分图元进行处理,之后输出新的图元。这一系列阶段包括:

  • 顶点着色器(Vertex Shader):这个阶段中会将图元中的顶点信息进行视角转换、添加光照信息、增加纹理等操作。
  • 形状装配(Shape Assembly):图元中的三角形、线段、点分别对应三个 顶点、两个 顶点、一个 顶点。这个阶段会将 顶点 连接成相对应的形状。
  • 几何着色器(Geometry Shader):额外添加额外的顶点,将原始图元转换成新图元,以构建一个不一样的模型。简单来说就是基于通过三角形、线段和点构建更复杂的几何图形。

3.Rasterization 光栅化阶段:图元转换为像素

光栅化的主要目的是将几何渲染之后的图元信息,转换为一系列的像素,以便后续显示在屏幕上。

4.Pixel 像素处理阶段:处理像素,得到位图

我们得到了图元所对应的像素,此时,我们需要给这些像素填充颜色和效果。

经过光栅化阶段得到了图元所对应的像素,此时,我们需要给这些像素填充颜色和效果。所以最后这个阶段就是给像素填充正确的内容,最终显示在屏幕上。这些经过处理、蕴含大量信息的像素点集合,被称作位图(bitmap)。也就是说,Pixel 阶段最终输出的结果就是位图,过程具体包含:

  • 片段着色器(Fragment Shader):对屏幕像素点着色。
  • 测试与混合(Tests and Blending):检查图层深度和透明度,从而判断片段的前后位置,以及是否应该被舍弃,并进行图层混合。

总的来说:

iOS的渲染分为四个部分:

  • 应用处理阶段:相当于 CPU 执行的部分,负责处理逻辑并提交渲染指令。
  • 几何处理:负责几何变换和顶点处理,转化为图元。
  • 光栅化:将图元转化为片段,生成像素数据。
  • 像素处理:片段着色、纹理映射等,输出到帧缓冲区(Frame Buffer)。

位图:

位图(Bitmap) 是一种数据结构。一个位图是由 n*m 个像素组成,每个像素的颜色信息由 RGB 组合或者灰度值表示。见下图:

介绍完iOS渲染流水线后(其实这里介绍的就是App图像渲染的基本流程的CPU和GPU部分),我们回到图像渲染的基本流程,接下来我们要介绍有关垂直同步信号和双缓冲机制的内容。

如何将已经渲染好的图像放到屏幕上?

这里先简单介绍下屏幕成像的原理:

显示器的电子束会从屏幕的左上角开始逐行扫描,屏幕上的每个点的图像信息都从帧缓冲器中的位图进行读取,在屏幕上对应地显示。扫描的流程如下图所示:

这时候就会出现一个问题:我如何知道屏幕下一个位置的像素是否已经渲染好了并且已经存放在了帧缓存区里面(这就是我们说的屏幕撕裂的问题)?这里就涉及到了两个机制:

  • 垂直同步信号
  • 双缓冲机制

1.垂直同步信号

当电子束完成一帧的扫描,将要从头开始扫描时,就会发出一个垂直同步信号。只有当视频控制器接收到 Vsync 之后,才会将帧缓冲器中的位图更新为下一帧,这样就能保证每次显示的都是同一帧的画面,因而避免了屏幕撕裂。

简单来说就是:帧缓冲器接收到信号了,才更新下一帧。

2.双缓冲机制

所以双缓冲机制会增加一个新的备用缓冲器(back buffer)。渲染结果会预先保存在 back buffer 中,在接收到 Vsync 信号的时候,视频控制器会将 back buffer 中的内容置换到 frame buffer 中,此时就能保证置换操作几乎在一瞬间完成(实际上是交换了内存地址)。

简单来说就是:GPU开始会绘制后缓存里的画面,然后视频控制器读取完前缓存的画面, 就会去读取后缓存里的画面,然后GPU再去绘制前缓存里的画面。

通过双缓冲机制,我们可以在60FPS(16.67ms)前,置换新的一帧屏幕图像。这样就能及时的更新屏幕图像了,就能解决屏幕撕裂问题。

掉帧

但是,如果在接收到 Vsync 之时 CPU 和 GPU 还没有渲染好新的位图,视频控制器就不会去替换 frame buffer 中的位图。这时屏幕就会重新扫描呈现出上一帧一模一样的画面。相当于两个周期显示了同样的画面,这就是所谓掉帧的情况。

这时候我们可以用三缓冲机制来优化CPU和GPU的效率,也就是在CPU和GPU的空闲时间再渲染一个区域。

总的来说:

  • 屏幕卡顿的根本原因:CPU 和 GPU 渲染流水线耗时过长,导致掉帧。
  • Vsync 与双缓冲的意义:强制同步屏幕刷新,以掉帧为代价解决屏幕撕裂问题。
  • 三缓冲的意义:合理使用 CPU、GPU 渲染性能,减少掉帧次数。

上述我们介绍了iOS中将内容数据通过一系列渲染后放到屏幕的详细过程,接下来将会讲解iOS的渲染框架,iOS 提供了多个渲染框架,帮助开发者管理渲染流程中的各个步骤。

见下图:

GPU Driver:上述软件框架相互之间也有着依赖关系,不过所有框架最终都会通过 OpenGL 连接到 GPU Driver,GPU Driver 是直接和 GPU 交流的代码块,直接与 GPU 连接。

OpenGL:是一个提供了 2D 和 3D 图形渲染的 API,它能和 GPU 密切的配合,最高效地利用 GPU 的能力,实现硬件加速渲染。OpenGL的高效实现(利用了图形加速硬件)一般由显示设备厂商提供,而且非常依赖于该厂商提供的硬件。OpenGL 之上扩展出很多东西,如 Core Graphics 等最终都依赖于 OpenGL,有些情况下为了更高的效率,比如游戏程序,甚至会直接调用 OpenGL 的接口。

Core Graphics:Core Graphics 是一个强大的二维图像绘制引擎,是 iOS 的核心图形库,常用的比如 CGRect 就定义在这个框架下。

Core Animation在 iOS 上,几乎所有的东西都是通过 Core Animation 绘制出来,它的自由度更高,使用范围也更广。

Core Image:Core Image 是一个高性能的图像处理分析的框架,它拥有一系列现成的图像滤镜,能对已存在的图像进行高效的处理。

Metal:Metal 类似于 OpenGL ES,也是一套第三方标准,具体实现由苹果实现。Core Animation、Core Image、SceneKit、SpriteKit 等等渲染框架都是构建于 Metal 之上的。

我们可以看到,在iOS上,几乎所有的东西都是通过 Core Animation 绘制出来,接下来我们深入了解Core Animation。

Core Animation:

Core Animation,它本质上可以理解为一个复合引擎,主要职责包含:渲染、构建和实现动画。

Core Animation 是 AppKit 和 UIKit 完美的底层支持,同时也被整合进入 Cocoa 和 Cocoa Touch 的工作流之中,它是 app 界面渲染和构建的最基础架构。 Core Animation 的职责就是尽可能快地组合屏幕上不同的可视内容,这个内容是被分解成独立的 layer(iOS 中具体而言就是 CALayer),并且被存储为树状层级结构。这个树也形成了 UIKit 以及在 iOS 应用程序当中你所能在屏幕上看见的一切的基础。

简单来说就是用户能看到的屏幕上的内容都由 CALayer 进行管理。

CALayer 是屏幕显示的基础(存储 bitmap)

CALayer的简单构成:

在运行时,操作系统会调用底层的接口,将 image 通过 CPU+GPU 的渲染流水线渲染得到对应的 bitmap,存储于 CALayer.contents 中,在设备屏幕进行刷新的时候就会读取 bitmap 在屏幕上呈现。

也正因为每次要被渲染的内容是被静态的存储起来的,所以每次渲染时,Core Animation 会触发调用 drawRect: 方法,使用存储好的 bitmap 进行新一轮的展示。

CALayer 与 UIView 的关系

  1. CALayer 是 UIView 的属性之一,负责渲染和动画,提供可视内容的呈现
  2. UIView 提供了对 CALayer 部分功能的封装,同时也另外负责了交互事件的处理。

可得出其他关系:

相同的层级结构:我们对 UIView 的层级结构非常熟悉,由于每个 UIView 都对应 CALayer 负责页面的绘制,所以 CALayer 也具有相应的层级结构。

部分效果的设置:因为 UIView 只对 CALayer 的部分功能进行了封装,而另一部分如圆角、阴影、边框等特效都需要通过调用 layer 属性来设置。

是否响应点击事件:CALayer 不负责点击事件,所以不响应点击事件,而 UIView 会响应。

不同继承关系:CALayer 继承自 NSObject,UIView 由于要负责交互事件,所以继承自 UIResponder。

为什么要将CALayer和UIView分离开来?

将 CALayer 独立出来这样设计的主要原因就是为了职责分离,拆分功能,方便代码的复用。通过 Core Animation 框架来负责可视内容的呈现,这样在 iOS 和 OS X 上都可以使用 Core Animation 进行渲染。与此同时,两个系统还可以根据交互规则的不同来进一步封装统一的控件。

Core Animation的渲染流程:

(区别于前面讲的iOS渲染流流水线,两者均为iOS渲染基础但是服务的层次和方面不一样)

整个流水线一共有下面几个步骤:

Handle Events:这个过程中会先处理点击事件,这个过程中有可能会需要改变页面的布局和界面层次。

Commit Transaction:此时 app 会通过 CPU 处理显示内容的前置计算,比如布局计算、图片解码等任务,接下来会进行详细的讲解。之后将计算好的图层进行打包发给 Render Server

Decode:打包好的图层被传输到 Render Server 之后,首先会进行解码。注意完成解码之后需要等待下一个 RunLoop 才会执行下一步 Draw Calls

Draw Calls:解码完成后,Core Animation 会调用下层渲染框架(比如 OpenGL 或者 Metal)的方法进行绘制,进而调用到 GPU。

Render:这一阶段主要由 GPU 进行渲染。

Display:显示阶段,需要等 render 结束的下一个 RunLoop 触发显示。

深度了解Commit Transaction:

一般开发当中能影响到的就是 Handle Events 和 Commit Transaction 这两个阶段,这也是开发者接触最多的部分。Handle Events 就是处理触摸事件,而 Commit Transaction 这部分中主要进行的是:Layout、Display、Prepare、Commit 等四个具体的操作。

1.Layout:构建视图

这个阶段主要处理视图的构建和布局,具体步骤包括:

  1. 调用重载的 layoutSubviews 方法
  2. 创建视图,并通过 addSubview 方法添加子视图
  3. 计算视图布局,即所有的 Layout Constraint

由于这个阶段是在 CPU 中进行,通常是 CPU 限制或者 IO 限制,所以我们应该尽量高效轻量地操作,减少这部分的时间,比如减少非必要的视图创建、简化布局计算、减少视图层级等。

2.Display:绘制视图

这个阶段主要是交给 Core Graphics 进行视图的绘制,注意不是真正的显示,而是得到前文所说的图元 primitives 数据:

  1. 根据上一阶段 Layout 的结果创建得到图元信息。
  2. 如果重写了 drawRect: 方法,那么会调用重载的 drawRect: 方法,在 drawRect: 方法中手动绘制得到 bitmap 数据,从而自定义视图的绘制。

注意正常情况下 Display 阶段只会得到图元 primitives 信息,而位图 bitmap 是在 GPU 中根据图元信息绘制得到的。但是如果重写了 drawRect: 方法,这个方法会直接调用 Core Graphics 绘制方法得到 bitmap 数据,同时系统会额外申请一块内存,用于暂存绘制好的 bitmap。

由于重写了 drawRect: 方法,导致绘制过程从 GPU 转移到了 CPU,这就导致了一定的效率损失。与此同时,这个过程会额外使用 CPU 和内存,因此需要高效绘制,否则容易造成 CPU 卡顿或者内存爆炸。

3.Prepare:Core Animation 额外的工作

这一步主要是:图片解码和转换

4.Commit:打包并发送

这一步主要是:当 runloop 在 kCFRunLoopBeforeWaiting 和 kCFRunLoopExit 状态时,会通知注册的监听,然后对图层打包,打完包后,将打包数据发送给一个独立负责渲染的进程 Render Server。图层打包并发送到 Render Server。

注意 commit 操作是依赖图层树递归执行的,所以如果图层树过于复杂,commit 的开销就会很大。这也是我们希望减少视图层级,从而降低图层树复杂度的原因。

Render Server 的具体操作

Render Server 通常是 OpenGL 或者是 Metal。以 OpenGL 为例,那么上图主要是 GPU 中执行的操作,具体主要包括:

  1. GPU 收到 Command Buffer,包含图元 primitives 信息
  2. Tiler 开始工作:先通过顶点着色器 Vertex Shader 对顶点进行处理,更新图元信息
  3. 平铺过程:平铺生成 tile bucket 的几何图形,这一步会将图元信息转化为像素,之后将结果写入 Parameter Buffer 中
  4. Tiler 更新完所有的图元信息,或者 Parameter Buffer 已满,则会开始下一步
  5. Renderer 工作:将像素信息进行处理得到 bitmap,之后存入 Render Buffer
  6. Render Buffer 中存储有渲染好的 bitmap,供之后的 Display 操作使用

这里有张流程图总结的特别好:

以上就是iOS渲染的流程笔记。

 离屏渲染

离屏渲染发生在iOS的渲染流程中(CPU、GPU、双缓冲器、视频控制器、屏幕)。我们知道,图像处理基本上是在 GPU中进行的,而GPU屏幕渲染有以下两种方式:

1.On-Screen Rendering:当前屏幕渲染,指的是GPU的渲染操作是在当前用于显示的屏幕缓冲区中进行。

正常情况下,如果要在显示屏上显示内容,我们至少需要一块与屏幕像素数据量一样大的帧缓冲区(frame buffer),作为像素数据存储区域,而这也是GPU存储渲染结果的地方。

2.Off-Screen Rendering:离屏渲染,指的是GPU在当前屏幕缓冲区以外新开辟一个(离屏)缓冲区进行渲染操作。

如果有时因为一些限制,无法把渲染结果直接写入frame buffer,而是先暂存在另外的内存区域,之后再写入frame buffer,那么这个过程被称之为离屏渲染。

其实

离屏渲染是有坏处的:

1.需要开辟一个新的缓存区,影响app性能。

2.因为是新的缓存区,此时有两个缓存区,那么GPU就要进行上下文切换来分别渲染,而上下文切换的代价是巨大的,会导致掉帧甚至卡顿。

那么,什么时候会触发离屏渲染呢?

我们再回顾下面layer的简单构成:

对于特定图层效果的使用,比如圆角,图层遮罩,阴影或者是图层光栅化都会强制Core Animation提前渲染图层的离屏绘制(注意⚠️:一旦我们 为contents设置了内容 ,无论是图片、绘制内容、有图像信息的子视图等,再加上圆角+裁剪,就会触发离屏渲染,而当contens没有内容时,圆角和裁剪都不会触发离屏渲染)。也就是说,当layer的contens中有东西(图片,色彩等)时, GPU为了将所有该绘画的绘画完了,再去为这个“结果”添加阴影或圆角,那么就需要离屏渲染存储layer。也就是说:阴影的本体(layer和其子layer)都还没有被组合到一起,怎么可能在第一步就画出只有完成最后一步之后才能知道的形状呢?这样一来又只能另外申请一块内存,把本体内容都先画好。

至于优化的话,有以下几种解决方法:

1.缓存已经处理好的结果,然后在复用的时候再拿出来用,得用shouldRasterize, 但是这个会导致至少一次离屏渲染,不过相对于有许多layer都各离屏渲染一次,这样处理就优化很多了。如果你的layer本来并不复杂,也没有圆角阴影等等,打开这个开关反而会增加一次不必要的离屏渲染

2.贝塞尔曲线优化

推荐大佬文章Texture | Corner Rounding

参考:[转] iOS离屏渲染原理及优化 · Tenloy's Blog

Core-Animation(三) - 渲染流程探究及性能分析 · Tenloy's Blog

iOS 离屏渲染探究 - 掘金

https://github.com/RickeyBoy/Rickey-iOS-Notes/blob/master/%E7%AC%94%E8%AE%B0/iOS%20Rendering.md

渲染(iOS渲染过程解析)_ios渲染流程-CSDN博客

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

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

相关文章

安全政策与安全意识(下)

等保测评介绍及解决方案 目录 一, 等保介绍 1.1 分三个等级 1.2 等级保护发展历程 1.2.1 等保1.0 1.2.2 等保2.0 1.2.3 等保等级对比 1.3 等级保护依据的法律,法规 1.4 等级保护2.0的法规、标准体系 1.5 等级保护等级划分 1.6 等级保护政策内容 二, 等保必要性 三…

Zookeeper工作机制、特点、数据结构、应用场景、配置参数解读

ZK工作机制 从涉及模式角度来理解:是一个基于观察者模式设计的分布式服务管理框架,负责存储和管理大家都关心的数据,然后接受观察者的注册,一旦这些数据的状态发生变化,zk就负责通知已在zk上注册的那些观察者做出相应…

基于PHP的丽江旅游管理系统

有需要请加文章底部Q哦 可远程调试 基于PHP的丽江旅游管理系统 一 介绍 此丽江旅游系统基于原生PHP开发,数据库mysql,前端bootstrap。系统角色分为用户和管理员。 技术栈:phpmysqlbootstrapphpstudyvscode 二 功能 用户 1 注册/登录/注销…

Shopee哪些活动助力泰国卖家99大促销售额增长8倍?

9月11日,据外媒报道,Shopee 9.9大促已正式收官,活动上线仅18分钟泰国卖家就实现了10亿泰铢的销售额,创下新纪录。 Shopee泰国商业总监Karan Ambani表示,此次9.9大促成功彰显了平台通过超值优惠和便捷工具为用户提供优质…

什么麦克风最好,直播麦克风用哪种比较好,无线领夹麦克风推荐

无线领夹麦克风,作为现代演讲与录音领域的必备工具,但由于市场品牌繁多,很多消费者在选择时往往陷入困惑。根据市场反馈,大疆、西圣、罗德、猛犸等品牌在销量上均表现优异,其中西圣以其稳定传输与高保真音质&#xff0…

使用 SAX 在 TPU v5e 上部署和提供 Llama 2 模型

创建 TPU 以下步骤展示了如何创建用于您的模型的 TPU 虚拟机。 创建环境变量: export PROJECT_IDPROJECT_IDexport ACCELERATOR_TYPEACCELERATOR_TYPEexport ZONEZONEexport RUNTIME_VERSIONv2-alpha-tpuv5-liteexport SERVICE_ACCOUNTSERVICE_ACCOUNTexport TPU_…

总结中文纠错项目走过的那些坑(pycorrector)

一、项目地址及说明 pycorrector: 中文文本纠错工具。支持中文音似、形似、语法错误纠正,python3.8开发。 pycorrector实现了Kenlm、ConvSeq2Seq、BERT、MacBERT、ELECTRA、ERNIE、Transformer等多种模型的文本纠错,并在SigHAN数据集评估各模型的效果。…

【网络图】:附Origin详细画图教程

目录 No.1 理解网络图 No.2 画图流程 1 导入数据并绘图 2 设置绘图细节 3 效果图 No.1 理解网络图 网络图,是一种由节点(或顶点)和连接这些节点的边(或链路)组成的图形结构。在网络图中,节点通常代表…

OpenAI「草莓」两周内发布?网传不是多模态,反应慢了10多秒

就在刚刚,The Information曝出:OpenAI的草莓将于两周内上线!收费疑似200刀一个月,最大的特色就是比其他模型多思考10到20秒。然而因为「狼来了」太多回,网友们忍不住吐槽:OpenAI现在就是个炒作公司。 来源…

十,Spring Boot 的内容协商的详细剖析(附+Debug调试说明)

十,Spring Boot 的内容协商的详细剖析(附Debug调试说明) 文章目录 十,Spring Boot 的内容协商的详细剖析(附Debug调试说明)1. 基本介绍2. 准备工作3. 内容协商的本质4. 内容协商:注意事项和使用细节5. 总结:6. 最后: 1…

k8s环境搭建(续)

查看节点信息并做快照 kubectl get nodes 将components.yml文件上传到master主机 创建nginx,会在添加一个新的pod kubectl run nginx --imagesnginx:latest 查看nginx的pod信息 [rootk8s-master ~]# kubectl get po -Aowide|grep nginx 出现错误,查…

Python | Leetcode Python题解之第399题除法求值

题目: 题解: class Solution:def calcEquation(self, equations: List[List[str]], values: List[float], queries: List[List[str]]) -> List[float]:# 构造图graph defaultdict(list)for (u, v), value in zip(equations, values):graph[u].appen…

Vite + Electron 时,Electron 渲染空白,静态资源加载错误等问题解决

问题 如果在 electron 里直接引入 vite 打包后的东西,那么有些资源是请求不到的 这是我的引入方式 根据报错,我们来到 vite 打包后的路径看一看 ,修改一下 dist 里的文件路径试了一试 修改后的样子,发现是可以的了 原因分析 …

react 基础语法

前置知识 类的回顾 通过class关键字定义一个类 类名首字母大写 class类有constructor构造器 new 一个类得到一个实例 类还有方法,该方法也会在其原型上 static静态数据,访问静态属性通过 类名.id getter和setter getter:定义一个属性&…

渠道分析促增长,App如何靠渠道来源追踪构建评估体系

只要接触市场或运营工作,流量的投入产出细节就是必定要被追问的问题,碎片化的渠道营销和投入资源没有精细化管理的话,势必要面临以下诸多问题: 做了这么多地方的投放,哪个渠道效果最好?某个大主播确实给我…

猫鼠游戏: KaijiK病毒入侵溯源分析

1. 事件背景 近期,网宿平台某客户在使用云主机工作的时候突然出现主机卡顿,连接不稳定,网络断开的情况,并且收到了网宿主机入侵检测产品的告警信息。由于客户没有专职的安全人员,由运维人员兼任安全运营工作&#xff…

OA项目值用户登入首页展示

1.什么是OA 办公自动化(Office Automation,简称OA)是将现代化办公和计算机技术结合起来的一种新型的办公方式。办公自动化没有统一的定义,凡是在传统的办公室中采用各种新技术、新机器、新设备从事办公业务,都属于办公自动化的领域。通过实现办公自动化,或者说实现数字化…

微信小程序开发——比较两个数字大小

在这里我们使用的工具是 需要自行安装和配置。 在微信小程序中比较两个数字大小有以下几种方式: 一、普通条件判断 在小程序的.js 文件中,先定义两个数字,如let num1 5; let num2 3;。通过if - else if - else语句,根据num1与…

在VB.net中,DateTime类使用,举例说明

标题 在VB.net中,DateTime类使用,举例说明 前面学习相关 1.在VB.net中,如何把"20240906"转化成日期格式 2.在VB.net中 DateTime有什么属性与方法 3.在VB.net中,Stopwatch有什么属性与方法 正文 在VB.NET中,D…

vite + vue3 + ts 移动端开箱即用现代开发模板

中文 | English SouthernWind https://blog.csdn.net/nanchen_J?typeblog sw-template vite vue3 ts 移动端开箱即用现代开发模板 特点 🐶 Vite 的Vue3 的文件路由布局系统Mock 后续支持Api 自动引入组件自动引入VueUse 支持TypeScript 的Tailwind css 的暗…