找出Swift中发生上下文切换的时间

时间:2018-12-12 21:28:46

标签: swift grand-central-dispatch context-switch

说实话,我不知道是否可以解决我的问题,但我想在Swift中捕获上下文切换时的情况。

我正在想象一个函数,该函数需要很长时间才能完成,例如在远程服务器上执行写操作,我在想是否有办法了解何时(至少在哪一行)线程是执行该任务正在执行上下文切换,因为必须执行另一个等待很长时间的任务。

对不起,如果您觉得这是一个愚蠢的问题,或者在尝试解释以上内容时我犯了错误

编辑:

我说的是调度程序自动请求的上下文切换。所以,再次想像一下,我们处于这个长函数的中间,该函数执行大量操作,而调度程序为此任务花费了几秒钟的时间。 10秒以使其完成。如果进程用完了时间并且没有结束任务,它将被挂起,例如线程将执行另一个进程的另一个任务。结束时,调度程序可能会考虑对挂起的作业进行另一次尝试,并且将从挂起的位置开始继续执行(因此将从PC寄存器中读取值并将继续执行)

2 个答案:

答案 0 :(得分:4)

您绝对可以满足您的要求,但我感觉它对您的用处将比您可能认为的要少得多。大量(巨大,巨大!)上下文切换将在您可能会认为“无趣的”点发生。 lstat64()mach_vm_map_trap()mach_msg_trap()mach_port_insert_member_trap()kevent_id(),列表继续。大多数线程将大部分时间都花在OS堆栈中。花费很长时间后,“远程服务器上的写操作”将不会阻塞。它会主动阻止自己,因为它知道这将花费很长的时间。

即使如此,您当然也可以使用Instruments进行探索。只需选择系统跟踪配置文件,它将向您显示所有线程和系统核心,以及如何调度设备上的线程和所有其他线程,每个系统调用等,等等。这是大量信息,因此您通常一次只能配置几秒钟。但它看起来像这样:

Instruments with System Trace

如果上下文切换是主要瓶颈,这将是有用的信息。如果您正在处理过多的锁争用,或者由于不断被其他线程中断而导致L1高速缓存崩溃,则可能会发生这种情况。因此,如果您有一些线程希望继续保持连续运行并且被阻塞,那么这确实是有价值的信息。或者,如果您认为有两个线程可以来回平滑地运行,但是它们似乎在争夺(快速切换),那么您可以进行此工作。 (但是,除非您使用的是相当低级的代码,否则这很少是您寻求性能调整的第一个地方。)

根据您的描述,我认为您可能对调度程序有错误的认识。调度程序中的任何内容都不会达到10秒左右。在调度程序世界中,毫秒是很多时间。您应该考虑耗时数微秒甚至是纳秒的事物。如果您正在编写假定从RAM提取数据是免费的代码,那么您使用的时间尺度错误。 A network call is so ludicrously slow that you can basically estimate it as "forever."在上下文切换级别,您正在查看类似事件:

00:00.770.247   Virtual memory Zero Fill took 10.50 µs  small_free_list_add_ptr ← (31 other frames) 

答案 1 :(得分:1)

我认为这是一个很酷的问题,但不清楚。答案完全是我对您问题的理解。通常情况下,如果您实现C ++或C程序进行上下文切换,请考虑使用互斥或​​信号量编写代码。在这些部分中,进程或线程在关键部分中起作用,有时会手动或以中断方式执行上下文切换。在iOS中,有相同的并发实现,例如DispatchSemaphore。(实际上,互斥锁是与锁定系统一起工作的Semaphore。)您可以从here阅读文档。

首先,这是Semaphore中的Swift类定义。

class DispatchSemaphore : DispatchObject

您可以使用int值将其初始化,例如

let semaphore = DispatchSemaphore(value: intValue)

如果要使用互斥变量,则可以轻松使用锁变量。如

 var lock = Lock()

以正确的实现锁定线程时,您将处在关键区域,可以使用解锁或其他方式切换线程。

POSIX pthread_lock_t

相似

您可以像这样在lock或semaphore关键部分中处理上下文切换

lock.lock()
// critical section
// handle the calculation, if its longer unlock, or let it do its job
lock.unlock()


semaphore.wait(timeout: DispatchTime.distantFuture)
// critical section
// handle the calculation, if its too long signal to exit it in here, or let it do its job
// if it is a normal job, it will be signal for exit already.
semaphore.signal()

处理后的答案包含线程中的上下文切换。

除了我的问题外,当您询问上下文切换时,其自然的意思是基本上更改线程或进程。因此,当您从后台线程获取数据并为UITableView实现数据时,您可能会在DispatchQueue.main.async中进行reloadData方法调用。这是上下文切换的常见用法。