圆形路标

In one of the sprints, we were tasked with implementing the generation of a pdf-document on the client-side. We completed the task. But we wanted to make sure the effectiveness of the technical nuances of the decision. Signpost helped us with this. Using it we increased he document’s displaying speed several times.
在其中一个冲刺中,我们的任务是在客户端实现pdf文档的生成。 我们完成了任务。 但是我们要确保该决定的技术细微差别的有效性。 路标帮助了我们。 使用它,我们将文档的显示速度提高了数倍。
To learn more about os_signpost application technology, see where it can help you and how it has already helped us, go further forward.
要了解有关os_signpost应用程序技术的更多信息,请参见os_signpost应用程序技术在哪些方面可以为您提供帮助以及如何为我们提供帮助,请继续前进。

深潜 (Deepdive)

There are lot of applications on the user's mobile device, and all of them use common system resources, such as: CPU, RAM, network, battery, etc. If your application performs its tasks and does not crash, it doesn’t mean that it works efficiently and correctly.
用户的移动设备上有很多应用程序,并且它们都使用公用的系统资源,例如:CPU,RAM,网络,电池等。如果您的应用程序执行了任务并且没有崩溃,则并不意味着它有效且正确地工作。
Below we describe the cases that you may potentially encounter.
下面我们描述您可能遇到的情况。

次优算法可能导致较长的CPU负载 (Suboptimal algorithm can lead to a long CPU load)

  • At the start of the application, after 20 seconds of waiting, the system will shut down the application, and the user will not even see the app's first screen. In this case, the system will set a crash report, the distinguishing feature of which will be an exception type — EXC_CRASH (SIGKILL), type 0x8badf00d.在应用程序启动时,等待20秒后,系统将关闭该应用程序,并且用户甚至不会看到该应用程序的第一个屏幕。 在这种情况下,系统将设置一个崩溃报告,其区别特征是异常类型EXC_CRASH(SIGKILL),类型为0x8badf00d。
  • Resource-intensive processes in the background thread can affect the responsiveness of the UI, increase battery consumption and force the application to terminate the system (in case of prolonged CPU overheating).后台线程中的资源密集型进程可能会影响UI的响应能力,增加电池消耗并迫使应用程序终止系统(如果CPU长时间长时间过热)。

低内存 (Low RAM)

The specifications for the phones on the Apple website do not provide information on RAM, but other sources provide the following memory allocation for phone models:
Apple网站上的电话规格未提供有关RAM的信息,但是其他来源为电话型号提供了以下内存分配:

Type 4S 5 5C 5S 6 6P 6S 6SP
RAM, Gb 0.5 1 1 1 1 1 2 2
类型 4S 5 5C 5S 6 6P 6S 6SP
内存,Gb 0.5 1个 1个 1个 1个 1个 2 2
Type SE X 7 7P 8 8P XS XSM XR
RAM, Gb 2 3 2 3 2 3 4 4 3
类型 东南 X 7 7P 8 8P XS XSM XR
内存,Gb 2 3 2 3 2 3 4 4 3
  • When there is too little free RAM, iOS starts looking for memory to free up, simultaneously sending a memory warning to all running applications. This process implicitly affects the CPU and battery of the device. If the memory warning is ignored, and the allocation of memory continues, the system forcibly terminates the application process. For the user, this looks like crash, with no backtraces in the crash report.当可用内存太少时,iOS将开始寻找要释放的内存,同时向所有正在运行的应用程序发送内存警告。 此过程隐式影响设备的CPU和电池。 如果忽略内存警告,并且继续分配内存,则系统将强制终止应用程序进程。 对于用户而言,这看起来像崩溃,崩溃报告中没有回溯。
  • Excessive use of network requests. This also leads to a battery-life decreasing. Duplication of requests and / or lack of cancellation of unnecessary requests additionally leads to inefficient use of the CPU.过度使用网络请求。 这也导致电池寿命的减少。 请求重复和/或缺少不必要请求的取消还导致CPU使用效率低下。
  • Do not forget about CoreLocation. The more often and more accurately we request the user's location, the more the device’s battery is spent. 不要忘记CoreLocation。 我们请求用户位置的频率越高,越准确,设备的电池消耗就越多。

