Dar*_*ust 9 io macos grand-central-dispatch ios
使用Grand Central Dispatch,您可以安排读取和写入,而无需担心何时/如何发生这种情况.与我之前基于NSStream的方法相比,这需要更少的外部管理.但是,我的天真实现比基于NSStream的方法慢.
对于NSStream,我查询了源和目标(NSURLPreferredIOBlockSizeKey)的首选IO大小.然后我将整个"首选输入大小的块"读入缓冲区,并且只要我在缓冲区中至少有"首选输出大小"字节,我就会将整个块写入目标(当然除了最后一个块).在读写性能方面,这应该非常接近最佳值.
但是,对于GCD,我对此没有多大影响.想象一下,源的首选IO大小为100kB,并且目标的首选IO大小为1MB:我的天真实现现在写入的次数是基于NSStream的解决方案的10倍.
那么,用GCD解决这个问题最有效的方法是什么?只需写入读取器块中的缓冲区,一旦收集到足够的数据,就可以调度"首选输出大小"的写入块?我想GCD可能会在这里为我提供一个我还没有意识到的解决方案.
这是我目前GCD解决方案中最重要的部分:
// input_ and output_ are of type dispatch_io_t
dispatch_io_read(
    input_,
    0,
    SIZE_MAX,
    dispatch_get_main_queue(),
    ^(bool done, dispatch_data_t data, int error) {
        size_t data_size;
        if (error) {
            NSLog(@"Input: error %d", error);
            [self cancel];
            return;
        }
        if (data) {
            data_size = dispatch_data_get_size(data);
            if (data_size > 0) {
                dispatch_io_write(
                    output_,
                    0,
                    data,
                    dispatch_get_main_queue(), ^(bool done, dispatch_data_t data, int error) {
                        // TODO: I don't know how to get the offset (for progress). So I need to
                        // pass it from the calling block.
                        if (error) {
                            NSLog(@"Output: error %d", error);
                            return;
                        }
                        if (done) {
                            bytesWritten_ += data_size;
                            // Update progress report here.
                        }
                    }
                );
            }
        }
    }
);
虽然在大多数情况下不需要,但您可以使用dispatch_io_set_high_water(3)和dispatch_io_set_low_water(3)API 来影响GCD使用的IO大小.
GCD不会读取或写入大于通道高水位线的块.永远不会使用小于低水位线的数据对象调用读/写处理程序.
例如,通过将input_示例中的低水位标记设置为1MB,可以确保当前的读取回调不会传递小于1MB的数据对象dispatch_io_write(3).
如果此控件在您的情况下不够用,您还可以组合从读取处理程序的连续调用中接收的多个数据对象,dispatch_data_create_concat(3)直到它们达到足够大的大小以传递给它dispatch_io_write(3).
希望这不应该是必要的,但是,将源端的低水位标记设置为首选源块大小的倍数,大小足以达到首选目标块大小,并将目标通道的高水位标记设置为首选目标块大小(或多个)应该提供与当前基于NSStream的解决方案相同的性能.
您可以检查出的GCD IO缓冲政策的具体的实施.
在任何情况下,请确保在您看到默认GCD IO缓冲的性能问题的任何情况下提交错误.
| 归档时间: | 
 | 
| 查看次数: | 2218 次 | 
| 最近记录: |