iOS 锁的性能测试

 前言:OSSpinLock 性能真的很高?
 @synchronize 性能真的很差?
 OSSpinLock 的替代品 os_unfair_lock很高?

ibireme 的结论真的对吗?

iOS 锁的性能测试_第1张图片

1、主线程中测试代码:(测试环境:iPhone 7  iOS 13.4 MAC OS 10.15.4 xCode 11.4)

1.1、通过clock_gettime() 转换为微秒时间进行比较 ,通过在主线程中分别尝试10000次加锁,解锁操作 得出diff:

static uint32_t getCurrentTimeIntervalMicrosecond()
{
    struct timespec         time = {0, 0};
    clock_gettime(CLOCK_MONOTONIC, &time);
    
    return (uint32_t)(time.tv_sec * 1000000 + time.tv_nsec / 1000);
}

- (void)spinLockTest{
    uint32_t before = getCurrentTimeIntervalMicrosecond();
    OSSpinLock spinLock = OS_SPINLOCK_INIT;
    for (int i = 0; i < 10000;) {
        OSSpinLockLock(&spinLock);
        i++;
        OSSpinLockUnlock(&spinLock);
    }
    NSLog(@"spinLock time:%d",getCurrentTimeIntervalMicrosecond() - before);
}

- (void)os_unfair_lock_test{
    uint32_t before = getCurrentTimeIntervalMicrosecond();
    os_unfair_lock osUnfairLock = OS_UNFAIR_LOCK_INIT;
    for (int i = 0; i < 10000;) {
      os_unfair_lock_lock(&osUnfairLock);
      i++;
      os_unfair_lock_unlock(&osUnfairLock);
    }
    NSLog(@"osUnfairLock time:%d",getCurrentTimeIntervalMicrosecond() - before);
}


- (void)os_unfair_lock_try_test{
    uint32_t before = getCurrentTimeIntervalMicrosecond();
    os_unfair_lock osUnfairLock = OS_UNFAIR_LOCK_INIT;
    for (int i = 0; i < 10000;) {
      if (os_unfair_lock_trylock(&osUnfairLock)) {
          i++;
          os_unfair_lock_unlock(&osUnfairLock);
      }
    }
    NSLog(@"osUnfairTryLock time:%d",getCurrentTimeIntervalMicrosecond() - before);
}

- (void)pthread_mutex_normal_test{
    uint32_t before = getCurrentTimeIntervalMicrosecond();
    pthread_mutex_t normal_mutex;
    pthread_mutexattr_t attr;
    pthread_mutexattr_init(&attr);
    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
    pthread_mutex_init(&normal_mutex, &attr);
      for (int i = 0; i < 10000;) {
          pthread_mutex_lock(&normal_mutex);
          i++;
          pthread_mutex_unlock(&normal_mutex);
      }
      NSLog(@"PTHREAD_MUTEX_NORMALdiff time:%d",getCurrentTimeIntervalMicrosecond() - before);
    pthread_mutexattr_destroy(&attr);
    pthread_mutex_destroy(&normal_mutex);
}

- (void)pthread_mutex_recursive_test{
    uint32_t before = getCurrentTimeIntervalMicrosecond();
    pthread_mutex_t normal_mutex;
    pthread_mutexattr_t attr;
    pthread_mutexattr_init(&attr);
    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
    pthread_mutex_init(&normal_mutex, &attr);
    for (int i = 0; i < 10000;) {
        pthread_mutex_lock(&normal_mutex);
        i++;
        pthread_mutex_unlock(&normal_mutex);
    }
    NSLog(@"PTHREAD_MUTEX_RECURSIVE diff time:%d",getCurrentTimeIntervalMicrosecond() - before);
    pthread_mutexattr_destroy(&attr);
    pthread_mutex_destroy(&normal_mutex);
}

- (void)nslockTest{
    uint32_t before = getCurrentTimeIntervalMicrosecond();
    NSLock* lock = NSLock.new;
    for (int i = 0; i < 10000;) {
        [lock lock];
        i++;
        [lock unlock];
    }
    NSLog(@"NSLock diff time:%d",getCurrentTimeIntervalMicrosecond() - before);
}

- (void)nsRecursiveLockTest{
    uint32_t before = getCurrentTimeIntervalMicrosecond();
    NSRecursiveLock* lock = NSRecursiveLock.new;
    for (int i = 0; i < 10000;) {
        [lock lock];
        i++;
        [lock unlock];
    }
    NSLog(@"NSRecursiveLock time:%d",getCurrentTimeIntervalMicrosecond() - before);
}

