2023.11.06 TIL
Embedded System에서는…
Bottleneck이 발생할 우려가 크다.
Python Application 최적화 : User Level
🌊 코드 최적화
최적화 전 (Recursive Function)
import time
def fibonecci(n):
if n <= 1:
return n
else:
return fibonacci(n-1) + fibonacci(n-2)
start_time = time.time()
n = 30
fib = fibonacci(n)
end_time = time.time()
print(f"Fibonacci({n}) = {fib}")
print(f"Execution time: {end_time - start_time:.4f} seconds")
최적화 후 (Dynamic programming)
import time
def fibonecci(n):
fib_values = [0, 1]
for i in range(2, n+1):
fib_values.append(fib_values[i-1] + fib_values[i-2])
return fib_values[n]
start_time = time.time()
n = 30
fib = fibonacci(n)
end_time = time.time()
print(f"Fibonacci({n}) = {fib}")
print(f"Execution time: {end_time - start_time:.4f} seconds")
최적화에 따른 변수, 함수 메모리 사용량 비교
List 대신 tuple 사용
🌊 최신 Python 버전 사용
예시로 v3.8 이후 math.dist 함수의 Euclidean distance function → sqrt로 구현하는 것보다 훨씬 빠르다
🌊 Profiling, Benchmarking
cprofile
- 성능 bottleneck을 분석하기 위한 library
- 함수별 call 횟수, 실행시간, memory 사용량 등
- 어떤 함수가 bottleneck인지 파악할때 유용
timeit
- 소스코드 실행시간 측정
- 함수 쉽게 테스트 가능
memory_profiler
- Memory 사용량 측정
- 코드 블록단위, 각 line마다 사용되는 memory 양 (느림)
pip3 install memory-profiler
🌊 병렬 처리 및 동시성
Threading
ayncio
Multiprocessing
🌊 JiT Compiler 사용
Interpreter 기반이지만 Byte code→Native code 속도가 빠르다
pip3 install numba
PyPy, Numba 등
🌊 C/C++ 확장 사용
Cython
C로 변환 가능한 python 모듈을 작성하기 위한 언어
Python 코드를 C로 변환하고 Cpython을 사용해 C 코드를 python 모듈로 빌드
코드의 실행 속도가 빨라진다
ctypes
C 함수를 호출하고, C 함수 library를 사용하는 python 코드를 작성하는데 사용하는 interface
Python 코드에서 C 함수와 변수 호출가능
gcc -shared -o matrix_multiply.so 6_matrix_multiply.c -fPIC
python3-config --cflags
🌊 External Library 활용
numpy
행렬 곱셈 등등 갖다쓰기 좋다
🌊 I/O 작업 최적화
Network/Disk I/O 관련
Normal read / mmap / async I/O
최적화 : Kernel Level
프로파일링 툴
htop, top
sudo apt-get install htop
- 터미널에서 실행중인 process(application)와 system resource 사용률을 실시간으로 표시
- htop은 top의 향상된 버전
Mpstat
sudo apt-get install sysstat
- 다중 processor system의 CPU 사용률을 표시
- CPU 코어의 활동 유휴 상태 모니터링 가능
- ex:
mpstat -n 1
→ 1초마다 해당 상태를 업데이트해서 보여줌
Perf
sudo apt-get install perf-tools
- 운영체제가 어떻게 돌어가는지 웬만한건 다 확인가능
- 하드웨어 이벤트 및 소프트웨어 이벤트를 수집, 분석 가능
- 많은 하위 명령어 존재 (
perf record
, report
, annotate
, …)
- 하드웨어 성능 카운터를 이용해 CPU event(ex: Cache miss, branch miss) 모니터링 가능
- Application/Kernel의 성능 프로파일 수집가능, 시간이 긴 함수, 자주 호출되는 함수 등 성능에 문제가 있는 코드를 식별가능
- User/Kernel Space에서 발생하는 성능 데이터를 수집하고 파일에 저장 가능
- 어떤 녀석을 수집할건지, 샘플링 빈도 정의 가능
- 프로그램의 성능 관련 통계를 수집하고 출력 가능, 성능 특성을 이해하고 개선방향 찾는게 가능
확인해볼만한 포인트들
- Context switching Overhead (CPU)
- Page fault Overhead (CPU, Memory)
- Fike I/O Overhead (Disk)
- Scheduling Overhead (CPU)
help
, F4
검색으로 더 자세한 사용법 보기
strace
- User Level application과 system call 관련된 이벱트를 추적하고 기록하는 도구
- System call → User와 Kernel 간의 interface
- 호출에 실행되는 순서, 전달되는 인자, 반환값 등을 확인가능
- Syscall의 이름, 호출 시점, 전달되는 parameters, 반환값, 오류 코드
- Signal과 관련된 이벤트 (signal 발생 및 처리 (
control+D
등)
strace -p 1234
→ top/htop에서 볼 수 있는 pid로 추적
strace -e trace-open, close ls
→ open, close 이벤트만 추적
strace -o trace_output.txt ls
→ trace의 output을 파일로 저장
ftrace
- ⚠️사용시 주의⚠️ 대부분의 tracing이 성능 저하를 가져오고, 매우 오래걸림
lsof
- Linux에서 열린 파일, 디렉토리, 소켓, 파이프 등을 나열해줌
- Linux는 모든 것을 파일로 관리하기 때문에 유용
- Process별로 제공
eBPF(Extended Berkeley Packet Filter)
- 사용자가 커널 기능을 확장하거나 추가할 수 있는 framework
- 사용자가 작성한 eBPF 프로그램을 커널 공간에서 안전하게 실행할 수 있는 구조를 만들어놓음
- 매우 엄격한 검증 과정을 거치며, 안전하지 않은 프로그램이 실행되는 것을 방지
- 커널에서 발생하는 다양한 이벤트를 추적하고 분석하는 기능 제공
- 보통 C로 작성, Python으로도 확장하능
- 코드 작성후 eBPF compiler를 사용해 Bytecode로 변환 후 커널에서 실행
- BCC(BPF Compiler Collection)
sudo apt-get update;sudo apt-get upgrade
sudo apt install clang llvm libelf-dev python3 python3-pop python3-dev
sudo apt install rapberrypo-kernel-headers
Kernel이 compile 되어있는지 확인sudo mod probe configs
zgrep -E "(BPF|XDP) /proc/config.gz
아마 안되어있을것…
Device Driver
- Kernel-Hardware간 interface 역할
- Hardware의 동작을 관리
- 유저 레벨 애플리케이션과 커널 사이 데이터 전달하는 역할
- 모듈화 되어있어 동적으로 삽입 및 제거 가능
목적
- 추상화
- HW-SW 간의 추상화 제공
- Application 개발자는 HW에 대한 이해가 부족해도 HW 사용가능
- 표준화
- 하드웨어에 대한 표준 인터페이스 정의
- 애플리케이션 개발자는 다양한 하드웨어에 일관된 방식으로 접근 가능
- Hardware 지원
- 디바이스를 사용하기 위한 필요 기능 구현
- 커널이 다양한 하드웨어를 지원하는 것에 큰 도움이 된다.
종류
- 문자 디바이스 드라이버
- 순차적으로 접근할 수 있는 디바이스( ex: 시리얼 포트, 키보드) 와 통신
- 이 디바이스 드라이버를 통해 데이터를 바이트 단위로 읽고 쓰기가 가능
- 블록 디바이스 드라이버
- 블록 기반의 무작위 접근이 가능한 디바이스 (ex: 하드 디스크, 플래쉬 메모리)와 통신
- 데이터를 블록 단위로 읽고 쓰기가 가능
- 네트워크 디바이스 드라이버
- 네트워크 인터페이스 카드(NIC) 같은 네트워크 하드웨어와 통신
- 데이터 패킷을 송 수신
Compile
C 로 코드를 작성
컴파일 후 삽입 또는 제거가 가능
Make
sudo make install
sudo modprobe <module_name>
sudo modprobe -r <module_name>