标签: grand-central-dispatch

性能测试:sem_t vs dispatch_semaphore_t和pthread_once_t vs dispatch_once_t

我想知道使用POSIX调用pthread_once()和/ sem_wait()或dispatch_*函数会更好/更快,所以我创建了一个小测试并对结果感到惊讶(问题和结果在最后).

在测试代​​码中,我使用mach_absolute_time()来为调用计时.我真的不在乎这与纳秒没有完全匹配; 我正在将这些值相互比较,因此确切的时间单位无关紧要,只有间隔之间的差异.结果部分中的数字是可重复的而不是平均数; 我可以平均时间,但我不是在寻找确切的数字.

test.m(简单的控制台应用程序;易于编译):

#import <Foundation/Foundation.h>
#import <dispatch/dispatch.h>
#include <semaphore.h>
#include <pthread.h>
#include <time.h>
#include <mach/mach_time.h>  

// *sigh* OSX does not have pthread_barrier (you can ignore the pthread_barrier 
// code, the interesting stuff is lower)
typedef int pthread_barrierattr_t;
typedef struct
{
    pthread_mutex_t mutex;
    pthread_cond_t cond;
    int count;
    int tripCount;
} pthread_barrier_t;


int pthread_barrier_init(pthread_barrier_t *barrier, const pthread_barrierattr_t *attr, unsigned int count)
{
    if(count == 0)
    {
        errno = EINVAL;
        return -1;
    }
    if(pthread_mutex_init(&barrier->mutex, 0) < 0) …
Run Code Online (Sandbox Code Playgroud)

multithreading semaphore objective-c grand-central-dispatch

14
推荐指数
1
解决办法
6001
查看次数

GCD Dispatch Sources和select()有什么区别?

我一直在编写一些替代现有的代码:

while(runEventLoop){
  if(select(openSockets, readFDS, writeFDS, errFDS, timeout) > 0){
    // check file descriptors for activity and dispatch events based on same 
  }
} 
Run Code Online (Sandbox Code Playgroud)

套接字读码.我想将其更改为使用GCD队列,以便我可以使用dispatch_async将事件弹出到队列,而不是维护"必须在下一次迭代时调用"数组.我也已经在使用GCD队列来/包含/这个特定的动作,因此希望将它转移到更自然的GCD调度表格中.(不是while()循环独占串行队列)

但是,当我尝试将其重构为依赖于从套接字描述符上的DISPATCH_SOURCE_TYPE_READ和DISPATCH_SOURCE_TYPE_WRITE绑定的事件处理程序触发的调度源的形式时,依赖于此调度的库代码停止工作.我的第一个假设是我误解了DISPATCH_SOURCE_TYPE_READ和DISPATCH_SOURCE_TYPE_WRITE的使用 - 我假设它们会产生与使用这些套接字描述符调用select()大致相同的行为.

我是否误解了GCD调度来源?或者,关于重构,我是否在不适合的情况下使用它?

sockets iphone multithreading grand-central-dispatch ios

13
推荐指数
1
解决办法
2007
查看次数

这是Operation Queue完成块的正确用法吗?

我第一次使用Objective-C块和操作队列.我正在加载一些远程数据,而主UI显示一个微调器.我正在使用完成块告诉表重新加载其数据.正如文档中提到的那样,完成块不会在主线程上运行,因此表会重新加载数据,但在主线程上执行某些操作(例如拖动表)之前不会重新绘制视图.

我现在使用的解决方案是一个调度队列,这是从完成块刷新UI的"最佳"方法吗?

    // define our block that will execute when the task is finished
    void (^jobFinished)(void) = ^{
        // We need the view to be reloaded by the main thread
        dispatch_async(dispatch_get_main_queue(),^{
            [self.tableView reloadData];
        });
    };

    // create the async job
    NSBlockOperation *job = [NSBlockOperation blockOperationWithBlock:getTasks];
    [job setCompletionBlock:jobFinished];

    // put it in the queue for execution
    [_jobQueue addOperation:job];
Run Code Online (Sandbox Code Playgroud)

更新 Per @ gcamp的建议,完成块现在使用主操作队列而不是GCD:

// define our block that will execute when the task is finished
void (^jobFinished)(void) = ^{
    // …
Run Code Online (Sandbox Code Playgroud)

cocoa-touch nsoperationqueue grand-central-dispatch ios

13
推荐指数
1
解决办法
7110
查看次数

何时使用NSEnumerationConcurrent

我时不时地注意到,我正在使用一个块来迭代一个集合,而不会写入任何共享数据或导致任何副作用.我考虑添加一个NSEnumerationConcurrent选项,然后决定反对它,因为我不知道什么时候值得使用.

所以我有一个特定的问题,一个更普遍的问题.

第一个问题:这是一个可能稍微有点人为的例子,它使用一个块同时做一些微不足道的事情:

CGFloat GetAverageHeight(NSArray* people)
{
  NSUInteger count = [people count];
  CGFloat* heights = malloc(sizeof(CGFloat) * count);

  [people enumerateObjectsWithOptions: NSEnumerationConcurrent usingBlock:
  ^(id person, NSUInteger idx, BOOL* stop)
  {
    heights[idx] = [person height];
  }];

  CGFloat total= 0.0;
  for (size_t i = 0 ; i < count ; i++) total += heights[i];
  free(heights);
  return total / count;
}
Run Code Online (Sandbox Code Playgroud)

忽略非并发枚举可能只是直接求和高度这一事实,而不需要调用malloc或函数的后半部分,在这里使用NSEnumerationConcurrent有什么意义吗?使用GCD(或任何NSEnumerationConcurrent在后台执行的操作)的开销是否会抵消同时获取平凡属性的收益?在使用NSEnumerationConcurrent值之前,块的工作需要多少微不足道的事情?

第二个问题:更一般地说,当我看到有机会这样做时,我应该考虑并发性(理论上:理论上这些API的重点是它们使并发性不是特殊情况而是更多部分的一般化妆一个程序),或者只是我应该使用的优化,如果我发现了一个特定的性能问题,并认为并发是答案(理由:并发代码中的错误是追踪的噩梦)?

concurrency cocoa objective-c grand-central-dispatch

13
推荐指数
1
解决办法
3984
查看次数

Int to Double cast问题

我是一名具有很少C/C++经验(并且没有培训)的Objective-C开发人员,今天我遇到了一些奇怪的硬编码数值.

我确定这是一个简单/愚蠢的问题,但有人可以解释为什么这样做:

NSDate *start = [NSDate date];
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC);

dispatch_after(popTime, dispatch_get_main_queue(), ^{
  NSLog(@"seconds: %f", [start timeIntervalSinceNow]);
});
// output: seconds: -1.0001
Run Code Online (Sandbox Code Playgroud)

这也有效(注意秒数已经改变):

NSDate *start = [NSDate date];
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC);

