스위프트에서 퍼포먼스란?

퍼포먼스라는 것은 개발언어에서 여러가지 다양한 노력의 결과가 가져다 주는 사용 속도의 향상과 공간의 절약을 의미합니다. 여기서는 WWDC 2016 session-416 Understanding swift performance를 바탕으로 퍼포먼스 개선을 위한 방법을 소개합니다.

스위프트에서 퍼포먼스의 의미

  • Allocation

    • 당신이 코드에서 무엇을 하던 일단 메모리에 저장이 되고 나서야 뭐라도 실행이 가능합니다.

    • 메모리의 영역은 스택과 힙으로 구부

    • 스택(stack)

      •  빠릅니다

      • class 타입 외의 모든 값을 저장합니다.

      • 개발자가 별도로 객체의 소유권을 선언하거나 해지할 필요가 없이 사용 스코프를 벗어나면 소멸합니다. 참고로 swift던 objective-c with arc 던 결국 클래스는 컴파일러가 객체의 소유권의 선언과 해지를 해주고 있습니다.

      • swift 2.0부터 protocol and value type 중심의 코딩을 밀고있는 이유가 이것에 있죠

    • 힙(heap)

      •  느립니다

      • class 타입을 저장함

      • 개발자가 코드상에서 객체의 소유권에 대한 선언과 해지를 명시해서 컴파일러가 제대로 객체를 해지하거나 소유할 수 있게 해야합니다. 이 부분에서 실수를 하면 앱이 크래쉬가 나게 됩니다.

      • ARC 이후, 코드상에서는 신경쓰지 않아도 되지만, 구조적으로는 신경쓰지 않으면 예상하지 못한 버그를 발생시키게 됩니다.

  • Reference Counting

    • 객체의 소유권에 대한 선언과 해제

    • 선언과 해지의 빈도수가 적을 수록 좋습니다.

    • ARC 이후, 코드상에서는 보이지 않지만, 컴파일러가 객제의 소유와 해지를 해주고 있습니다. 구조적으로는 객체의 소유에 대해서 신경써야합니다.

  • Method Dispatch

    • method overriding과 특히 관련이 많습니다.

    • 슈퍼클래스의 메소드를 상속하거나, 한 메소드에서 다른 메소드를 호출하는 빈도에 대한 내용입니다.

    • static

      • final 타입으로 상속을 제한한 경우 속도가 빠릅니다.
    • dynamic

      • 상속이 가능하며 속도가 final function에 비하여 느립니다.

Allocation 방식의 비교

스택

  • 각 작업에 대한 스택포인터의 가감이 전부입니다

  • 고수준(복잡하다고 읽으면 됩니다) 데이터 구조

  • 데이터를 쓰기 위한 빈 영역 검색

  • 데이터를 해지하기 위한 메모리 블럭 재배치

  • 멀티스레드를 사용한 경우 스레드 세이프티를 위한 오버헤드 발생

  • 스택의 값을 class객체의 인스턴스에 복사하는 과정 필요

결론

  • 같은 기능을 가진 struct와 class의 퍼포먼스는 struct의 압승입니다.

Reference Counting 의 비교

struct

  • struct내의 인스턴스가 class가 아닌경우 class에 비해 reference counting이 없어 매우 빠릅니다.

  • struct내의 인스턴스가 class와 같이 reference를 가진 객체인 경우 모든 인스턴스에 대해 객체의 소유와 해지가 발생하기 때문에 경우에 따라 class보다 reference counting이 더 많아질 수 있습니다.

  • struct내의 인스턴스들이 최대한 class가 아닌 enum, struct로 대치할 수 있는 구조를 짜도록 해당 세션은 권하고 있습니다.

class

  • struct에 비해 평균적으로 reference counting이 많습니다. 다만 struct의 내부 인스턴스가 class인 경우 더 나을 경우도 있습니다.

결론

  • 상황에 따라 다르지만, 구조를 잘 설계할 경우 struct의 압승입니다.

Method Dispatch의 비교

Static 함수

  • 런타임시에 바로 함수를 찾아갑니다.

  • final, private, struct에서 선언한 함수, final class의 함수, 그리고 build settings-> Optimization Level 을 Whole Module Optimization(컴파일 속도는 느려지지만, 모든 함수를 static으로 만들어 줍니다. 느리니까 배포시에만 사용합시다.)으로 설정한 경우의 모든 함수

Dynamic 함수

  • 실행시에 함수 테이블에서 함수를 찾습니다.

  • 함수의 메모리 번지로 이동합니다

  • 실행합니다.

  • 함수를 실행하려고 시도 할 때마다 객체의 함수 테이블을 참조해야해서 속도가 Static함수에 비해 많이 느립니다.

다음글은 protocol구조를 활용한 퍼포먼스 향상에 대해 올리겠습니다.