예시로 알아보는 Python Heap Memory
프로세스 메모리는 크게 code, data, stack, heap 영역이 있는데 이번 글에서는 stack, heap 영역을 다룰 예정이다
그럼 heap 영역은 왜 알아야 할까?
- 파이썬은 모든 게 객체이기 때문, 즉 값을 heap에 저장하고 stack에서 참조한다
- 모든 thread는 자기 process heap memory 영역을 공유한다 이걸 이용해서 좀 더 유연한 프로세스를 만들 수 있다
- 객체를 무분별하게 생성하지 않기 위해서
- 버그를 찾기 위해
- 기타 등등…
간단하게 예시를 들면
1 | from threading import Thread |
실행 결과는
True
True
True
False
heap 메모리 그림을 보면 프로세스 실행 3초 뒤
thread2가 detect_word를 cat으로 바꾸었기 때문에
heap 메모리를 공유하는 thread1의 detect_word도 cat을 가리키고 있다
dog는 reference counting이 0이 되어 GC에 의해 메모리 해제된다
간단한 예시지만 이런 특징을 사용해서 좀 더 유연한 프로그램을 만들 수 있다
thread 프로그래밍이 장점이 많지만 메모리를 공유하기 때문에 연산 작업할 때는 lock을 사용하여 thread-safe하게 신경 써야 한다
하지만 lock은 처리 시간을 느리게 하므로 주의가 필요하다
자료구조 시간 복잡도
자료구조별 시간 복잡도
실무에서 주로 사용했던 자료구조 시간복잡도를 정리해봤다 작업의 시간복잡도를 보고 효율적인 자료구조를 선택하자
| 자료구조 | 접근 | 검색 | 입력 | 삭제 |
|---|---|---|---|---|
| array list | O(1) | O(n) | O(n) | O(n) |
| set | O(1) | O(1) | O(1) | O(1) |
| stack | O(n) | O(n) | O(1) | O(1) |
| queue | O(n) | O(n) | O(1) | O(1) |
| singled-linked list | O(n) | O(n) | O(1) | O(1) |
| doubly-linked list | O(n) | O(n) | O(1) | O(1) |
| hash table | N/A | O(log(n)) | O(log(n) | O(log(n) |
| binary tree | O(log(n)) | O(log(n)) | O(log(n)) | O(log(n)) |
습관적으로 탐색할 때도 list를 많이 사용했는데 탐색할 때는 list 대신 set을 사용하자
시간 복잡도 그래프
참조링크
Python 병렬처리로 크롤링 시간 단축하기
thread 와 concurrent.futures 사용으로 병렬 처리하기
1. thread 사용으로 병렬 처리
저번 코드에서 save_img 함수를 multi thread로 실행하면 좀 더 빠른 결과물을 얻을 수 있을 것 같다
1 | import requests |
작업결과
작업 시간이 1초대로 단축된 걸 확인 할 수 있다
2. concurrent.futures 사용으로 병렬 처리하기
concurrent.futures는 비동기 처리 고수준 인터페이스 모듈이다 이 모듈을 써서 작업 시간을 줄여보자
1 | import requests |
작업결과
마찬가지로 작업 시간이 1초대로 단축된 걸 확인 할 수 있다
결론
- I/O 작업이 있을 때 병렬 처리 작업을 활용하여 작업 시간을 단축시킬수 있다
- 상황에 따라 다르지만 될 수 있으면 thread 모듈보단 고수준 비동기 concurrent.futures 모듈을 사용하자 병렬처리 작업의 결과물을 리턴 받는 등 다양한 함수를 제공한다 참조링크