曂沅仴駦 发表于 2025-3-14 02:40:41

Metal新特性:大幅度提升iOS端性能

如上图所示,我们可以利用近似大概是查找表的方式来替换复杂的运算。别的,我们可以将全精度的浮点数替换为半精度的浮点数。尽量避免隐式转换,避免32位浮点数的输入。以及确保全部的着色器都利用Metal的“-ffast-math”来进行编译。
2.Texture Read and Write

GPU通过Texture Processing Unit来处理纹理的读写操作。固然在读写的过程中也会碰到一些性能瓶颈问题。这里从读和写两个部门分别来给出优化点:


[*] Read
https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8zM1AyRmRBbmp1OWliYXZ3ckJZTFZQU0FsOUF1MGljTWxQZ0FNaWFtMEZqRUVnTmZpYmNyVDM4MkVyeGZlZTdTUWFRMnhFQVhXQUQwWlBuZ3FUeFFncjJHTUEvNjQw?x-oss-process=image/format,png
如上图所示,我们可以尝试利用mipmaps。别的,可以思量更改过滤选项。例如,利用双线性代替三线性,降低像素巨细。确保利用了纹理压缩,对Asset利用块压缩(如ASTC),对运行时天生的纹理利用无损纹理压缩。


[*] Write
https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8zM1AyRmRBbmp1OWliYXZ3ckJZTFZQU0FsOUF1MGljTWxQMEVrVmdsWVBCYXhhZnRiQUZiM0tYbW1yUTRxVHU4MVUxSVJiaWFjSTh2SXBMcXNzZDlIOU9zZy82NDA?x-oss-process=image/format,png
如上图所示,我们应该留意到像素的巨细,以及每个像素中唯一MSAA样本的数量。别的,可以尝试一些优化一些逻辑写法。
✎  Tile Memory Load and Store

图块内存是一组存储Thread Group和ImageBlock数据的高性能内存。当从ImageBlock或是Threadgroup读取或写入像素数据时,比如在利用Tile着色器时大概是盘算分派时,可以访问到Tile内存。那当利用GPU性能计数器发现这个方面的性能瓶颈时,我们可以如下图所示进行优化。
https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8zM1AyRmRBbmp1OWliYXZ3ckJZTFZQU0FsOUF1MGljTWxQMEVrVmdsWVBCYXhhZnRiQUZiM0tYbW1yUTRxVHU4MVUxSVJiaWFjSTh2SXBMcXNzZDlIOU9zZy82NDA?x-oss-process=image/format,png
思量淘汰threadgroup的并行,大概是SIMD/Quadgroup操作。别的,确保将线程组的内存分配和访问对齐到16字节。末了,可以思量重新排序内存访问模式。
✎  Buffer Read and Write

在Metal中,缓冲区只被着色器核心访问。在这个地方发现了性能瓶颈。我们可以如下图所示进行优化:
https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8zM1AyRmRBbmp1OWliYXZ3ckJZTFZQU0FsOUF1MGljTWxQMEVrVmdsWVBCYXhhZnRiQUZiM0tYbW1yUTRxVHU4MVUxSVJiaWFjSTh2SXBMcXNzZDlIOU9zZy82NDA?x-oss-process=image/format,png
可以更大力大举度的压缩打包数据,例如利用例如packed_half3这样小的类型。别的,可以尝试向量化加载和存储。例如利用SIMD类型。避免寄存器溢出,以及可以利用纹理来均衡工作负载。
✎  GPU Last Level Cache

如果在这个方面,我们的GPU性能计数器显示一个过高的值。我们可以如下图这样优化:
https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8zM1AyRmRBbmp1OWliYXZ3ckJZTFZQU0FsOUF1MGljTWxQUWlhVzRLSWliNDBCUjQwaWM1dHNLWnVWaG9RWlFwQXFGVTFoVkt1YVhnQVF5QzdvWGt3dGJVNFRnLzY0MA?x-oss-process=image/format,png
如果纹理大概是缓存区也同样显示一个过高的值,我们可以把这个优化放到第一优先级。我们可以思量减小工作集的巨细。如果Shader正在利用Device Atomics,我们可以尝试重构我们的代码来利用Threadgroup Atomics。
✎  Fragment Input Interpolation

分段输入插值。分段输入在渲染阶段由着色器核心进行插值。着色器核心有一个专用的分段输入插值器。这个是比较固定和高精度的功能。我们能优化的点不多,如下图所示:
https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8zM1AyRmRBbmp1OWliYXZ3ckJZTFZQU0FsOUF1MGljTWxQUWlhVzRLSWliNDBCUjQwaWM1dHNLWnVWaG9RWlFwQXFGVTFoVkt1YVhnQVF5QzdvWGt3dGJVNFRnLzY0MA?x-oss-process=image/format,png
尽可能的移除传递给分段着色器的极点属性。
▐  内存带宽