To verify the correctness of processing the described cases, we suggest using os_signpost to profile the application processes and then analyze the data obtained.
为了验证处理上述情况的正确性,我们建议使用os_signpost对应用程序进行概要分析,然后分析所获得的数据。

项目中的OSLog集成 (OSLog integration in the project)

At the top level, the process of creating a PDF consists of three steps:
在顶层,创建PDF的过程包括三个步骤:

  1. Receiving data over the network;通过网络接收数据;
  2. Document formation;文件形成;
  3. Document displaying on the screen屏幕上显示的文件

We decided to split and log the stages of document generation, starting from the user clicking the «Generate» button and ending with the display of the document on the screen.
我们决定拆分并记录文档生成的各个阶段,从用户单击“生成”按钮开始,直到在屏幕上显示文档为止。
Suppose we are faced with the task of analyzing an asynchronous network request. The markup in the code will look like this:
假设我们面临分析异步网络请求的任务。 代码中的标记将如下所示:

import os.signpostlet pointsOfInterestLog = OSLog(subsystem: "com.example.your-app", category: . pointsOfInterest)
let networkLog = OSLog(subsystem: "com.example.your-app", category: "NetworkOperations")os_signpost(.event, log: pointsOfInterestLog, name: "Start work")
os_signpost(.begin, log: networkLog, name: "Overall work")for element in elements {os_signpost(.begin, log: networkLog, name: "Element work")makeWork(for: element)os_signpost(.end, log: networkLog, name: "Element work")
}os_signpost(.end, log: networkLog, name: "Overall work")

Steps for using signpost are as follows:
使用路标的步骤如下:

  • Import the os.signpost framework.导入os.signpost框架。
  • Create an instance of OSLog. It is worth considering that there are several types of events: for interval events (for example, a network request), you can use an arbitrary category, and for simultaneous events (for example, clicking a button), the predefined category pointsOfInterest / OS_LOG_CATEGORY_POINTS_OF_INTEREST.创建一个OSLog实例。 值得考虑的事件有几种类型:对于间隔事件(例如,网络请求),可以使用任意类别;对于同时发生的事件(例如,单击按钮),可以使用预定义的类别pointsOfInterest / OS_LOG_CATEGORY_POINTS_OF_INTEREST 。
  • For interval events, call the os_signpost function with the .begin and .end type at the beginning and at the end of the stage under investigation. For simultaneous events, use the .event type.对于间隔事件,请在调查阶段的开始和结束时使用.begin和.end类型调用os_signpost函数。 对于同时发生的事件,请使用.event类型。
  • If the code can be executed asynchronously, then add a Signpost ID, which will allow you to separate the intervals of the same type of operations with different objects.如果代码可以异步执行,则添加路标ID,这将使您可以将具有不同对象的同一类型操作的间隔分开。
  • Optionally, you can add additional data (metadata) to dispatched events. For example, the size of the images downloaded or the number of the generated PDF page. Such information will help to understand what exactly happens in the investigated stage of code execution.(可选)您可以将其他数据(元数据)添加到调度的事件中。 例如,下载的图像大小或生成的PDF页面数。 这些信息将有助于了解在代码执行的调查阶段究竟发生了什么。

Similarly on obj-c:
同样在obj-c上:

@import os.signpost;os_log_t pointsOfInterestLog = os_log_create("com.example.your-app",   OS_LOG_CATEGORY_POINTS_OF_INTEREST);
os_log_t networkLog = os_log_create("com.example.your-app",   "NetworkOperations");
os_signpost_id_t operationIdentifier = os_signpost_id_generate(networkLog);os_signpost_event_emit(pointsOfInterestLog, operationIdentifier, "Start work");
os_signpost_interval_begin(networkLog, operationIdentifier, "Overall work");for element in elements { os_signpost_id_t elementIdentifier = os_signpost_id_make_with_pointer(networkLog, element);os_signpost_interval_begin(networkLog, elementIdentifier, "Element work");[element makeWork];os_signpost_interval_end(networkLog, elementIdentifier, "Element work");
}os_signpost_interval_end(networkLog, operationIdentifier, "Overall work");

