2017-11-13 14 views
1

단일 xcodebuild 명령이 모든 개별 대상을 생성하는 데 소비하는 시간을 측정 할 수 있습니까?모든 대상 (종속 된 대상 포함)에 대한 xcodebuild 지속 시간 측정

대상이 있는데, 이는 cocoapod : pod1pod2에 따라 다릅니다. xcodebuild을 사용하여 타겟을 만듭니다. 전체 시간을 측정 할 수 있습니다. 나는

내가 xcodebuild의 출력에서 ​​답을 찾을려고했는데, 그렇게하는 데 실패 별도로 pod1, pod2에 소요 된 시간, 내 목표를 측정 할 필요가있다.

미리 감사드립니다.

답변

1

모든 xcodeprojPods.xcodeproj의 모든 대상을 수정하기 위해 사용자 지정 ruby 스크립트를 작성했습니다. 이 스크립트는 대상 이름과 현재 시간 소인을 출력 파일에 기록하는 두 개의 build phase을 추가합니다. 하나는 build phase이고 다른 하나는 마지막으로 실행됩니다. 나중에 나는 별도의 스크립트로 다른 타임 스탬프를 빼기 만하면된다.

/Users/tryusipov/Desktop/screenshots/Image 2017-11-17 18-23-49.png


출력 파일 (정렬 후)과 같이 표시됩니다 출력 파일에

Alamofire end: 1510929112.3409 
Alamofire start: 1510929110.2161 
AlamofireImage end: 1510929113.6925 
AlamofireImage start: 1510929112.5205 

경로 (/a/ci_automation/metrics/performance-metrics/a.txt에 : 여기

스크립트의 결과입니다 스크린 샷)은 아무렇게나 하드 코드되지 않습니다. 대신,이 같은 ruby 스크립트의 매개 변수로 전달합니다

$ruby prepare-for-target-build-time-profiling.rb ${PWD}/output.txt

참고,이 스크립트는 cocoapods 1.3.1 (아마도 1.3)을 필요로. ruby prepare-for-target-build-time-profiling.rb

#!/usr/bin/env ruby 

require 'xcodeproj' 
require 'cocoapods' 
require 'fileutils' 

def inject_build_time_profiling_build_phases(project_path) 
    project = Xcodeproj::Project.open(project_path) 

    log_time_before_build_phase_name = '[Prefix placeholder] Log time before build'.freeze 
    log_time_after_build_phase_name = '[Prefix placeholder] Log time after build'.freeze 

    puts "Patching project at path: #{project_path}" 
    puts 
    project.targets.each do |target| 
     puts "Target: #{target.name}" 

     first_build_phase = create_leading_build_phase(target, log_time_before_build_phase_name) 
     last_build_phase = create_trailing_build_phase(target, log_time_after_build_phase_name) 

     puts 
    end 

    project.save 

    puts "Finished patching project at path: #{project_path}" 
    puts 
end 

def create_leading_build_phase(target, build_phase_name) 
    remove_existing_build_phase(target, build_phase_name) 

    build_phase = create_build_phase(target, build_phase_name) 

    shift_build_phase_leftwards(target, build_phase) 

    is_build_phase_leading = true 

    inject_shell_code_into_build_phase(target, build_phase, is_build_phase_leading) 

    return build_phase 
end 

def create_trailing_build_phase(target, build_phase_name) 
    remove_existing_build_phase(target, build_phase_name) 

    build_phase = create_build_phase(target, build_phase_name) 

    is_build_phase_leading = false 

    inject_shell_code_into_build_phase(target, build_phase, is_build_phase_leading) 

    return build_phase 
end 

def remove_existing_build_phase(target, build_phase_name) 
    existing_build_phase = target.shell_script_build_phases.find do |build_phase| 
     build_phase.name.end_with?(build_phase_name) 
     # We use `end_with` instead of `==`, because `cocoapods` adds its `[CP]` prefix to a `build_phase_name` 
    end 

    if !existing_build_phase.nil? 
     puts "deleting build phase #{existing_build_phase.name}" 

     target.build_phases.delete(existing_build_phase) 
    end 
end 

def create_build_phase(target, build_phase_name) 
    puts "creating build phase: #{build_phase_name}" 

    build_phase = Pod::Installer::UserProjectIntegrator::TargetIntegrator 
     .create_or_update_build_phase(target, build_phase_name) 

    return build_phase 
end 

def shift_build_phase_leftwards(target, build_phase) 
    puts "moving build phase leftwards: #{build_phase.name}" 

    target.build_phases.unshift(build_phase).uniq! unless target.build_phases.first == build_phase 
end 

def inject_shell_code_into_build_phase(target, build_phase, is_build_phase_leading) 
    start_or_end = is_build_phase_leading ? "start" : "end" 

    build_phase.shell_script = <<-SH.strip_heredoc 
     timestamp=`echo "scale=4; $(gdate +%s%N/1000000000)" | bc` 
     echo "#{target.name} #{start_or_end}: ${timestamp}" >> #{$build_time_logs_output_file} 
    SH 
end 

def parse_arguments 
    $build_time_logs_output_file = ARGV[0] 

    if $build_time_logs_output_file.to_s.empty? || ! $build_time_logs_output_file.start_with?("/") 
     puts "Error: you should pass a full path to a output file as an script's argument. Example:" 
     puts "$ruby prepare-for-target-build-time-profiling.rb /path/to/script/output.txt" 
     puts 
     exit 1 
    end 
end 

def print_arguments 
    puts "Arguments:" 
    puts "Output path: #{$build_time_logs_output_file}" 
    puts 
end 

def clean_up_before_script 
    if File.exist?($build_time_logs_output_file) 
     FileUtils.rm($build_time_logs_output_file) 
    end 

    build_time_logs_output_folder = File.dirname($build_time_logs_output_file) 
    unless File.directory?(build_time_logs_output_folder) 
     FileUtils.mkdir_p(build_time_logs_output_folder) 
    end 
end 

def main 
    parse_arguments 
    print_arguments 
    clean_up_before_script 
    inject_build_time_profiling_build_phases("path/to/project.xcodeproj") 
    inject_build_time_profiling_build_phases("path/to/pods/project.xcodeproj") 
end 

# arguments: 
$build_time_logs_output_file 

main 
: 여기

ruby 스크립트입니다