内存带宽也是影响我们GPU性能的一个重要因素。如果在GPU性能计数器的内存带宽模块看到一个很高的值。我们就应该如下图所示来进行优化:
https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8zM1AyRmRBbmp1OWliYXZ3ckJZTFZQU0FsOUF1MGljTWxQR2ljZEtJcEFndkZwcUU3UHNpYzNmaWN6T1AzYmxVYWN2R0M4QXRqaWM3Q3FXQlJSVHUxTlJtY3VGUS82NDA?x-oss-process=image/format,png
如果纹理和缓存区也同样显示比较高的值,那优化优先级应该排到第一位。优化方案也是较少Working Set的巨细。别的,我们应该只加载当前渲染过程需要的数据,只存储未来渲染过程需要的数据。然后就是确保利用纹理压缩。
▐  Occupancy

https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8zM1AyRmRBbmp1OWliYXZ3ckJZTFZQU0FsOUF1MGljTWxQWUdtTzJ2cUNocTExclZRSkpqbEQweDlpYVZhRkRMUEQ1VjFxckhWeXVoQWE2enEwNGZ3T251US82NDA?x-oss-process=image/format,png
如果我们看到整体利用率比较低,这意味着Shader可能已经耗尽了一些内部资源,比如tile大概threadgroup内存。也可能是线程完成执行的速率比GPU创建新线程的速率快。
▐  避免重复绘制

https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8zM1AyRmRBbmp1OWliYXZ3ckJZTFZQU0FsOUF1MGljTWxQOGljYWhRN2hUdUM5Y3c1dGJGWE5xb0FpYUNlSEtkNUhFN2FCdXlLMFVzWHlYcUVSaHlNWDJ5aWNnLzY0MA?x-oss-process=image/format,png
我们通过GPU计数器可以统计到重复绘制的区域,我们应该高效利用HSR来避免这样的重绘。我们可以如图所示的顺序来进行绘制。
Build GPU binaries with Metal
这一章主要给开发者们先容了一种利用Metal的编程工作流,可以通过优化Metal的渲染编译模型来增强渲染管线,这个优化可以在应用步伐启动,特别是初次启动时大大淘汰PSO(管线状态对象)的加载时间。可以让我们的图形渲染更加的高效。整个章节主要分为四个部门:
▐  Metal的Shader编译模型概述

众所周知,Metal Shading Language是Apple为开发者提供的Shader编程语言,Metal会将编程语言编译成为一个叫做AIR的中间产物,然后AIR会在装备上进一步编译,天生每个GPU所需的特定的机器码。整个过程如下图所示:
https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8zM1AyRmRBbmp1OWliYXZ3ckJZTFZQU0FsOUF1MGljTWxQZzRaRmtzenRzcUlkcDRWaWMyU0ZGR2VMV0NicUI3MlBYYnBXeVRiMDdnc1JtMzl4bzJyNkZYQS82NDA?x-oss-process=image/format,png
上述过程在每个管线的生命周期中都会发生,当前Apple为了加快管线的重新编译和重新创建流程,会缓存一些Metal的方法变体,但是这个过程还是会造成屏幕的加载耗时过长。而且在当前的这个编译模型中,应用步伐不能在差别的PSO(管线状态对象)中重用之宿世成的机器码子步伐。
所以我们需要一种方法来淘汰这个整个管线编译(即源代码->AIR->GPU二进制代码)的时间成本,还需要一种机制来支持差别PSO之间共享子步伐和方法,这样就不需要将相同的代码多次编译大概是多次加载到内存中。这样开发者们就可以利用这套工具来优化App初次的启动体验。
▐  Metal二进制文件先容