- (void)nslockConditionTest{
    uint32_t before = getCurrentTimeIntervalMicrosecond();
    NSCondition* lock = NSCondition.new;
    for (int i = 0; i < 10000;) {
        [lock lock];
        i++;
        [lock unlock];
    }
    NSLog(@"NSCondition diff time:%d",getCurrentTimeIntervalMicrosecond() - before);
}

- (void)nslockConditionLockTest{
    uint32_t before = getCurrentTimeIntervalMicrosecond();
    NSConditionLock* lock = [[NSConditionLock alloc] initWithCondition:0];
    for (int i = 0; i < 10000;) {
        [lock lockWhenCondition:i];
        i++;
        [lock unlockWithCondition:i];
      
    }
    NSLog(@"NSConditionLock lock diff time:%d",getCurrentTimeIntervalMicrosecond() - before);
}

- (void)synchronizeTest{
    uint32_t before = getCurrentTimeIntervalMicrosecond();
    NSNumber* number = @(100);
    for (int i = 0; i < 10000;) {
        @synchronized (number) {
            i++;
        }
      
    }
    NSLog(@"synchronize diff time:%d",getCurrentTimeIntervalMicrosecond() - before);
}

1.2、测试结果:

 

2、异步在全局并发队列中执行10000次并打印结果,打印时间为毫秒:

2.1、测试代码:

//毫秒
static uint32_t getCurrentTimeIntervalMicrosecond()
{
    struct timespec         time = {0, 0};
    clock_gettime(CLOCK_MONOTONIC, &time);
    
    return (uint32_t)(time.tv_sec * 1000 + time.tv_nsec / 1000000);
}

- (void)spinLockTest{
    uint32_t before = getCurrentTimeIntervalMicrosecond();
    static OSSpinLock spinLock = OS_SPINLOCK_INIT;
    dispatch_group_t group = dispatch_group_create();
    for (int i = 0; i < 10000;) {
        dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{
             OSSpinLockLock(&spinLock);
             g_global_variable = i;
             //NSLog(@"__%s__:g_global_variable = %d",__func__,g_global_variable);
             OSSpinLockUnlock(&spinLock);
        });
        i++;
    }
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"result spinLockTest diff time:%d",getCurrentTimeIntervalMicrosecond() - before);
    });
    
}

- (void)os_unfair_lock_test{
    uint32_t before = getCurrentTimeIntervalMicrosecond();
    static os_unfair_lock osUnfairLock = OS_UNFAIR_LOCK_INIT;
    dispatch_group_t group = dispatch_group_create();
    for (int i = 0; i < 10000;) {
         dispatch_group_async(group,dispatch_get_global_queue(0, 0), ^{
            os_unfair_lock_lock(&osUnfairLock);
            g_global_variable = i;
            //NSLog(@"__%s__:g_global_variable = %d",__func__,g_global_variable);
            os_unfair_lock_unlock(&osUnfairLock);
        });
        i++;
    }
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"result os_unfair_lock_test diff time:%d",getCurrentTimeIntervalMicrosecond() - before);
    });
}


- (void)os_unfair_lock_try_test{
    uint32_t before = getCurrentTimeIntervalMicrosecond();
    static os_unfair_lock osUnfairLock = OS_UNFAIR_LOCK_INIT;
    dispatch_group_t group = dispatch_group_create();
    for (int i = 0; i < 10000;) {
         dispatch_group_async(group,dispatch_get_global_queue(0, 0), ^{
         if (os_unfair_lock_trylock(&osUnfairLock)) {
             g_global_variable = i;
             //NSLog(@"__%s__:g_global_variable = %d",__func__,g_global_variable);
             os_unfair_lock_unlock(&osUnfairLock);
         }
        });
        i++;
    }
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"result os_unfair_lock_try_test diff time:%d",getCurrentTimeIntervalMicrosecond() - before);
    });
}

- (void)pthread_mutex_normal_test{
    uint32_t before = getCurrentTimeIntervalMicrosecond();
    static pthread_mutex_t normal_mutex;
    static pthread_mutexattr_t attr;
    pthread_mutexattr_init(&attr);
    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
    pthread_mutex_init(&normal_mutex, &attr);
    dispatch_group_t group = dispatch_group_create();
    for (int i = 0; i < 10000;) {
         dispatch_group_async(group,dispatch_get_global_queue(0, 0), ^{
            pthread_mutex_lock(&normal_mutex);
            g_global_variable = i;
            //NSLog(@"__%s__:g_global_variable = %d",__func__,g_global_variable);
            pthread_mutex_unlock(&normal_mutex);
        });
        i++;
    }
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"result pthread_mutex_normal_test diff time:%d",getCurrentTimeIntervalMicrosecond() - before);
    });
}

