본문 바로가기
WWDC

WWDC 15 - Optimizing Swift Performance

by vapor3965 2021. 6. 27.

목차


    • 세션보면서 정리한 내용입니다. 해석이 잘못된 경우가 있을수있으니 발견하시면 댓글로 남겨주시면 감사하겠습니다🙏🏻

     

    https://developer.apple.com/videos/play/wwdc2015/409/

     

    Optimizing Swift Performance - WWDC15 - Videos - Apple Developer

    Hear from the experts about how you can write faster Swift code and use Instruments to identify performance bottlenecks. Dive deep into...

    developer.apple.com


     

    관련내용

    • 더효과적인코드를 작성할수있도록 도와주는 기술들을 발견하라~

    👍요약

    • swift는 컴파일러를통해 최적화가 다양하게 이루어지기때문에 빠르다.
    • 👍generic에서는 타입정보만 알수있다면 generic specialization이라는 최적화가 이루어질 수 있다.
    • 👍각파일은 개별적으로 병렬로 빌드되어지는데, whole module opimization은 모든모듈을 하나로봄으로써 빌드속도는 느려지지만 컴파일된바이너리파일은 런타임에서 빠르다. 그러므로 release모드에서는 이방법을사용해야한다.
    • class를 배열에넣어, for p in [class]하거나, 함수에넘길때도, 참조하는새로운변수가생성됨으로써 레퍼런스카운팅+-1 이발생한다.
    • final, private, whole module optimization을 통해 dynamic dispatch를 제거하라

     

     


    swift

    • 어떻게 swift가 빠를수있을까,
    • 컴파일러에서 다양한 최적화를시도한다.
      • 아래와같이 없애고,최적화하고,등등…

    bounds check elimination

    • 간단한 포문안에서도 아래와같은 조건문이생성된다.

    • 하지만 컴파일러는 위로 보냄으로써 조건이한번만실행도록한다.

     

     

    컴파일러는 파일들을 개별적으로컴파일한다. 이는 병렬적으로 실행이가능하도록하여 속도가향상된다.
    대신 최적화는 한파일에만 제한된다.

    Whole Module optimization

    • 하지만 이를 키게되면, 최적화는 더이상 한파일에 제한되어지지않고, 전체모듈로 분석하여최적화가 가능해진다.
    • 당연히도, 빌드시간은 증가될수밖에없다.
    • 하지만! 당연하게도, 빌드된바이너리는 일반적으로 빠를수밖에없다! ㅎ
    • 하지만,ㅎㅎ 대단하게도 애플은 whole module optmization 모드에서도 그룹적으로병렬?실행이가능하게끔하여 기존보다 더 빨라지도록했다.

    퍼포먼스향상하기

    • Reference counting
    • Generics
    • Dynamic dispatch

     

    Reference counting

    • 컴파일러는 레퍼런스참조오버헤드를 줄인다. 하지만, 그래도 오버헤드가존재하는걸발견할수있다.
    • 그래서 2가지방법이있다.

    우선 어떻게 레퍼런스카운팅이동작하는지보자.

    • x는 C클래스인스턴스가저장되는데, 가장상단에 1이란는값이저장된다. 이는 레퍼런스카운트를의미한다.



    y는 x를 강한참조함으로써 2가된다.


    마찬가지로 함수도 강한참졸르하여 3이된다.

    • 실제로 y를 전달하기보다는, 참조하는 c를 만들어전달한다. 그러므로 3이된다.



    그리고 foo()함수가종료되어 줄어든다.


    배열안에 클래스타입들을 만들고, for문으로 p를 호출하면, 생성되어진다.

    • 그러므로 매번 안에서 레퍼런스참조 증가,감소 가발생한다 . 당연히 오버헤드가따른다.

    struct

    • 하지만 struct로 바꾸면, 참조횟수를 요구하지않는다.

    • 👍그러므로, for문안에서 따로 참조회수그런 오버헤드가발생하지않는다!!

     

     

    struct & reference counting

    • struct 그자체는 레러펀스카운팅을 가지지않지만, 경우에따라 가지게된다.
    • 즉 class를 가지는 struct일경우 발생한다.
    • 같은struct타입객체를 복사하면 아래와같이 레퍼런스참조하게된다.
    • 뭐, 하나정도는 괜찮다!!!


    • 극단적으로 struct가 많은 레퍼런스를가질경우!
      • 다 value타입인데, 내부데이타의 라이프타임을 관리하기위해 내부적으로 클래스가사용된다. ( ???? )
      • 그러므로, 이를 복사하면 레퍼런스카운팅비용이발생한다.


      • 뭐, 굳이 struct를 쓰겠다면, wrapper class를 사용해라.
        • 그럼으로써 레퍼런스카운팅을하나로만줄이도록할수있다.
      • 하지만 이런경우 struct, class 타입이섞여있으니 이상한결과가나타날수있다.

     

     

    Generics

    • 아래와같은 단순한 3문장 코드여도 컴파일러는 아래와같이 만들어낸다.
    • 내부적으로 indirection( FTable)을 사용한다.
    • 왜냐하면 어떠한 Comparable을 채택하는 타입이올지모르기때문이다.


    • 하지만,대단하게도! 컴파일러는 generics specialization 이라는 최적화를통해 이러한오버헤들를 줄일수있다.
      • 아래와같이 foo함수가있다면, 컴파일러는 “오, Int타입이쓰였군!” 하면서 아래와같이 min함수가바뀐다. ( 미친..)
    • 그러면서결국아래와같이 최적화되어진다……

    • 하지만, 한가지 제한이있긴한데, 일반적으로 visibility of generic definition이다. min(T? )
      • 즉 int가전달되긴하지만,  하나의파일을 확인할때 Definition을알수가없다.
      • 그러므로, generic specialization이 적용되지않느다.

    • 하지만! whole module optimization과함께라면 ! 가능해진다 ㅎㅎ
      • 다른 곳에있는 파일이여도, 하나의모듈로써 보기때문에, definition이 visible 되기때문이다. 

     

     

     

    dynamic dispatch

    • 컴파일러는 그대로 name을 호출하지않고,
    • 아래와같이 추가한다.

    • 이러한 지시자없이 직접적으로호출하는 경우는, 오직, 해당클래스가 오버라이드되지않았다는것만 알수있을때이다.
    • func noise() 는 overriden되는게 합당하다.
    • 하지만, name은 바람직하지못하다. name은 서브클래스에서 혼자가지고있는게좋겠다.
      • 그래서 두가지방법이있다. 계층, access control.
    • final키워드를 작성하면, 컴파일러는 “오, 서브클래스되지않겠구나, 다이나믹디스패치, 간접적으로호출할필요가없겠군! 하하” 하며 다음과같이 직접적으로호출할수있게된다.

    • 또는 private 키워드를 통해, 다른파일에서 절대로 보여질수가없으니, 컴파일러는 직접적호출이가능해진다.

    • whole module Optimization ( 릴리즈버전에서 사용해라 )
      • 을적용하면, 컴파일러는 다른모듈에서도 Dog 클래스가 다른클래스에서 서브클래스하는지확인한다.
      • 적용하지않는다면, 아래와같이 간접적호출을하게된다.
        • 왜냐하면 Dog클래스가 다른모듈에서 사용됐는지, 즉 서브클래스됐는지모르니까!

    • 대신 켰을경우 & 다른모듈에서도 서브클래스하는게없는게확인되면, 직접적 호출을 하게된다

    • 왜, 객체지향에서 런타임에서 swift가 더빠를까?
      • 그이유는 objective-c는 컴파일러에서 OB-C message로부터 보내온, ? dynamic dispatch를 삭제할수없다.
      • 왜냐하면 컴파일러는 이러한 message가 다른곳에서도 사용됐을수밖에없다라고가정할수바게없다.


    댓글