Metal二进制文件就是办理上述需求的方法之一,如今开发者们可以直接利用Metal为二进制文件来控制PSO的缓存。开发者可以收集已编译的PSO,然后将它们存储到装备中,甚至可以分发到其他兼容的装备中(同样的GPU和同样的操作体系),这种二进制文件可以看做一种Asset。下面是一些例程和表示图:
https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8zM1AyRmRBbmp1OWliYXZ3ckJZTFZQU0FsOUF1MGljTWxQbVJhTXhMcGt5TjhPNEM3d3ozMWlhaHRNVUFjek5ublV5dmp0NmZWREYxMXNVUWFSQmExSWpZdy82NDA?x-oss-process=image/format,png
//创建一个空的二进制文件
let descriptor = MTLBinaryArchiveDescriptor()
descriptor.url = nil
let binaryArchive = try device.makeBinaryArchive(descriptor:descriptor)
https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8zM1AyRmRBbmp1OWliYXZ3ckJZTFZQU0FsOUF1MGljTWxQV2NoTTFBT3NueklXZ3V2Y2x5bzhwSndmaktrNGJxN0lBZENnVnRmUHpOMVd3UmFBWG10MGFRLzY0MA?x-oss-process=image/format,png
//Populating an archive
// Render pipelines
try binaryArchive.addRenderPipelineFunctions(with: renderPipelineDescriptor)
// Compute pipelines
try binaryArchive.addComputePipelineFunctions(with: computePipelineDescriptor)
// Tile render pipelines
try binaryArchive.addTileRenderPipelineFunctions(with: tileRenderPipelineDescriptor)
https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8zM1AyRmRBbmp1OWliYXZ3ckJZTFZQU0FsOUF1MGljTWxQRUdZZ3VuSmZlbHBpYU4ySE81RXphZFR5YmRsWXJNemRGeU1kSDNybnJvNmw1THJnTTdpYjZ5M0EvNjQw?x-oss-process=image/format,png
//重用已编译的方法
// Reusing compiled functions to build a pipeline state object from a file
let renderPipelineDescriptor = MTLRenderPipelineDescriptor()
// …
renderPipelineDescriptor.binaryArchives = [ binaryArchive ]
let renderPipeline = try device.makeRenderPipelineState(descriptor:
renderPipelineDescriptor)
//序列化
let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let archiveURL = documentsURL.appendingPathComponent(“binaryArchive.metallib”)
try binaryArchive.serialize(to: NSURL.fileURL(withPath: archiveURL))
//反序列化
let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let serializeURL = documentsURL.appendingPathComponent(“binaryArchive.metallib”)
let descriptor = MTLBinaryArchiveDescriptor()
descriptor.url = NSURL.fileURL(withPath: serializeURL)
let binaryArchive = try device.makeBinaryArchive(descriptor: descriptor)
总的来说就是这个Metal二进制文件可以提供开发者手动管理管线缓存的方法,这样就可以从一个装备中获取这些文件并摆设到其他兼容的装备上,在iOS环境下,极大地淘汰了第一次安装游戏或应用以及装备重启后的管道创建时间。可以优化应用的初次启动体验和冷启动体验。
▐  Metal对动态库的支持

动态库将答应开发者编写可重用的库代码,却可以淘汰重新编译步伐的时间和内存成本,这个特性将会答应开发者将盘算着色器和步伐库动态链接。而且和二进制文件一样,动态库也是可序列化和可转移的。这也是办理上述需求的方案之一。
在PSO天生的时候,每个应用步伐都需要为步伐library天生机器码,而且利用相同的步伐库编译多个管线会导致天生重复的机器码。由于大量的编译和内存的增加,这个可能会导致更长的管线加载时间。而动态库就可以办理这个问题。
Metal Dynamic Library答应开发者以机器码的情势动态链接,加载和共享工具方法。代码可以在多个盘算管线中重用,消除了重复编译和多个相同子步伐的存储。而且这个 MTLDynamicLibrary是可序列化的,可以作为应用步伐的Asset利用。MTLDynamicLibrary其实就是多个盘算管线调用的导出方法的聚集。
大抵的工作流程如下:我们首先创建一个MTLLibrary作为我们指定的动态库,这个可以将我们的metal代码编译为AIR。然后我们调用方法makeDynamicLibrary,这个方法需要指定一个唯一的installname,在管线创建时,linker将会利用这个名字来加载动态库。这个方法可以将我们的动态库编译成为机器码。这就完成了动态库的创建。
对于动态库的利用来说:通过设置MTLCompileOptions里的libraries参数,就可以完成动态库的加载和利用了。代码如下:
//利用动态库进行编译
let options = MTLCompileOptions()
options.libraries = [ utilityDylib ]
let library = try device.makeLibrary(source: kernelStr, options: options)


▐  开发工具先容