dispatch_after(popTime, dispatch_get_main_queue(), ^{
  NSLog(@"seconds: %f", [start timeIntervalSinceNow]);
});
// output: seconds: -2.0001
Run Code Online (Sandbox Code Playgroud)

但这是立即执行的:

NSDate *start = [NSDate date];
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 4 * NSEC_PER_SEC);

dispatch_after(popTime, dispatch_get_main_queue(), ^{
  NSLog(@"seconds: %f", [start timeIntervalSinceNow]);
});
// output: seconds: -0.0001
Run Code Online (Sandbox Code Playgroud)

但是,使用4.0而不是4 …

c cocoa objective-c grand-central-dispatch

13
推荐指数
2
解决办法
6593
查看次数

NSNotificationCenter线程安全吗?

我可以在给定队列中发布通知并在另一个队列中接收通知吗?我想使用通知来传达不同的队列,但我不确定这是否安全......

concurrency cocoa-touch objective-c grand-central-dispatch nsnotificationcenter

13
推荐指数
2
解决办法
5366
查看次数

Dispatch Queue和NSOperationQueue之间的区别

我是GCD和线程的新手.我已经完成了教程并且非常困惑.有人可以用简单的话来解释.请不要建议苹果开发者链接..

提前致谢 !

iphone multithreading nsoperationqueue grand-central-dispatch nsinvocation

