| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | |||
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 | 16 | 17 | 18 |
| 19 | 20 | 21 | 22 | 23 | 24 | 25 |
| 26 | 27 | 28 | 29 | 30 |
- 산업공학부
- PS
- airflow
- openssl
- 백준
- 메틸페니데이트
- 디자인 패턴
- 파이썬
- 최적화
- strace
- SSL
- 아토목세틴
- Spring
- knapsack
- Celery
- Memory Leak
- ADHD
- memory
- DP
- 메디키넷
- 메모리
- string
- java.lang.ClassNotFoundException
- 콘서타
- 기술부채
- 알고리즘
- docker
- TCP
- 메모리유수
- IntelliJ
- Today
- 0
- Total
- 6,164
목록전체 글 (103)
뜌릅
1. 장애 요약어느 날 갑자기 Airflow 운영 서버의 MongoDB 업로드 Task에서 원인 불명의 에러가 발생했습니다. 코드 변경이 없었음에도 세 가지 양상의 에러가 무작위로 나타났습니다.증상 1 (무한 대기): 로그 없이 40시간 이상 Pending 상태 지속 (알람 미발생).증상 2 (Exit -6): double free or corruption으로 인한 프로세스 강제 종료.증상 3 (Exit -9): OOM(Out of Memory) 발생 및 컨테이너 셧다운.코드도 변경이 없었고, 로그도 일관적이지 않았습니다...2. 디버깅 로그: 원인을 찾기 위한 사투문제 해결을 위해 인프라와 이미지의 모든 경우의 수를 테스트했습니다.구분테스트 내용 및 결과결론코드최신 커밋 리버트(Revert) 후 실행 ..
현재 회사에서는 산업공학부 박사 연구생들을 고용하여 함께 협업을 진행하고 있습니다.그분들이 만든 코드를 최적화한 작업을 소개합니다.최적화를 하게 된 계기박사 연구원의 말로 코어 40개로 이미지 41000개를 processing하여 생성하는데 21시간이 소요된다고 하였습니다.41000장의 용량은 약 8.4GB입니다. (참고로 이미지 1장의 용량은 약 200kb입니다.)하지만 8.4GB을 DISK Write을 하는데에 21시간이 걸리는것은 코드의 어디선가에서 병목이 생겼을거라고 추측하였습니다.CPU 40개로 병렬 실행시, 이미지 Computing 속도는 매우 빠를겁니다.이는 분명히 DISK IO보다 빨라야 합니다. 저는 따라서 Cpu Bound job에 대한 병렬처리에 병목이 있을거라고 추측했습니다.최적화 ..
새로운 요구 사항,,,새로운 요구 사항이 생겼다.우리회사에는 C++로 작성된 엔진파일이 존재한다. 이 코드에 구현된 알고리즘을 통해 우주에서 발생할수 있는 수많은 NP-HARD 문제를 해결할 수 있다. 문제는 Airflow는 파이썬 환경이며, Docker Container 형태로 Worker Node에 설치되어 있는 상황이다. C++ 파일을 Docker Mount하더래도, 컴퓨팅 환경에 맞춰 빌드해야하는 C++가 도커 워커 내부에서 돌아갈리 만무하다. 사실 이 문제는 C++코드를 Docker Image로 말았으면 해결될 문제였지만, 그때는 그 생각을 하지 못하여 SSH Hook이라는 최악의 방법을 꺼내들고 말았다. SSH HookSSH을 통해서 원격접속을 한뒤, 빌드되어있는 C++ 파일을 실행하면, 이..
야근의 끝,,,길고 길었던 회사에서의 야근이 끝났다. 새로운 직원들도 들어왔고, 레거시 코드와 일 자체도 안정화 되고있다.이제 잠깐 한숨을 돌릴 시간이 생겼다. 쉬면서 생각해보니 많은 문제가 Airflow에서 나왔었다.스케줄링 마비, BFS 도어 해킹 (언제부턴가 이상한놈이 채굴을 하고있었다......), C++ 바이너리파일 실행하기, 컨테이너 내부 시스템 라이브러리의 충돌(이건 찾아낸게 기적이다) 등등,,,,,,,,,,, 과거를 회고할겸 나를 가장 골치아프게 했던 Airflow을 구축했던 경험을 적어보고자 한다. Airflow 도입 이유당시 나는 처음 정규직으로 입사한 주니어중에 주니어 개발자였지만 겁도 없이 Airflow 도입을 결정하였다. Airflow을 들어보지도 못했고, 회사에는 시니어도 동..
앱을 사용할 때 로그인 혹은 OAUTH 기반 로그인(구글, 네이버 등등)으로 로그인을 하게 됩니다. 이때 어떤 앱은 한번 로그인하면 계속 로그인이 유지되고, 어떤경우는 오랫동안 로그인을 하지 않다가 들어가면 로그인이 풀려있기도 합니다. 인증방식은 여러가지가 있습니다. 쌩으로 헤더에 유저정보를 담아서 보내기 세션과 쿠키 토큰 인증 방식 (OAUTH2 애도 사실 토큰인증) 그 인증방식중 하나(3번)가 오늘 알아볼 JWT 인증 방식입니다. (제일 많이 사용됨) 먼저 JWT는 무엇인지 알아보겠습니다. 구성요소 JWT는 "."으로 3가지 문자열로 구성되어 있습니다. {"token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXNzd29yZCI6IiIsInJvbGUiOiJST0xF..
집합의 요소들의 구성 여부를 표현할 때 유용한 테크닉 왜 비트마스크를 사용하는가? DP나 순열 등, 배열 활용만으로 해결할 수 없는 문제 작은 메모리와 빠른 수행시간으로 해결이 가능 (But, 원소의 수가 많지 않아야 함) 집합을 배열의 인덱스로 표현할 수 있음 코드가 간결해짐 비트마스크는 2진법으로 사용하는 것을 비트마스크라고 합니다. 예시) [1,2,3,4,5]라는 집합이 있을때 임의로 몇개를 골라서 뽑는 경우를 구한다고 해보자. 원래라면 각 배열의 요소를 for문을 통해 접근하면서 확인해야 할 것이다. 하지만 비트마스킹으로 구현하게 되면 int 하나로 표현이 가능하다. [1,2,3,4,5] => 11111 => 31 [1,2,3] => 00111 => 7 [1,2,5] => 10011 => 19 이..
다익스트라 알고리즘은 특정 정점에서 다른 정점으로가는 최단 경로를 구합니다. 여기서 DP가 적용이 됩니다. DP는 이미 최단경로를 구한 곳은 다시 구할 필요가 없기 때문입니다. 이를 활용해 정점에서 정점까지 간선을 따라 이동할때 최단경로를 구할 수 있습니다. 우선순위 큐를 사용하여 구현하였습니다. void dijkstra(vector matrix, int start){//인접 행렬임 vector distance(matrix.size(), INT_MAX); priority_queue pq; pq.emplace(0,start); distance[start] = 0; while(!pq.empty()){ int cost = pq.top().first; int cur = pq.top().second; pq.pop..
최소 공통 조상을 찾는 알고리즘입니다. 두 정점이 만나는 최초 부모 정점을 찾으면 됩니다. 예시)13번과 15번의 공통 조상 노드는 5번노드이다. 예시) 13번과 11번 노드의 공통조상은 1번노드이다. LCA 알고리즘을 푸는 방법은 인풋(트리의 형태)가 어떻게 주어지느냐에 따라 다르지만 기본적으로 root노드와 자식노드만 알고있다고 가정해보겠습니다. LCA을 풀기위한 가장 효율적인 방법은 Sparse Tree을 사용하는 것입니다. 이 방법은 우선 DFS을 이용하여 Depth(해당 레벨에 어떤 노드들이 존재하는지 알려주는 배열), Parent(해당 노드의 부모 노드를 알려주는 배열)을 구합니다. const int MAX = 100001; // 최대 노드 수 const int LOG = 17; // 2^17..
최장 증가 부분 수열은 배열에서 가장 긴 증가하는 수열을 찾는 알고리즘입니다. 예시) [ 7, 2, 3, 8, 4, 5 ] → 해당 배열에서는 [2,3,4,5]가 LIS로 답은 4 예시) [ 6, 2, 5, 1, 7, 4, 8, 3] -> [2,5,7,8] DP로 풀기 일반적으로 푸는 방법은 DP을 이용하여 푸는 것입니다. 이중 포문을 통하여 구현하며 시간복잡도는 O(N^2)가 나옵니다. 방법은 간단합니다. Bottom to Top형태의 DP을 사용합니다. i = 1 부터 Dp의 값을 계산해 나갑니다. i번째의 배열값은 자기보다 작은 index인 j번째 배열값들과 비교하여 더큰지를 비교합니다. 만약 더 크다면 해당번째의 Dp값을 비교합니다. Dp[i]의 의미는 i번째 인덱스에서 끝나는 가장 큰 최장 증가..
그래프 알고리즘으로, 문제를 풀 때 상당히 많이 사용합니다. 경로를 찾는 문제 시, 상황에 맞게 DFS와 BFS를 활용하게 됩니다. DFS 깊이 우선 탐색입니다. 모든 경로를 탐색해야 할 경우에 적합하며 노드에서 다른 브랜치를 찾아보기 이전에 현재 브랜치를 모두 탐색한 후에 다음 브랜치를 탐색합니다. 스택 or 재귀를 통해서 구현할 수 있습니다. 하지만 재귀 또한 Stack Trace을 통해서 작동하는 것이기 때문에 본질은 같다고 할수있습니다. 시간 복잡도는 다음과 같습니다. 인접 행렬 : O(V^2) 인접 리스트 : O(V+E) 둘의 시간복잡도는 같으나 이 또한 구조체의 특징때문에 차이가 발생하는 것이지 동작 자체는 동일합니다. 각 노드에 대해 탐색해야할 모든 브랜치를 탐색하게 되므로 인접행렬은 O(V..