这个部门主要先容了构建Metal二进制文件和构建动态库的具体工具和方法。以视频的情势可能会更好的体现,详情可见:Build GPU binaries with Metal (从22:51开始)
Debug GPU-side errors in Metal
这一章主要先容的是GPU侧的bug,当前如果我们的应用步伐出现了GPU侧的bug,他的错误日记常常都不能让开发者很直观的定位到错误的代码范围和调用栈。所以在最新的Xcode中,增强了关于GPU侧的debug机制。可以像在代码侧发成的错误一样不但能定位到错误缘故原由,另有错误的调用堆栈和各种信息都可以具体的查看到。让开发者能更好的修复代码造成的GPU侧的渲染错误。
▐  Enhanced Command Buffer Errors

https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8zM1AyRmRBbmp1OWliYXZ3ckJZTFZQU0FsOUF1MGljTWxQeGNYMzZWU2NydFppYXB5QTNpYnlCYW5qNmFFa1NhZjlTWDNBQ2N2OU5rbUowdEhKbzZadUhLVUEvNjQw?x-oss-process=image/format,png
这是当前的错误日记上报,我们可以看到GPU侧的错误日记不像Api的错误日记一样可以让开发者很快的定位到错误缘故原由和错误的代码位置。
https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8zM1AyRmRBbmp1OWliYXZ3ckJZTFZQU0FsOUF1MGljTWxQNUNJdmI2bEp3bUNhOTJuS0I4RVZubUl5Y2I4NDlRVnNTOEhuNElBMThheWNMWGljczhVV05QQS82NDA?x-oss-process=image/format,png
而最新的Metal debugging工具就增强了这方面的能力,让Shader的code也可以像Api代码一样提供错误定位和分类能力。
我们通过以下代码便可以启用增强版的commandbuffer错误机制
//启用增强版的commandbuffer错误机制
let desc = MTLCommandBufferDescriptor()
desc.errorOptions = .encoderExecutionStatus
let commandBuffer = commandQueue.makeCommandBuffer(descriptor: desc)
错误一共有五种状态:
https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8zM1AyRmRBbmp1OWliYXZ3ckJZTFZQU0FsOUF1MGljTWxQYlJwQ2FYYWlhRmFNbGF5TlRNOU1pY1JOdXE1ZnlZSTNaUWs5MmljSjhTSjBOZE0zV25Ecmh1NFFBLzY0MA?x-oss-process=image/format,png
我们也可以通过以下代码来打印error:
//打印commandbuffer的错误
if let error = commandBuffer.error as NSError? {
if let encoderInfos =
error.userInfo
as? {
for info in encoderInfos {
print(info.label + info.debugSignposts.joined())
if info.errorState == .faulted {
print(info.label + " faulted!")
}
}
}
}
开发者可以在开发时和测试时启用优化版的错误机制
https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8zM1AyRmRBbmp1OWliYXZ3ckJZTFZQU0FsOUF1MGljTWxQTmpSYVBjbHA5aWNReTdmbTY3VHZ6ZThBZlZCZDRFaWFGTFIyaWN1QWRSdWN2Y1dSUjN5UFZLMUJBLzY0MA?x-oss-process=image/format,png


▐  Shader Validation

https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8zM1AyRmRBbmp1OWliYXZ3ckJZTFZQU0FsOUF1MGljTWxQNjhVbFBhb093ekwxbmRueWljS1d1NmhPenBmSTBTVTl4cmNNOWtRSUg4UVBzNFpwMXltVFBuZy82NDA?x-oss-process=image/format,png
如上图所示,这个功能可以在GPU侧发生渲染错误时自动定位和catch到错误并定位到代码,以及获取回溯栈帧。
我们可以在Xcode中按照以下流程来开启这个功能:
1.开启Metal中的两个Validation选项
https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8zM1AyRmRBbmp1OWliYXZ3ckJZTFZQU0FsOUF1MGljTWxQanc5S1RXS1U3N2Y3SUdVQ25TR25nM1htQ3BOWUNMQUtndmJmYm13aG1wbk95cHk3NUU3MDlnLzY0MA?x-oss-process=image/format,png
2.开启issue自动断点开关并配置类型和分类等选项
https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8zM1AyRmRBbmp1OWliYXZ3ckJZTFZQU0FsOUF1MGljTWxQaGxXRTlqWGliUzF1Ujd2UGRtQlhtQW14enJFYVBnMmliQ0tRbUQ1N3BQVDBYVVR4SmFGVUR6ZHcvNjQw?x-oss-process=image/format,png
Video中用了一个demo来展示整个工作流,具体参见Debug GPU-side errors in Metal(11:25~14:45)大抵流程如下图所示:
https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8zM1AyRmRBbmp1OWliYXZ3ckJZTFZQU0FsOUF1MGljTWxQekFLNU1wVm0xbm5pY1UzdDIzcnB4ZGJIRE5QTVB6TzdpY3lQY0VaaWNUeEN5YkdpY1pzU0IyaWFhdkEvNjQw?x-oss-process=image/format,png
这是一个Demo应用步伐,很明显它在渲染上出现了一些非常,但是因为是GPU侧的问题,所以开发者很难定位。但是通过上述的工作流开启Shader Validation之后。
https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8zM1AyRmRBbmp1OWliYXZ3ckJZTFZQU0FsOUF1MGljTWxQUVpKNzZpY3pOOHljeVJRNUFjZEw5Sm1ZWGtFMGdVeDB1T3IyN0tGdWRIRkFNSFp6OXhDYW5Ddy82NDA?x-oss-process=image/format,png
Xcode会自动断点到发生非常的地方,并展示出非常信息,这样就可以极大的提升开发者的错误修复服从。
Gain insights into your Metal app with Xcode 12
这一章主要讲的是Xcode12给Metal App提供了更多调试和分析的新工具。大抵如下图所示:
https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8zM1AyRmRBbmp1OWliYXZ3ckJZTFZQU0FsOUF1MGljTWxQSjhvcWc5NFgwR0xyNkhpYktDZktDeGliUTU0dGM0cUZXZTgyaElCNXFuYmliN3JwYjFxUzZueFVnLzY0MA?x-oss-process=image/format,png
主要分为两个部门:
▐  Metal Debugger

