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 책을 참조하였습니다.

댓글