Note that if the project should run on iOS prior to version 12.0, Xcode will offer to wrap os_signpost calls in the if #available construct. In order not to clutter up the code, you can put this logic in a separate class.
请注意,如果项目应在12.0版之前的iOS上运行,则Xcode会将os_signpost调用包装在if #available结构中。 为了不使代码混乱,可以将此逻辑放在单独的类中。
It is worth considering that os_signpost requires a static string literal as the parameter of the event name. To add more stringent typing, you can create an enum with event types, and in the class implementation, map them to string literals. Putting OSLog in a separate class will add the logic to disable it for the release scheme (there is a separate OSLog command for this).
值得考虑的是,os_signpost需要静态字符串文字作为事件名称的参数。 要添加更严格的类型,可以创建具有事件类型的枚举,然后在类实现中将它们映射到字符串文字。 将OSLog放在单独的类中将添加逻辑以针对发布方案禁用它(为此存在单独的OSLog命令)。

import os.signpostlet networkLog: OSLogif ProcessInfo.processInfo.environment.keys.contains("SIGNPOSTS_FOR_NETWORK") {networkLog = OSLog(subsystem: "com.example.your-app", category: "NetworkOperations"
} else {    networkLog = .disabled
}

You can add values from any properties to the event marking with the following type decoders for convenient formatting:
您可以使用以下类型解码器将任何属性的值添加到事件标记中,以方便格式化:

Value type Custom specifier Example output
time_t %{time_t}d 2016-01-12 19:41:37
timeval %{timeval}.*P 2016-01-12 19:41:37.774236
timespec %{timespec}.*P 2016-01-12 19:41:37.2382382823
errno %{errno}d Broken pipe
iec-bytes %{iec-bytes}d 2.64 MiB
bitrate %{bitrate}d 123 kbps
iec-bitrate %{iec-bitrate}d 118 Kibps
uuid_t %{uuid_t}.*16P
%{uuid_t}.*P
10742E39-0657-41F8-AB99-878C5EC2DCAA
值类型 自定义说明符 输出示例
time_t %{time_t} d 2016-01-12 19:41:37
时间间隔 %{timeval}。* P 2016-01-12 19:41:37.774236
时间规格 %{timespec}。* P 2016-01-12 19:41:37.2382382823
埃尔诺 %{errno} d 断管
字节 %{iec-bytes} d 2.64 MiB
比特率 %{bitrate} d 123 kbps
比特率 %{iec-bitrate} d 118千bps
uuid_t %{uuid_t}。* 16P
%{uuid_t}。* P
10742E39-0657-41F8-AB99-878C5EC2DCAA

Now, when profiling the application, events from os_signpost will be sent to Instruments in the form of tabular data. To switch to tools, use the keyboard shortcut Cmd + I, then select the tool necessary for profiling. To see the marked data, just turn on the os_signpost and Point of Interest tools on the right side of the tool interface.
现在,在对应用程序进行性能分析时,来自os_signpost的事件将以表格数据的形式发送到Instruments。 要切换到工具,请使用键盘快捷键Cmd + I,然后选择进行分析所需的工具。 要查看标记的数据,只需打开工具界面右侧的os_signpost和Point of Interest工具。

By default, events are grouped into categories and displayed in a table, where their number and statistics on runtime are calculated. Additionally, there is a graphical display on the timeline, which makes it easy to compare the received events with the results in other tools. There is also the possibility of customizing the display of statistics and writing expert systems — but this topic deserves a separate article.
默认情况下,事件被分组并显示在表格中,在表格中计算事件的数量和统计信息。 此外,时间轴上有图形显示,可轻松将接收到的事件与其他工具中的结果进行比较。 也可以自定义统计数据的显示并编写专家系统,但是该主题值得另作文章。

使用实例 (Examples of using)

情况1。 PDFKit与WKWebView (Case #1. PDFKit vs WKWebView)

Through the use of os_signpost, we saw that for small documents (a couple of pages) the longest step was the last step — displaying the document — rather than working with a network or graphics. This led us to the decision to replace WKWebView with PDFView, which accelerated the display of the document from 1.5 seconds to 30 milliseconds. On the graphs, it looks like this:
通过使用os_signpost,我们看到对于小型文档(几页),最长的一步是最后一步-显示文档-而不是使用网络或图形。 这导致我们决定将WKWebView替换为PDFView,从而将文档的显示时间从1.5秒加速到30毫秒。 在图形上,它看起来像这样:

Rendering PDF document (WKWebView) in time profiler. 时间分析器中呈现PDF文档(WKWebView)

time profiler.时间分析器中呈现PDF文档(PDFView)。
The resulting data can be implemented in other tools that Xcode provides. As the Allocations tool showed, the gain in download speed was achieved by increasing the use of RAM.
所得数据可以在Xcode提供的其他工具中实现。 如分配工具所示,下载速度的提高是通过增加RAM的使用来实现的。

案例2低内存警告 (Case #2 LowMemory Warning)

A PDF document generates asynchronously, and its formation requires the allocation of a significant amount of memory. In case of insufficient memory, we decided to add the ability to stop the asynchronous operation of creating a document.
PDF文档是异步生成的,其形成需要分配大量的内存。 在内存不足的情况下,我们决定增加停止创建文档的异步操作的功能。
As you know, when using NSOperationQueue, the cancelAllOperation method frees an existing queue but does not stop already running operations. From this, we conclude that in the implementation of the operation it is necessary to periodically determine its condition and stop working. Thus freeing up resources if it is set to Canceled status.
如您所知,在使用NSOperationQueue时,cancelAllOperation方法将释放现有队列,但不会停止已在运行的操作。 由此得出的结论是,在实施该操作时,有必要定期确定其状况并停止工作。 如果设置为“取消”状态,则释放资源。
The next step is an asynchronous operation that we need to check for cancellation. But at the same time, it is not clear with what frequency to do this check. We had two options — line-by-line checking and page-by-page checking. os_signpost helped here too. As it turned out, adding a check for cancellation in the line-by-line cycle of rendering the table in the document, we increased the time it took to generate the document (by 150 pages) by 2 times. The second option was more optimal in terms of performance and actually did not increase the time it took to create the document. As a result, when we receive the memory warning event, we cancel the operation programmatically and display the error screen for the user.
下一步是异步操作,我们需要检查是否取消。 但同时,尚不清楚以何种频率进行此检查。 我们有两个选项-逐行检查和逐页检查。 os_signpost也提供了帮助。 事实证明,在逐行显示文档中的表格的周期中添加了用于取消的检查,我们将生成文档的时间(增加了150页)增加了2倍。 第二个选项在性能方面更为理想,实际上并没有增加创建文档所花费的时间。 结果,当我们收到内存警告事件时,我们将以编程方式取消该操作并为用户显示错误屏幕。
To make sure that memory is indeed freed, we can also use os_signpost. This time, by adding a marker about the start of the event in the didRecieveMemoryWarning method and a marker about the end of the error screen in viewDidLoad. By the way, you can emulate an insufficient memory event in the simulator (shift + command + m).
为了确保确实释放了内存,我们还可以使用os_signpost。 这次,通过在didRecieveMemoryWarning方法中添加有关事件开始的标记,并在viewDidLoad中添加有关错误屏幕结束的标记。 顺便说一下,您可以在模拟器中模拟内存不足事件(Shift + Command + m)。

案例3。 更新约束 (Case #3. Update Constraints)

Signpost may be useful in the layout process. To create constraints, we use the masonry framework. The documentation for the framework says that it is recommended to use the updateConstraints () method to create constrates. But Apple strongly discourages doing so, and you can verify this with signpost markup.
路标可能在布局过程中很有用。 为了创建约束,我们使用砌体框架。 该框架的文档说,建议使用updateConstraints()方法创建构造。 但是Apple强烈建议您不要这样做,您可以使用路标标记进行验证。

According to Apple's documentation, updateConstraints should only be used to change constraints if we cannot do it at the place the change occurred.
根据Apple的文档,如果我们不能在更改发生的地方进行更改,则只能将updateConstraints用于更改约束。

After analyzing the results, we concluded that in our application the updateConstraints call is not so frequent — approximately every time the view appears on the screen. Despite this, in order to avoid potential performance defects, we recommend following Apple's advice on this.
在分析了结果之后,我们得出结论,在我们的应用程序中,updateConstraints调用不是那么频繁-大约每次视图出现在屏幕上时。 尽管如此,为了避免潜在的性能缺陷,我们建议遵循Apple的建议。

摘要 (Summary)

In 2018, Apple provided developers with the opportunity to independently expand profiling tools. Of course, you can use other debugging tools: breakpoints, output to the console, timers, custom profilers. But it takes more time to implement or do not always give a complete picture of what is happening.
苹果在2018年为开发人员提供了独立扩展性能分析工具的机会。 当然,您可以使用其他调试工具:断点,输出到控制台,计时器,自定义探查器。 但是,这需要花费更多的时间来实施,或者不一定总能对发生的事情有一个完整的了解。
In the next article, we will consider how to use the information received from signpost more efficiently by writing our own expert system (Custom Instruments).
在下一篇文章中,我们将考虑如何通过编写我们自己的专家系统(Custom Instruments)更有效地使用从路标收到的信息。

有用的链接 (Useful links)

  • Measuring Performance Using Logging (WWDC)

    使用日志记录(WWDC)评估性能

  • Creating Custom Instruments (WWDC)

    创建自定义工具(WWDC)

  • What’s New in Energy Debugging (WWDC)

    能源调试(WWDC)的新功能

  • iOS Memory Deep Dive (WWDC)

    iOS记忆深潜(WWDC)

  • Practical Approaches to Great App Performance (WWDC)

    出色的应用程序性能(WWDC)的实用方法

  • High Performance Auto Layout (WWDC)

    高性能自动版式(WWDC)

  • Understanding and Analyzing Application Crash Reports

    了解和分析应用程序崩溃报告

  • Logging

    记录中

  • List of iOS devices

    iOS设备列表

  • Using Signposts for Performance Tuning on iOS

    在iOS上使用路标进行性能调整

  • Getting started with signposts

    路标入门

  • os_signpost API 尝鲜

    os_signpost API尝鲜

victoriaqb — Victoria Kashlina, iOS-developer.victoriaqb撰写的-iOS开发人员Victoria Kashlina。

翻译自: https://habr.com/en/company/sberbank/blog/498480/

圆形路标

圆形路标_自定义工具:路标不足时相关推荐

  1. java validate校验_自定义工具类实现validate参数校验

    前言 相信项目中做一些htttp接口,避免不了要对参数进行校验,大多数情况下,其实我们只是校验是否为NULL就可以了 1.通过注解实现各种状态的字段 1.1.引入依赖 默认的版本是6.0.9.Fina ...

  2. java登录界面圆形头像_自定义圆形头像

    在很多应用中,我们看到,个人主页里面的头像一般都是圆的,设计成圆的会使整个界面布局变的优雅漂亮.那么,怎么使头像变圆呢?有的人说可以在上面加一个中间为透明圆形的png图,用它来遮盖住头像不就行了嘛,但 ...

  3. php设置用户头像,php制作圆形用户头像的实例_自定义封装类源代码

    思路 使用图层的方法设计,共需要创建3个图像层 1.底层:最后生成的图像 2.真实用户头像:作为中间层,用户上传的真实头像图片 3.圆形蒙版:作为最上层,在蒙版中绘制圆形,并设置为透明 如图: 代码如 ...

  4. 中望CAD的lisp编辑器_巧用中望CAD2017自定义工具选项板

    我们在日常绘图工作中,除了正常使用软件提供的工具选项板之外,还可以根据工作需要进行自定义,把最常用的对象(如命令.Lisp工具.或图形等)放置在自定义工具选项板里面,以供日常工作中随时调取使用,提高绘 ...

  5. 中望CAD的lisp编辑器_【中望CAD2017】巧用自定义工具选项板,提高CAD绘图效率

    我们在日常绘图工作中,除了正常使用软件提供的工具选项板之外,还可以根据工作需要进行自定义,把最常用的对象(如命令.Lisp工具.或图形等)放置在自定义工具选项板里面,以供日常工作中随时调取使用,提高绘 ...

  6. sketch钢笔工具_设计工具(Sketch,Adobe XD,Figma和InVision Studio)中奇怪的一项功能

    sketch钢笔工具 When you build a new product that is very similar to the existing products in the market, ...

  7. paddle2.0高层API实现人脸关键点检测(人脸关键点检测综述_自定义网络_paddleHub_趣味ps)

    paddle2.0高层API实现人脸关键点检测(人脸关键点检测综述_自定义网络_paddleHub_趣味ps) 本文包含了: - 人脸关键点检测综述 - 人脸关键点检测数据集介绍以及数据处理实现 - ...

  8. sql server 开源_开源工具SQL Server安全注意事项

    sql server 开源 As our company has grown, we've recently added developers to our team who want to use ...

  9. 去水印软件哪个好_去水印工具

    地址:去水印工具https://www.shuiyinyun.com/ 怎么批量处理图片水印_去水印工具_去水印软件_图片去水印 功能目录 图片去水印 视频去水印 视频加水印 图片加水印 视频加字幕 ...

最新文章

  1. Linux之OpenSSL
  2. SAP_SD常用增强
  3. windows服务器性能分析方法小结,Windows服务器性能分析方法小结
  4. 笔记-信息系统安全管理-开放系统互连安全体系
  5. html assign无效,Object.assign的一些用法
  6. Centos7安装Docker教程
  7. 二、Python第二课——变量命名规则及字符串变量相关函数
  8. unef螺纹_PT螺纹,NPT螺纹,G螺纹,公制螺纹的区别
  9. jdbc驱动类加载直接指定线程上下文加载器加载
  10. c语言考试常考大题,C语言题库经典题 考试常考题.doc
  11. oracle xtts 测试,XTTS 跨平台表空间迁移测试
  12. 四级重点高频词汇表_零基础,教你裸过英语四级!这些方法请收藏
  13. 获取字符串长度的函数sizeof()、strlen()、length()、size()详解和区别
  14. websocket错误码盘点
  15. php发出声音,电容也会发出声音!电容啸叫是怎么产生的?如何解决?
  16. PHP计算中文文字个数
  17. windows 沙盒,隔离应用
  18. python爬虫网易云音乐评论再分析_Scrapy爬取网易云音乐和评论(一、思路分析)...
  19. B站离线多机房架构实践
  20. 几种概率分布(伯努利分布、二项分布、泊松分布、均匀分布、正态分布、指数分布、伽马分布)

热门文章

  1. 技术知识花园体系概述
  2. Docker daemon 配置和故障排除
  3. wnmp mysql_wnmp配置(windows+nginx+mysql+php开发环境)
  4. 关于Apache服务器配置SSL证书的那些事(保姆级教程)
  5. 窗口置顶工具v2.4.0
  6. ios 更新尺寸调用什么方法_iOS开发:iPhone尺寸和适配
  7. NumPy个人学习笔记【持续更新】
  8. A Two-stage Unsupervised Approach for Low light Image Enhancement(一种两阶段无监督的微光图像增强方法)
  9. RNA-seq工作流程:基因水平的探索性分析和差异表达
  10. 拆解康柏321电池之电池串并联容量计算