美文网首页
探究xcode执行c函数和OC方法的效率问题

探究xcode执行c函数和OC方法的效率问题

作者: child_cool | 来源:发表于2018-10-15 14:34 被阅读36次

测试对象如图:

#import "GZip.h"
#import <zlib.h>

@implementation GZip
+ (NSData *)gzipData:(NSData *)uncompressedData {
    if ((uncompressedData == nil) ||
        ([uncompressedData length] == 0)) {
        return uncompressedData;
    }
    
    z_stream strm;
    
    strm.zalloc    = Z_NULL;
    strm.zfree     = Z_NULL;
    strm.opaque    = Z_NULL;
    strm.total_out = 0;
    strm.next_in   = (Bytef*)[uncompressedData bytes];
    strm.avail_in  = (unsigned int)[uncompressedData length];
    
    if (deflateInit2(&strm,
                     Z_DEFAULT_COMPRESSION,
                     Z_DEFLATED,
                     (15+16),
                     8,
                     Z_DEFAULT_STRATEGY) != Z_OK) {
        return nil;
    }
    
    NSMutableData *compressed = [NSMutableData dataWithLength:16384]; // 16K chunks for expansion
    
    do {
        
        if (strm.total_out >= [compressed length])
            [compressed increaseLengthBy: 16384];
        
        strm.next_out  = (Bytef*)[compressed mutableBytes] + strm.total_out;
        strm.avail_out = (unsigned int)([compressed length] - strm.total_out);
        
        deflate(&strm, Z_FINISH);
        
    } while (strm.avail_out == 0);
    
    deflateEnd(&strm);
    
    [compressed setLength: strm.total_out];
    return [NSData dataWithData:compressed];
}

NSData *brs_gzipData(NSData *uncompressedData) {
    if ((uncompressedData == nil) ||
        ([uncompressedData length] == 0)) {
        return uncompressedData;
    }
    
    z_stream strm;
    
    strm.zalloc    = Z_NULL;
    strm.zfree     = Z_NULL;
    strm.opaque    = Z_NULL;
    strm.total_out = 0;
    strm.next_in   = (Bytef*)[uncompressedData bytes];
    strm.avail_in  = (unsigned int)[uncompressedData length];
    
    if (deflateInit2(&strm,
                     Z_DEFAULT_COMPRESSION,
                     Z_DEFLATED,
                     (15+16),
                     8,
                     Z_DEFAULT_STRATEGY) != Z_OK) {
        return nil;
    }
    
    NSMutableData *compressed = [NSMutableData dataWithLength:16384]; // 16K chunks for expansion
    
    do {
        
        if (strm.total_out >= [compressed length])
            [compressed increaseLengthBy: 16384];
        
        strm.next_out  = (Bytef*)[compressed mutableBytes] + strm.total_out;
        strm.avail_out = (unsigned int)([compressed length] - strm.total_out);
        
        deflate(&strm, Z_FINISH);
        
    } while (strm.avail_out == 0);
    
    deflateEnd(&strm);
    
    [compressed setLength: strm.total_out];
    return [NSData dataWithData:compressed];
}

NSData *brs_un_gzipData(NSData *gzipData){
    if ([gzipData length] == 0) return gzipData;
    
    unsigned full_length = (unsigned)[gzipData length];
    unsigned half_length = (unsigned)[gzipData length] / 2;
    
    NSMutableData *decompressed = [NSMutableData
                                   dataWithLength:full_length + half_length];
    BOOL done = NO;
    int status;
    
    z_stream strm;
    strm.next_in = (Bytef *)[gzipData bytes];
    strm.avail_in = (unsigned)[gzipData length];
    strm.total_out = 0;
    strm.zalloc = Z_NULL;
    strm.zfree = Z_NULL;
    
    if (inflateInit2(&strm, (15 + 32)) != Z_OK) return nil;
    while (!done) {
        // Make sure we have enough room and reset the lengths.
        if (strm.total_out >= [decompressed length])
            [decompressed increaseLengthBy:half_length];
        strm.next_out = [decompressed mutableBytes] + strm.total_out;
        strm.avail_out = (uInt)([decompressed length] - strm.total_out);
        
        // Inflate another chunk.
        status = inflate(&strm, Z_SYNC_FLUSH);
        if (status == Z_STREAM_END) done = YES;
        else if (status != Z_OK) break;
    }
    if (inflateEnd(&strm) != Z_OK) return nil;
    
    // Set real length.
    if (done) {
        [decompressed setLength:strm.total_out];
        return [NSData dataWithData:decompressed];
    } else return nil;
}

