0

I'm looking for suggestions/implementations of how to create a comma separated log file on an iPhone when my data comes at a relatively fast rate (200 times per second). I expect to capture the timestamp and 2-3 integer numbers for each data point. Over a 15 minute period, there would be 15*60*200 = 180,000 rows of data, each one having a timestamp, a few integers and a newline character.

I want to make sure that writing of this data to disk happens in the correct sequential order.

My current implementation has been optimized for data coming in at 1 data point per second, and may not be very efficient for "fast" data. How can I tweak my code to make sure that it can run in a background thread without taking too much resources for each write? Alternatively, is there a fast "log to data file" implementation out there that I can just give numbers to and ask it for a log file at a later point?

   NSString *appDataFile ;
    NSFileHandle *aFileHandle;

-(NSString*)dataFilePath
{
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];

    appDataFile = [documentsDirectory stringByAppendingPathComponent:@"Data"];
    aFileHandle = [NSFileHandle fileHandleForWritingAtPath:appDataFile];
    return appDataFile;
}

//creates a new log file for each app run, or appends to existing log
-(void)writeStringToDataFile:(NSString *)csvLine
{

    if(aFileHandle)
    {
        //telling aFilehandle what file write to
        [aFileHandle truncateFileAtOffset:[aFileHandle seekToEndOfFile]]; //setting aFileHandle to write at the end of the file
        [aFileHandle writeData:[csvLine dataUsingEncoding:NSUTF8StringEncoding]];

    }else{
        NSData* headers = [@"timestamp,waveform amplitude,score, connection, event\n" dataUsingEncoding:NSUTF8StringEncoding];

        //clear the old log file
        NSError *error = nil;
        NSFileManager* fileManager =  [NSFileManager defaultManager];
        [fileManager removeItemAtPath:[self dataFilePath] error:&error];

        //create CSV headers
        aFileHandle = [NSFileHandle fileHandleForWritingAtPath:appDataFile];
        [headers writeToFile:appDataFile atomically:YES];

        aFileHandle = [NSFileHandle fileHandleForWritingAtPath:appDataFile];
        //telling aFilehandle what file write to
        [aFileHandle truncateFileAtOffset:[aFileHandle seekToEndOfFile]]; //setting aFileHandle to write at the end of the file
        [aFileHandle writeData:[csvLine dataUsingEncoding:NSUTF8StringEncoding]];

    }

}
4

1 回答 1

2

一个明显的变化是删除不必要的调用来截断您要编写的每一行的文件。打开文件时,只需将句柄移到末尾一次。

下一轮更改将是使用 C 代码而不是 Objective-C。用于fopen打开文件。用于fputs编写 C 字符串。

另一个要检查的地方是您如何构建csvLine. 使用stringWithFormat很慢。使用 . 获取低级别并将每个单独的值写入 C 字符串fputs。无需格式化。无需转换为 NSData。

还要看看你是如何做时间戳的。如果你把一个转换成一个NSDateNSString你会浪费很多时间。

这是一个重要的建议 - 如果时间如此紧迫,请在内存中构建一个大的可变字符串,然后在完成后将整个内容一次性写入文件。这将在时间关键阶段切断文件 I/O。

利用 Instruments 找出真正的瓶颈在哪里。没有它,您可能会优化错误的代码。

于 2013-03-10T01:28:15.323 回答