Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/114.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 有没有办法加速这个文件I/O代码?_Ios_Objective C - Fatal编程技术网

Ios 有没有办法加速这个文件I/O代码?

Ios 有没有办法加速这个文件I/O代码?,ios,objective-c,Ios,Objective C,在我的应用程序中,大约有300个大小为0.5 MB的NSData对象,我将它们按顺序写入一个文件,基本上就是这样的代码(将单个0.5 MB对象写入300次): -(void)创建文件{ //创建要写入的.5 MB块 int size=500000; 字节*字节=malloc(大小); 对于(int i=0;i

在我的应用程序中,大约有300个大小为0.5 MB的NSData对象,我将它们按顺序写入一个文件,基本上就是这样的代码(将单个0.5 MB对象写入300次):

-(void)创建文件{
//创建要写入的.5 MB块
int size=500000;
字节*字节=malloc(大小);
对于(int i=0;i
在我的iPod(第五代)和iPhone6上,这个过程大约需要3秒钟,我想知道是否有更快的方法来完成这个过程。我尝试过使用
NSFileManager
NSFileHandle
方法,但它们花费的时间大致相同,这让我认为这是我遇到的基本I/O限制


有什么方法可以更快地执行此操作(此代码应该在任何设备上编译和运行)?

300*0.5/3=50MB/s,150MB的数据看起来足够快了。我想您达到了闪存写入速度限制。我相信这段代码是在后台线程中运行的,所以问题不在于UI的阻塞

这是我使用mmap和memcpy能够实现的最高性能

在我的iPhone6上运行平均需要0.2秒,有些变化高达0.5秒左右。然而,YMMV似乎有两个不同的闪存存储供应商——一个是TLC,另一个是MLC——使用TLC的供应商将获得更好的结果

当然,这假设您可以使用异步I/O。如果您确实需要同步的东西,请寻找其他解决方案

- (IBAction)createFile {
  NSData *data = [[self class] dataToCopy];

  // temp output file
  NSUUID *uuid = [NSUUID UUID];
  NSString *path = [[NSTemporaryDirectory()
                     stringByAppendingPathComponent:[uuid UUIDString]]
                    stringByAppendingPathExtension:@"dat"];

  NSUInteger size = [data length];
  NSUInteger count = 300;

  NSUInteger file_size = size * count;

  int fd = open([path UTF8String], O_CREAT | O_RDWR, 0666);
  ftruncate(fd, file_size);

  void *addr = mmap(NULL, file_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

  double startTime = CACurrentMediaTime();
  static dispatch_queue_t concurrentDataQueue;
  static dispatch_once_t onceToken;
  dispatch_once(&onceToken, ^{
    concurrentDataQueue = dispatch_queue_create("test.concurrent", DISPATCH_QUEUE_CONCURRENT);
  });

  for (int i = 0; i < count; i++) {
    dispatch_async(concurrentDataQueue, ^{
      memcpy(addr + (i * size), [data bytes], size);
    });
  }

  dispatch_barrier_async(concurrentDataQueue, ^{
    fsync(fd);

    double duration = CACurrentMediaTime() - startTime;
    NSLog(@"duration = %f", duration);

    munmap(addr, file_size);
    close(fd);
    unlink([path UTF8String]);
  });
}
-(iAction)创建文件{
NSData*data=[[self class]dataToCopy];
//临时输出文件
nsuid*uuid=[nsuid-uuid];
NSString*路径=[[NSTemporaryDirectory()
stringByAppendingPathComponent:[uuid UUIDString]]
stringByAppendingPathExtension:@“dat”];
NSU整数大小=[数据长度];
整数计数=300;
NSU整数文件大小=大小*计数;
int fd=open([path UTF8String],O|u CREAT | O|u RDWR,0666);
ftruncate(fd,文件大小);
void*addr=mmap(NULL,文件大小,保护读取,保护写入,映射共享,fd,0);
double startTime=CACurrentMediaTime();
静态调度队列并发数据队列;
静态调度一次;
一次发送(一次发送)^{
concurrentDataQueue=dispatch\u queue\u create(“test.concurrent”,dispatch\u queue\u concurrent);
});
for(int i=0;i
我可以推荐两个性能提示:尝试关闭文件系统缓存或检查IO缓冲区大小

“当读取您确定不久将不再需要的数据时,如流式传输大型多媒体文件,请告诉文件系统不要将该数据添加到文件系统缓存中

应用程序可以使用
F_NOCACHE
标志调用BSD
fcntl
函数来启用或禁用文件缓存。有关此函数的更多信息,请参阅
fcntl
~

或者“在处理之前将大部分或全部数据读入内存”~


iPhone 6使用16Gb SK hynix闪存,理论上顺序写入的限制约为40至70 Mb/s~。

不确定是否遇到此问题,但在
while
循环中有一个严重的错误。在调用
write:maxLength:
@rmaddy:谢谢,捕捉得好,您需要将
size
替换为
size-totalBytesWrite
。这不是我的实际代码,但该错误也存在于我的实际方法中。不,我认为I/O位是可以的,但是没有必要使用
malloc()
;只需使用
NSMutableData
即可。@TienDinh不,他不是。你试过吗?+50mb/s对于闪存来说非常慢,它是字节而不是位。因此它是47.68 MB/s或400 MB/s。我想说的是,您最有可能是I/O绑定的。对于台式机或笔记本电脑SSD,50MB/s的写入速度会很慢。这对一部手机来说似乎并不是完全不合理的(因为它的电源效率特别重要)。你确定你每次都在写~500K?您的数据表明,写入速率为300-750MB/s,相对于iPhone6闪存的基准测试,这似乎很高。如果正确的话,那太好了。我在这里试用你的方法。PROT_READ、PROT_WRITE和MAP_共享常量需要哪些include/import语句?因此,这段代码似乎不起作用,不确定我是否做错了什么。在我的实际应用程序中,这种方法只比我原来的方法快一点点(大约4秒对4.5秒),
- (IBAction)createFile {
  NSData *data = [[self class] dataToCopy];

  // temp output file
  NSUUID *uuid = [NSUUID UUID];
  NSString *path = [[NSTemporaryDirectory()
                     stringByAppendingPathComponent:[uuid UUIDString]]
                    stringByAppendingPathExtension:@"dat"];

  NSUInteger size = [data length];
  NSUInteger count = 300;

  NSUInteger file_size = size * count;

  int fd = open([path UTF8String], O_CREAT | O_RDWR, 0666);
  ftruncate(fd, file_size);

  void *addr = mmap(NULL, file_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

  double startTime = CACurrentMediaTime();
  static dispatch_queue_t concurrentDataQueue;
  static dispatch_once_t onceToken;
  dispatch_once(&onceToken, ^{
    concurrentDataQueue = dispatch_queue_create("test.concurrent", DISPATCH_QUEUE_CONCURRENT);
  });

  for (int i = 0; i < count; i++) {
    dispatch_async(concurrentDataQueue, ^{
      memcpy(addr + (i * size), [data bytes], size);
    });
  }

  dispatch_barrier_async(concurrentDataQueue, ^{
    fsync(fd);

    double duration = CACurrentMediaTime() - startTime;
    NSLog(@"duration = %f", duration);

    munmap(addr, file_size);
    close(fd);
    unlink([path UTF8String]);
  });
}