Q. 왜 Python은 C언어보다 느린가?
1. Python의 변수는 Dynamically Typed이기 때문이다
Static Typing Dynamic Typing
-
Static typing은 runtime 이전(또는 compile-time)에 하는 type checking
장점 : 실행 속도가 빠름, 컴파일 최적화를 통해 runtime 효율성 향상 및 메모리 사용 절약 가능
단점 : development-time이 길어 빠르게 변화하는 요구사항에 대처하기 어려움
-
Dynamic typing은 runtime에 하는 type checking
장점 : development-time이 짧고 빠르게 변화하는 요구사항에 대처하기 쉬움
단점 : type checking을 runtime에 하기 때문에 실행 속도가 느림, runtime error가 비교적 많이 발생
Example
-
Dynamic Typing은 runtime에 type checking을 함으로써 모든 작업에 더 많은 단계가 포함되어 있다는 것을 의미한다. Statically typed language인 C 언어의 변수와 Dynamically typed language인 Python 언어의 변수를 활용한 덧셈과정을 살펴보면 단계 수가 차이나는 걸 바로 확인할 수 있다.
2. Python은 Interpreted되기 때문이다
Interpret Compile
-
프로그램 언어를 해석하고 실행시키는 대표적인 방법으로 Compile 과 Interpret 방식이 있다
-
Complie
- 과정
-
Preprocessing (预处理)
- '#’ 으로 시작하는 부분에 대해서는 C컴파일러가 쉽게 인식할 수 있도록 C언어 소스를 재정리
- 주석 제거
- source code file을 Preprocessing 한 다음 확장자가 .i 또는 .c 인 file을 생성하게 됨
-
Compile (编译)
- 전처리가 끝난 source code를 기반으로 assembler code file (확장자가 .s인 file) 를 생성
-
Assemble (汇编)
- assembler code를 바탕으로 Object file (확장자가 .o인 file) 을 생성
- Object file 부터는 Binary code로 되어있어 사람 이해할 수 없는 형태
-
Link (连接)
-
Link 작업을 통하여 여러 Object file 파일들과 표준 C Library(확장자가 .a 또는 .so인 file), 사용자 Library들을 합쳐서 실행 파일을 만들 수 있다
-
Static Link :
Linker가 프로그램이 필요로 하는 부분을 Library에서 찾아 실행파일에다가 바로 복사
직접 구현한 code를 library화 시켜 기술 유출 방지로 사용 가능
실행 파일 내에 library code가 저장되기 때문에 메모리를 많이 잡아먹음
-
Dynamic Link :
어떤 기능이 실행 파일에 직접 덧붙여 지지 않고, library file에 독립적으로 존재하다가 프로그램이 실행될때 동적으로 링크되어 사용됨
최근 소프트웨어들은 Static Link를 하용하면 실행파일이 너무 커져서 Dynamic Link 사용
내 프로그램 영역에서 Library가 저장되어 있는 주소로 jump하는 거라 성능상 overhead가 듬
Library만 version up이 되면 그거에 대한 성능을 내가 그대로 받을 수 있다
-
성능 상으로는 Static Link이 좋지만 메모리 관리 차원에서는 Dynamic Link가 좋음
-
-
파일의 변천사
-
최적화
-
같은 기능의 프로그램을 만들지만, 실행 속도나 메모리 점유율이 낮아지도록 최적의 코드로 만드는 것을 의미한다. 코드의 최적화는 크게 두가지로 나뉜다 :
-
중간코드의 최적화 : Source Code를 기반으로 공통 부분과 불필요한 부분을 제거한다.
-
목적코드의 최적화 : 메모리 로드의 기준에서 가장 효율적인 메모리나 레지스터의 할당을 하도록 한다.
-
-
-
Interpret
- 고급언어로 작성된 프로그램을 한문장씩 읽고 번역 후 실행하는 방식
- 프로그래머가 수정한 사항이 바로 반영
- source code의 일부를 입력으로 넣기 때문에 컴파일타임 에러를 못잡아냄
- Interpreter가 설치된 곳 이면 어느 곳에서도 실행이 가능하므로 프로그램 이식성이 높음
- 컴파일러는 반복되거나 불필요한 연산을 미리 내다보고 최적화된 실행 파일을 생성하여 실행 속도를 높일 수 있다
- 하지만 Python interpreter는 컴파일되지 않은 source code를 interpret하고 실행시키기 때문에 실행시간이 더 걸린다
3. Python의 Object model은 비효율적인 Memory access가 발생할 수 있기 때문이다
-
특히 순차적인 데이터 구조에서 연속적인 데이터에 대해 동작을 할 경우 비효율적인 Memory access가 발생할 수 있다
参考 : Numpy 배열은 C의 Array과 유사함
-
Array는 반드시 할당된 메모리 공간은 연속적이라는 것이다, 그리고 Array의 모든 아이템들이 똑같은 사이즈를 가진다
-
반면, List는 index를 갖지만 이는 몇 번째 데이터인가 정도를 의미한다, List는 아이템들의 메모리 주소가 연속적일 수도 있고, 아닐 수도 있다.
-
정리
Python이 C보다 느린 이유들 :
- Python의 변수는 Dynamically Typed이기 때문에 Runtime 때 C의 변수보다 더 많은 과정이 필요하다.
- Python은 Interpreter 언어이다. Interpreter 언어는 Compiled 언어와는 달리 코드를 한 줄씩 번역하고 실행하는 방식이기 때문에 실행 속도는 Compiled 언어인 C 보다 느리다.
- Python에서 List 같은 순차적인 데이터 구조는 C의 순차적인 데이터 구조보다 Memory access가 비효율적이다
Q. 그럼 Python과 Java 중 어떤 것이 빠른가?
-
실행 시간으로 봤을 땐 Java가 보통 더 빠르다. Interpreter 입장에선 사람이 알아보는 source code를 machine code로 바꿔서 처리하는 거 (Python) 보단 컴파일러를 거쳐나온 bytecode를 바로 처리하는게 (Java) 더 빠를 수 밖에 없다.
-
Example. 0 ~ 99 숫자를 “-” 로 이어라 (0-1-2-3-4 … -97-98-99)
Python : 0.323 초
Java : 0.198 초
-
프로그램 실행 시간으로 봤을 때 무조건 빠른 프로그래밍 언어를 선택해야되는건 아니다
- Java Interpreter(JVM)은 컴파일러를 거쳐나온 bytecode를 바로 처리할 수 있기 때문에 빠르다
- 즉, Java는 실행시간이 Python 보다 빠르지만 bytecode가 build-up되지 않으면 무용지물이다
- 프로젝트의 Source code가 커지면 Compile 시간도 고려를 해야된다
Q. 그렇다면 왜 Python을 사용하나?
- 이렇게 본질부터 비효율적임에도 불구하고, 왜 우리는 파이썬을 사용하려고 생각할까?
- Dynamic typing은 Python을 C보다 사용하기 쉽게 해줌
- 이 유연함은 개발시간의 효율적인 사용을 이끌어냄
- Python은 GLUE 언어라고도 부르는데, 그 이유는 다른 언어들과 잘 어울려 다른 언어와 결합해서 사용할 수 있기 때문이다
- CPython : Python 코드를 컴파일하여 machine code로 바꾸고 그 다음에 interpreter(virtual machine)가 실행 ( Python 코드를 C언어로 바꾸는 것이 )
- Jython : python 코드를 java bytecode로 만들어 JVM에서 실행할 수 있도록 함
Q. Java와 C의 차이는?
-
C언어에 비해 Java가 느린 이유
-
C언어는 컴파일 시 코드를 모두 기계어로 직접 번역해서 바로 메모리에 올려두고 실행한다. 하지만 Java에서는 먼저 Bytecode로 컴파일을 한 뒤, 동적 할당 된 코드를 JVM의 Excution Engine이 번역해서 실행하게 된다.
-
C언어에서는 동적 할당한 메모리를 개발자의 명령에 따라 즉시 해제하지만, Java는 직접 메모리를 다루지 않도록 되어 있기 때문에 이 작업을 GC(가비지 컬렉터)가 대신해준다. GC도 프로그램이기 때문에 메모리와 연산 작업을 동반한다.
-
즉, 개발자가 편해지는 만큼 컴퓨터가 일을 더 해야하니 더 느릴 수밖에 없는 구조이다.
-
-
Compile 과정에서 차이
- Java는 Link 과정이 없음, compiler가 바로 bytecode를 생성 그리고 이 bytecode file이 운영체제 위의 JVM에서 실행됨으로써 다양한 운영체제에서 독립적으로 사용이 가능
- C의 경우, Compile 해서 생성된 실행 파일은 Platform에 종속적인 code가 있고 만약 Platform이 바뀐다면 다시 Compile해야 된다
결론
- 프로그램 실행에 있어서 Python은 Java와 C언어에 비해 느리다
- 하지만 Python이 Java와 C언어에 비해 제공하는 operation도 많고 가독성도 좋고 여러 방면에서 개발할 때 더 효율적인건 사실이다
- 요즘같이 불명확성이 높은 상황에서 소프트웨어 개발하는 시간이 너무 길면 안된다
- 가지고 있는 컨셉이 있으면 최대한 빨리 주요한 부분만 만들어서 제품을 내놓아야된다
- 그리고 그 컨셉을 증명해야된다
- End-user한테 가치를 전달할 수 있는 소프트웨어를 만드는게 중요하다
- 그래서 차라리 Python을 가지고 먼저 만들고 출시해서 반응이 좋다면 Java 나 C 로 migration하면된다
《Reference》