28장: 파이썬 성능 최적화
파이썬은 다양한 용도로 사용되는 유연한 언어지만, 때로는 성능 최적화가 필요할 수 있습니다. 이 장에서는 파이썬 코드의 성능을 분석하고 최적화하는 다양한 기법을 다룹니다. 주요 내용으로는 코드 프로파일링, 메모리 최적화, 컴파일러 사용, 병렬 처리, 그리고 효율적인 데이터 구조 사용을 포함합니다.
#### 28.1 코드 프로파일링
코드 프로파일링은 프로그램의 실행 시간을 분석하여 성능 병목을 찾아내는 과정입니다. 파이썬에서는 `cProfile` 모듈을 사용하여 코드를 프로파일링할 수 있습니다.
##### 28.1.1 `cProfile` 사용 예제
```python
import cProfile
def my_function():
total = 0
for i in range(10000):
total += i
return total
cProfile.run('my_function()')
```
##### 28.1.2 `line_profiler` 사용 예제
`line_profiler`는 함수 내부의 각 라인별 실행 시간을 측정할 수 있습니다. 먼저 `line_profiler`를 설치해야 합니다.
```sh
pip install line_profiler
```
```python
from line_profiler import LineProfiler
def my_function():
total = 0
for i in range(10000):
total += i
return total
profiler = LineProfiler()
profiler.add_function(my_function)
profiler.run('my_function()')
profiler.print_stats()
```
#### 28.2 메모리 최적화
메모리 사용을 최적화하면 프로그램의 성능을 크게 향상시킬 수 있습니다.
##### 28.2.1 `memory_profiler` 사용 예제
`memory_profiler`를 사용하여 함수의 메모리 사용을 분석할 수 있습니다. 먼저 `memory_profiler`를 설치해야 합니다.
```sh
pip install memory_profiler
```
```python
from memory_profiler import profile
@profile
def my_function():
a = [i for i in range(10000)]
b = [i**2 for i in range(10000)]
return a, b
my_function()
```
##### 28.2.2 제너레이터 사용
제너레이터는 메모리를 절약하는 데 유용한 도구입니다.
```python
def my_generator():
for i in range(10000):
yield i
gen = my_generator()
for value in gen:
print(value)
```
#### 28.3 컴파일러 사용
파이썬 코드를 컴파일하여 성능을 향상시킬 수 있습니다. `Cython`은 파이썬 코드를 C로 컴파일하여 성능을 향상시키는 도구입니다.
##### 28.3.1 `Cython` 사용 예제
먼저 `Cython`을 설치합니다.
```sh
pip install cython
```
다음은 `Cython`을 사용하여 파이썬 코드를 컴파일하는 예제입니다.
```python
# mymodule.pyx
def my_function():
total = 0
for i in range(10000):
total += i
return total
```
```python
# setup.py
from setuptools import setup
from Cython.Build import cythonize
setup(
ext_modules=cythonize("mymodule.pyx")
)
```
```sh
python setup.py build_ext --inplace
```
```python
import mymodule
print(mymodule.my_function())
```
#### 28.4 병렬 처리
병렬 처리는 여러 작업을 동시에 실행하여 성능을 향상시킬 수 있습니다. 파이썬에서는 `multiprocessing` 모듈을 사용하여 병렬 처리를 구현할 수 있습니다.
##### 28.4.1 `multiprocessing` 사용 예제
```python
import multiprocessing
def worker(num):
print(f'Worker: {num}')
if __name__ == '__main__':
processes = []
for i in range(5):
p = multiprocessing.Process(target=worker, args=(i,))
processes.append(p)
p.start()
for p in processes:
p.join()
```
##### 28.4.2 `concurrent.futures` 사용 예제
`concurrent.futures`는 고수준의 병렬 처리 인터페이스를 제공합니다.
```python
from concurrent.futures import ThreadPoolExecutor
def worker(num):
print(f'Worker: {num}')
with ThreadPoolExecutor(max_workers=5) as executor:
for i in range(5):
executor.submit(worker, i)
```
#### 28.5 효율적인 데이터 구조 사용
효율적인 데이터 구조를 사용하면 성능을 향상시킬 수 있습니다. 파이썬의 내장 데이터 구조 외에도 `collections` 모듈의 데이터 구조를 사용할 수 있습니다.
##### 28.5.1 `collections` 모듈 사용 예제
```python
from collections import deque, defaultdict, namedtuple
# deque 사용 예제
d = deque([1, 2, 3])
d.append(4)
print(d)
# defaultdict 사용 예제
dd = defaultdict(int)
dd['key'] += 1
print(dd)
# namedtuple 사용 예제
Point = namedtuple('Point', ['x', 'y'])
p = Point(1, 2)
print(p.x, p.y)
```
#### 28.6 최적화 기법 요약
- **코드 프로파일링**: `cProfile`, `line_profiler` 등을 사용하여 코드의 성능 병목을 찾습니다.
- **메모리 최적화**: `memory_profiler`를 사용하여 메모리 사용을 분석하고, 제너레이터를 사용하여 메모리 사용을 줄입니다.
- **컴파일러 사용**: `Cython`을 사용하여 파이썬 코드를 C로 컴파일합니다.
- **병렬 처리**: `multiprocessing`과 `concurrent.futures`를 사용하여 병렬 처리를 구현합니다.
- **효율적인 데이터 구조 사용**: `collections` 모듈의 효율적인 데이터 구조를 사용합니다.
이상으로, 파이썬 코드의 성능을 최적화하는 다양한 기법에 대해 알아보았습니다. 추가로 알고 싶은 내용이나 질문이 있으시면 댓글로 남겨주세요!
---
이 글의 내용은 GoalKicker.com의 Python Notes for Professionals 책을 참조하였습니다.
댓글
댓글 쓰기