

最適化を行なった場合、下記の処理のベンチマークの差分はいかほどなのでしょうか？

また、処理を完了するまでの時間の差分、ベンチマークの差分、読みやすいかなどの観点で、  
どちらがより優れたコードになりますでしょうか。

[code]

    - (NSNumber *)sum:(NSArray *)items {
        NSInteger sum = 0;
    
        for (NSNumber* number in menuItemComponents) {
            sum += number.integerValue;
        }
        return [NSNumber numberWithInteger:sum];
    }
    
    
    - (NSNumber *)sum:(NSArray *)items {
        NSNumber * sum = [NSNumber numberWithInteger:0];
        for (NSNumber *number in items) {
            sum = [NSNumber numberWithInteger:sum.integerValue + number.integerValue];
        }
        return sum;
    }
    
[/code]


CC BY-SA 4.0
2018-12-04T13:17:27.457
50902
2019-12-20T07:01:23.147
2019-12-20T07:01:23.147
3060
31290
question
objective-c llvm
LLVMの最適化の処理についての質問


`Xcode`の`XCUnitTest`でほぼ同等と思われるソースの実行時間を計測してみました。  
`items`の個数が少ないと有意差が出にくいので、敢えて極端なアイテム数にしています。

[code]

    #import <XCTest/XCTest.h>
    
    @interface SpeedTestTests : XCTestCase
    
    @end
    
    @implementation SpeedTestTests
    
    - (void)setUp {
        // Put setup code here. This method is called before the invocation of each test method in the class.
    }
    
    - (void)tearDown {
        // Put teardown code here. This method is called after the invocation of each test method in the class.
    }
    
    - (void)testExample {
        // This is an example of a functional test case.
        // Use XCTAssert and related functions to verify your tests produce the correct results.
    }
    
    - (void)testPerformanceNumeric {
        NSArray<NSNumber *> *items = @[@1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10];
        [self measureBlock:^{
            NSInteger sum = 0;
    
            for (NSNumber* number in items) {
                sum += number.integerValue;
            }
        }];
    }
    
    - (void)testPerformanceObject {
        NSArray<NSNumber *> *items = @[@1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10];
        [self measureBlock:^{
            NSNumber * sum = [NSNumber numberWithInteger:0];
            for (NSNumber *number in items) {
                sum = [NSNumber numberWithInteger:sum.integerValue + number.integerValue];
            }
        }];
    }
    
    @end
    
[/code]

結果は、

[code]

    [SpeedTestTests testPerformanceNumeric]' measured [Time, seconds] average: 0.000, relative standard deviation: 20.883%, values: [0.000009, 0.000006, 0.000005, 0.000008, 0.000005, 0.000005, 0.000005, 0.000005, 0.000005, 0.000005], performanceMetricID:com.apple.XCTPerformanceMetric_WallClockTime, baselineName: "", baselineAverage: , maxPercentRegression: 10.000%, maxPercentRelativeStandardDeviation: 10.000%, maxRegression: 0.100, maxStandardDeviation: 0.100
    [SpeedTestTests testPerformanceObject]' measured [Time, seconds] average: 0.000, relative standard deviation: 5.197%, values: [0.000014, 0.000012, 0.000012, 0.000012, 0.000012, 0.000012, 0.000012, 0.000012, 0.000012, 0.000012], performanceMetricID:com.apple.XCTPerformanceMetric_WallClockTime, baselineName: "", baselineAverage: , maxPercentRegression: 10.000%, maxPercentRelativeStandardDeviation: 10.000%, maxRegression: 0.100, maxStandardDeviation: 0.100
    
[/code]

と、平均して倍半分後者の方が遅くなるようですね。  
可読性も、インスタンスの整数値を合計して、インスタンス化して返してるのねと理解しやすいのは前者だとおもうので、前者で充分ではないでしょうか？

しかしながら、プログラム全体を通してみた場合、ここは本当にボトルネックになっているのでしょうか？  
傾向として、プログラムのボトルネックはソースコード全体の10%未満であることが多いので、速度が充分でない場合のみ、プログラム全体を`TimeProfiler`でボトルネックになっている部分を探し、必要ならその部分のみ速度優先のチューニングを行い、そうでない部分については、可読性（最優先は自分にとって、幾つも考えられる場合はその中で誰にでも読みやすい）を優先した方が良い様な気がします。  
速度を意識しすぎて難解なコードを書いて、バグの元になっては本末転倒だと思うので。冗長になっても読みやすいを意識して、あとはコンパイラの最適化に任せる。必要なら、`Xcode`の`UnitTest`には時間計測もあるので、今回の様にそれを使ってみるのも良いかもしれませんが。


CC BY-SA 4.0
2018-12-04T19:14:18.397
50908
2018-12-04T19:20:15.980
2018-12-04T19:20:15.980
14745
14745
50902
answer