13
推荐指数
1
解决办法
2万
查看次数

等待多个街区完成

我有这些方法从互联网上检索一些对象信息:

- (void)downloadAppInfo:(void(^)())success
                failure:(void(^)(NSError *error))failure;
- (void)getAvailableHosts:(void(^)())success
                  failure:(void(^)(NSError *error))failure;
- (void)getAvailableServices:(void(^)())success
                     failure:(void(^)(NSError *error))failure;
- (void)getAvailableActions:(void(^)())success
                    failure:(void(^)(NSError *error))failure;
Run Code Online (Sandbox Code Playgroud)

下载的东西存储在对象属性中,这就是成功函数不返回任何内容的原因.

现在,我想要一个像这样的方法:

- (void)syncEverything:(void(^)())success
               failure:(void(^)(NSError *error))failure;
Run Code Online (Sandbox Code Playgroud)

除了调用上面的所有方法之外,它只会在每个方法执行其成功或失败块之后返回.

我怎样才能做到这一点?

提示:我知道级联方法调用彼此成功块会起作用.但是,当后来的实现包括更多方法时,这既不"干净"也不有用.

尝试:

我尝试在a中运行每个调用NSOperation并将其添加NSOperations到a NSOperationQueue后跟"完成操作",这取决于前面的每个操作.

这不行.由于即使在各自的成功/失败块返回之前也认为操作已完成.

我也试过用dispatch_group.但我不清楚我是以正确的方式做到这一点.不幸的是,它没有用.

nsoperation nsoperationqueue grand-central-dispatch ios objective-c-blocks

13
推荐指数
2
解决办法
7218
查看次数

我是否需要在ARC下调用dispatch_release?

(但这个问题完全不同)

这个非ARC代码示例设置一个基于GCD的计时器,它为dispatch_source_t对象调用dispatch_release:

    __block BOOL done = NO;
    dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());
    if (timer) {
        uint64_t milliseconds = 100ull;
        uint64_t interval = milliseconds * NSEC_PER_MSEC;
        uint64_t leeway = 10ull * NSEC_PER_MSEC;
        __block typeof(self) _self = self;

        dispatch_source_set_timer(timer, dispatch_walltime(NULL, 0), interval, leeway);
        dispatch_source_set_event_handler(timer, ^{
            //[_progressBar setProgress:exportSession.progress animated:YES];
            if (done) {
                dispatch_source_cancel(timer);
                dispatch_release(timer);
                _self.exportingMovieLabel.hidden = YES;
                _self.exportingProgress.hidden = YES;
            }
        });

        dispatch_resume(timer);
    }
Run Code Online (Sandbox Code Playgroud)

我了解到您不必在ARC下发布队列对象.但其他GCD对象如调度源?

objective-c grand-central-dispatch ios automatic-ref-counting

13
推荐指数
1
解决办法
6849
查看次数

使用GCD并行处理数组

我有一个大型数组,我想通过将它的片段交给几个异步任务来处理.作为概念证明,我编写了以下代码:

class TestParallelArrayProcessing {
    let array: [Int]
    var summary: [Int]

    init() {
        array = Array<Int>(count: 500000, repeatedValue: 0)
        for i in 0 ..< 500000 {
            array[i] = Int(arc4random_uniform(10))
        }
        summary = Array<Int>(count: 10, repeatedValue: 0)
    }

    func calcSummary() {
        let group = dispatch_group_create()
        let queue = dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0)

        for i in 0 ..< 10 {
            dispatch_group_async(group, queue, {
                let base = i * 50000
                for x in base ..< base + 50000 {
                    self.summary[i] += self.array[x]
                }
            })
        }
        dispatch_group_notify(group, …
Run Code Online (Sandbox Code Playgroud)

parallel-processing grand-central-dispatch swift

12
推荐指数
1
解决办法
2158
查看次数