GCD on iOS

队列优先级和任务执行顺序的关系

实验代码1 :相同数量任务,低优先级队列先提交

队列优先级从低到高,每个队列入队若干个任务(上一个队列入队完成后,才向下一个入队),查看任务执行情况

void queue_concurrent()
{
    os_signpost_id_t __spid = os_signpost_id_make_with_pointer(LOG_PERF, (void*)now_ns);
    os_signpost_interval_begin(LOG_PERF, __spid, "queue_concurrent", "");
    auto g = dispatch_group_create();
    auto q = dispatch_queue_create("q", dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_CONCURRENT, QOS_CLASS_USER_INTERACTIVE, 0));
    auto q1 = dispatch_queue_create("q1", dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_CONCURRENT, QOS_CLASS_USER_INITIATED, 0));
    auto q2 = dispatch_queue_create("q2", dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_CONCURRENT, QOS_CLASS_DEFAULT, 0));
    auto q3 = dispatch_queue_create("q3", dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_CONCURRENT, QOS_CLASS_UTILITY, 0));
    auto q4 = dispatch_queue_create("q4", dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_CONCURRENT, QOS_CLASS_BACKGROUND, 0));
    
    auto start = now_ns();
    for (int i = 0; i < task_count; i++) {
        dispatch_group_async_f(g, q4, nullptr, sleep_10ms);
    }
    for (int i = 0; i < task_count; i++) {
        dispatch_group_async_f(g, q3, nullptr, sleep_11ms);
    }
    for (int i = 0; i < task_count; i++) {
        dispatch_group_async_f(g, q2, nullptr, sleep_12ms);
    }
    for (int i = 0; i < task_count; i++) {
        dispatch_group_async_f(g, q1, nullptr, sleep_13ms);
    }
    for (int i = 0; i < task_count; i++) {
        dispatch_group_async_f(g, q, nullptr, sleep_14ms);
    }
    os_signpost_interval_end(LOG_PERF, __spid, "queue_concurrent", "");
    dispatch_group_wait(g, DISPATCH_TIME_FOREVER);
    printf("total takes %llu ms\n", now_ns() - start);
}

任务提交的队列所处的优先级顺序由低到高:QOS_CLASS_BACKGROUND,QOS_CLASS_UTILITY,QOS_CLASS_DEFAULT,QOS_CLASS_USER_INITIATED,QOS_CLASS_USER_INTERACTIVE
图里面的任务,最下面却先执行完成的是高优先级QOS_CLASS_USER_INTERACTIVE,最上面却最后执行完成的是低优先级QOS_CLASS_BACKGROUND

少量任务(task_count = 50)

iPhone7,iOS 15.7
iPad mini 5,iOS 18.5
iPhone 14 Pro Max,iOS 26

大量任务(task_count = 500)

iPhone7,iOS 15.7
iPad mini 5,iOS 18.5
iPhone 14 Pro Max,iOS 26

附录:辅助代码

#import <Foundation/Foundation.h>
#include <chrono>
#include <os/signpost.h>
#include <mach/mach_time.h>

static inline long long now_ns(void) {
    struct timespec ts;
    clock_gettime(CLOCK_MONOTONIC, &ts);
    return (long long)ts.tv_sec * 1000000000LL + ts.tv_nsec;
}

static os_log_t LOG_PERF = os_log_create("com.ufogxl.GCDTest", "Custom");

#define PERF_BEGIN(log, spid, ptr, name) \
    spid = os_signpost_id_make_with_pointer(log, (ptr)); \
    os_signpost_interval_begin(log, spid, (name), "");

#define PERF_END(log, spid, name) \
    os_signpost_interval_end(log, spid, (name), "");

#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)

//        printf("sleep for " TOSTRING(ms) " ms\n");

#define DEFINE_SLEEP_MS_FN(name, ms)                                 \
    __attribute__((used))                                            \
    void name(void*_) {                                              \
        os_signpost_id_t spid;                                       \
        uint64_t now_ns = mach_absolute_time();                      \
        PERF_BEGIN(LOG_PERF, spid, (void*)now_ns, #name);            \
        (void)_;                                                     \
        const uint64_t _ms = (ms);                                   \
        mach_timebase_info_data_t info;                              \
        mach_timebase_info(&info);                                   \
        uint64_t ns = _ms * 1000000L;                                 \
        uint64_t ticks = ns * info.denom / info.numer;               \
        mach_wait_until(now_ns + ticks);                             \
        PERF_END(LOG_PERF, spid, #name);                              \
    }


//#define DEFINE_SLEEP_MS_FN(name, ms)      \
//void name(void*_) {                       \
//    printf("sleep for " TOSTRING(ms) " ms\n"); \
//}


DEFINE_SLEEP_MS_FN(sleep_4ms, 4)
DEFINE_SLEEP_MS_FN(sleep_3ms, 3)
DEFINE_SLEEP_MS_FN(sleep_2ms, 2)
DEFINE_SLEEP_MS_FN(sleep_1ms, 1)
DEFINE_SLEEP_MS_FN(sleep_0ms, 0)

DEFINE_SLEEP_MS_FN(sleep_14ms, 14)
DEFINE_SLEEP_MS_FN(sleep_13ms, 13)
DEFINE_SLEEP_MS_FN(sleep_12ms, 12)
DEFINE_SLEEP_MS_FN(sleep_11ms, 11)
DEFINE_SLEEP_MS_FN(sleep_10ms, 10)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容