这个工具可以让开发者在App运行时,获取到想分析和调试的任何一帧,然后再进入Xcode提供的各种分析界面,总体环境,依赖环境,内存,带宽,GPU,Shader等各种具体的界面来对这一帧进行更加具体的分析和调试。整个过程利用视频的方式可能会更加高效,所以这里不会进行具体的赘述和分析。详情可以参见 Gain insights into your Metal app with Xcode 12


▐  Metal System Trace

整个工具跟之前提到过的Debugger相比,他的功能主要是让开发者可以随着时间的推移来捕获应用步伐的各种信息和特性,可以让开发者很好的调试一些例如终端,帧丢失,内存泄漏等问题。而Debugger主要是对某一帧进行调试和分析。
他提供了一个叫做编码时间线的工具,可以让开发者查看到GPU在应用运行中的运行各种命令缓冲的环境。然后提供了一个叫做着色器时间线的工具,可以让开发者查看到各种着色器在代码运行期间运行的过程。然后另有GPU计数器的工具,这个工具我们在前文进行了具体的分析,主要是用于办理GPU的绘制性能问题的工具。然后末了一个工具就是内存分配跟踪工具,可以让开发者查看到应用步伐运行过程中各种内存的分配和开释,可以帮助开发者办理内存泄漏问题大概是降低应用内存占用。
技能启发与思考
WWDC 20关于Metal的Session中,比较重要的就是官方提供了许多可供开发者进行GPU级别的调试工具以及性能分析工具。给比较成熟庞大而复杂的工程突破性能瓶颈,提供更加优秀的用户体验提供了一些思路。
https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8zM1AyRmRBbmp1OWliYXZ3ckJZTFZQU0FsOUF1MGljTWxQZFJWZnlVWEJ0cnVFaWJaaWFTRTdIMGlhT0VWNXR6VEZpYk1jZXBoWTkzSnNIQWljM0M1WktDS0NPbWcvNjQw?x-oss-process=image/format,png
闲鱼作为一个电商类App,随着功能和增多和以及工程的复杂化,在所难免的会碰到性能瓶颈,而闲鱼团队当前面临挑战的方式是从工程级别来进行优化。从Flutter的角度来看,WWDC 20 对于Metal的调试工具和性能分析工具的完善,无疑提供了更多的优化思路。这为未来运行在iOS上的应用的调优和突破性能瓶颈带来了新的思路和可能性。
https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8zM1AyRmRBbmp1OWliYXZ3ckJZTFZQU0FsOUF1MGljTWxQQWljTU00T3d5TzZIUmtQV2lhM0thb1ZCU3cxUllOTXlVQ3VpY1VQVnVFNWdjRXZDaWM5TGUyTGVOUS82NDA?x-oss-process=image/format,png
对于跨平台框架,Apple有自家的SwiftUI,这也是此次大会的重点项目。不外无论是Flutter,还是SwiftUI,大家末了对应用的性能瓶颈突破和优化一定是殊途同归的,也就是深入到GPU级别来进行开发和调试以及性能分析。对于未来的客户端开发人员,理解GPU和进行GPU级别的编程肯定是不可或缺的技能点之一。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: Metal新特性:大幅度提升iOS端性能