- (void)pthread_mutex_recursive_test{
    uint32_t before = getCurrentTimeIntervalMicrosecond();
    static pthread_mutex_t normal_mutex;
    static pthread_mutexattr_t attr;
    pthread_mutexattr_init(&attr);
    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
    pthread_mutex_init(&normal_mutex, &attr);
    dispatch_group_t group = dispatch_group_create();
    for (int i = 0; i < 10000;) {
         dispatch_group_async(group,dispatch_get_global_queue(0, 0), ^{
            pthread_mutex_lock(&normal_mutex);
            g_global_variable = i;
            //NSLog(@"__%s__:g_global_variable = %d",__func__,g_global_variable);
            pthread_mutex_unlock(&normal_mutex);
        });
        i++;
    }
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"result pthread_mutex_recursive_test diff time:%d",getCurrentTimeIntervalMicrosecond() - before);
    });
}

- (void)nslockTest{
    uint32_t before = getCurrentTimeIntervalMicrosecond();
    NSLock* lock = NSLock.new;
    dispatch_group_t group = dispatch_group_create();
    for (int i = 0; i < 10000;) {
         dispatch_group_async(group,dispatch_get_global_queue(0, 0), ^{
            [lock lock];
            g_global_variable = i;
            //NSLog(@"__%s__:g_global_variable = %d",__func__,g_global_variable);
            [lock unlock];
        });
        i++;
    }
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"result nslockTest diff time:%d",getCurrentTimeIntervalMicrosecond() - before);
    });
}

- (void)nsRecursiveLockTest{
    uint32_t before = getCurrentTimeIntervalMicrosecond();
    NSRecursiveLock* lock = NSRecursiveLock.new;
    dispatch_group_t group = dispatch_group_create();
    for (int i = 0; i < 10000;) {
         dispatch_group_async(group,dispatch_get_global_queue(0, 0), ^{
            [lock lock];
            g_global_variable = i;
            //NSLog(@"__%s__:g_global_variable = %d",__func__,g_global_variable);
            [lock unlock];
        });
        i++;
    }
    
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"result nsRecursiveLockTest diff time:%d",getCurrentTimeIntervalMicrosecond() - before);
    });
}

- (void)nslockConditionTest{
    uint32_t before = getCurrentTimeIntervalMicrosecond();
    NSCondition* lock = NSCondition.new;
    dispatch_group_t group = dispatch_group_create();
    for (int i = 0; i < 10000;) {
         dispatch_group_async(group,dispatch_get_global_queue(0, 0), ^{
            [lock lock];
            g_global_variable = i;
            //NSLog(@"__%s__:g_global_variable = %d",__func__,g_global_variable);
            [lock unlock];
        });
        i++;
    }
    
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"result nslockConditionTest diff time:%d",getCurrentTimeIntervalMicrosecond() - before);
    });
}

- (void)nslockConditionLockTest{
    uint32_t before = getCurrentTimeIntervalMicrosecond();
    NSConditionLock* lock = [[NSConditionLock alloc] initWithCondition:0];
    dispatch_group_t group = dispatch_group_create();
    for (int i = 0; i < 10000;) {
         dispatch_group_async(group,dispatch_get_global_queue(0, 0), ^{
            [lock lockWhenCondition:i];
            g_global_variable = i;
            //NSLog(@"__%s__:g_global_variable = %d",__func__,g_global_variable);
            [lock unlockWithCondition:(i + 1)];
        });
        i++;
    }
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"result nslockConditionLockTest diff time:%d",getCurrentTimeIntervalMicrosecond() - before);
    });
}

- (void)synchronizeTest{
    uint32_t before = getCurrentTimeIntervalMicrosecond();
    NSNumber* number = @(100);
    dispatch_group_t group = dispatch_group_create();
    for (int i = 0; i < 10000;) {
         dispatch_group_async(group,dispatch_get_global_queue(0, 0), ^{
            @synchronized(@(i)){
                g_global_variable = i;
                //NSLog(@"__%s__:g_global_variable = %d",__func__,g_global_variable);
            };
        });
        i++;
    }
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"result synchronizeTest diff time:%d",getCurrentTimeIntervalMicrosecond() - before);
    });
}

2.2、惊奇发现调用顺序会影响结论,所以此结论不准:

2.3、每次启动单独调用某一个锁10000次:

你可能感兴趣的:(Objective-C)