+ (NSData *)unGzipData:(NSData *)gzipData {
    if ([gzipData length] == 0) return gzipData;
    
    unsigned full_length = (unsigned)[gzipData length];
    unsigned half_length = (unsigned)[gzipData length] / 2;
    
    NSMutableData *decompressed = [NSMutableData
                                   dataWithLength:full_length + half_length];
    BOOL done = NO;
    int status;
    
    z_stream strm;
    strm.next_in = (Bytef *)[gzipData bytes];
    strm.avail_in = (unsigned)[gzipData length];
    strm.total_out = 0;
    strm.zalloc = Z_NULL;
    strm.zfree = Z_NULL;
    
    if (inflateInit2(&strm, (15 + 32)) != Z_OK) return nil;
    while (!done) {
        // Make sure we have enough room and reset the lengths.
        if (strm.total_out >= [decompressed length])
            [decompressed increaseLengthBy:half_length];
        strm.next_out = [decompressed mutableBytes] + strm.total_out;
        strm.avail_out = (uInt)([decompressed length] - strm.total_out);
        
        // Inflate another chunk.
        status = inflate(&strm, Z_SYNC_FLUSH);
        if (status == Z_STREAM_END) done = YES;
        else if (status != Z_OK) break;
    }
    if (inflateEnd(&strm) != Z_OK) return nil;
    
    // Set real length.
    if (done) {
        [decompressed setLength:strm.total_out];
        return [NSData dataWithData:decompressed];
    } else return nil;
}

@end

测试代码:

     NSData *data = [str dataUsingEncoding:(NSUTF8StringEncoding)];

    CFAbsoluteTime startTime =CFAbsoluteTimeGetCurrent();
    //在这写入要计算时间的代码
    NSData *result = brs_gzipData(data);
    CFAbsoluteTime linkTime = (CFAbsoluteTimeGetCurrent() - startTime);
    NSLog(@"C函数压缩时间 %f ms", linkTime *1000.0);
    
    CFAbsoluteTime startTime1 =CFAbsoluteTimeGetCurrent();
    //在这写入要计算时间的代码
    NSData *result1 = [GZip gzipData:data];
    CFAbsoluteTime linkTime1 = (CFAbsoluteTimeGetCurrent() - startTime1);
    NSLog(@"OC方法压缩时间 %f ms", linkTime1 *1000.0);
    
    CFAbsoluteTime startTime2 =CFAbsoluteTimeGetCurrent();
    //在这写入要计算时间的代码
    NSData *result2 = [GZip unGzipData:result];
    CFAbsoluteTime linkTime2 = (CFAbsoluteTimeGetCurrent() - startTime2);
    NSLog(@"OC方法解压缩时间 %f ms", linkTime2 *1000.0);
    
    CFAbsoluteTime startTime3 =CFAbsoluteTimeGetCurrent();
    //在这写入要计算时间的代码
    NSData *result3 = brs_un_gzipData(result1);
    CFAbsoluteTime linkTime3 = (CFAbsoluteTimeGetCurrent() - startTime3);
    NSLog(@"C方法解压缩时间 %f ms", linkTime3 *1000.0);
    

测试结果:
真机(iphonex)和模拟器的结果类似,但是真机的执行时间大概是模拟器的一半。
OC的文件压缩时间平均值总是少于C函数的压缩时间。
OC的文件解压缩时间平均值总是大于C函数的解压缩时间。

相关文章

网友评论

      本文标题:探究xcode执行c函数和OC方法的效率问题

      本文链接:https://www.haomeiwen.com/subject/vwjfzftx.html