2020-11-22(Sun)

  1. 학습 날짜 // 2020-11-22(일)

  2. 학습시간 // 9:00~22:00

  3. 학습 범위 및 주제 // Webserv 에러잡기

  4. 동료 학습 방법 // sanam, yohai님과 토의

  5. 학습 목표 // webserv 에러를 잡는다.

  6. 상세 학습 내용

우선 극적인 성능개선을 이루어내었다. client로부터 읽어온 Body를 _body 멤버변수에 저장할 때 std::string의 append 메소드를 이용하니 1시간 40분 걸리던 처리가 1분 40초안에 처리되었다. 기존에는 할당연산자와 복사생성자를 통해 기존 body에 append하고 있었기 때문에 공간할당 문제로 병목이 크게 일어나고 있었던 것이다. 하긴 기존에도 malloc 하는 분기를 지워줬더니 크게 성능개선이 이뤄지길래 메모리할당 관련해서 이슈있는 부분을 주목하고 있긴했었다. 문제원인에 대해서 yohai님과 내가 나눈 추측을 바탕으로 sanam님이 찾아주셨는데 생각보다 빠르게 성능개선의 단서를 찾아서 다행이다.

이에 아쉽지만 우선 구조개선을 하지 않아도 충분히 테스터를 돌릴 정도로는 성능이 개선되었음을 확인했으므로 구조개선을 진행했던 브랜치는 우선 남겨두고, develop 브랜치에서 버그픽스 브랜치를 따서 버그를 우선 해결하기로 했다.

커밋만 안되었을뿐 토요일 심야부터 디버깅을 시작하였다. 그리고 마침내 우리 팀의 시행착오를 알게되었다.

recv함수의 세번째 인자로 receive_target_size를 전달하게끔 구현해두었다. 이 때 우리는 client가 우리에게 보내는 데이터가 receive_target_size보다 크다면 recv함수를 실행시킨 결과로 적어도 receive_target_size만큼 데이터가 읽히는 것이 보장된다고 생각해왔다. 그러나, receive_target_size가 32770임에도 불구하고 읽어온 bytes가 32769만큼 읽히는 경우가 생기지 않는가! 이건 그래도 충분히 그럴 수 있다는 생각이 든다, client가 보내는 data가 천천히 순차적으로 server에 도착할 수도 있으니.

더 어이없는건 10000000 size body를 보내와야할 tester가 header와 body를 함께 보내는 경우가 많지만 처음에 header만 보내고 body를 순차적으로 보내는 경우도 왕왕있다는 것이다. 지금까지 우리 서버는 recv를 버퍼사이즈만큼 한다음 읽어온 버퍼에 \r\n으로 끝나는 헤더만 있을 경우 클라이언트가 더 보내올 body가 없다고 판단하고 있었다. 만약 body가 있다면 버퍼사이즈만큼 읽었을 때 무조건 헤더와 바디의 일부분이 함께 포함되어있을 것이라고 생각한 것이다. 매우 순진했고, 디버거로 찍어보지 않았다면 알기 힘들었을 것이다.

이는 select를 거쳐서 여러번 recv MSG_PEEK하여 client가 '느리게' 데이터를 보내는 경우에 대응하도록 만들었다.

그리고 마침내.. 테스터를 다 돌리는데 성공하였다! ㅠㅠ

  1. 학습 내용에 대한 개인적인 총평

토요일에 눈을 뜨니 오후 12시가 훌쩍 넘어있었습니다. 그리 늦게 잠들지도 않았는데 이렇게 늦잠잤다는건 확실히 요즘 피로가 많이 쌓여있었기 때문으로 보입니다. 푹 자고 나니 머리가 다시 돌아가기 시작하여 내친김에 푹~ 쉬면서 웹서버를 생각했습니다.. 그리고 심야부터는 버그를 예상하고 끈기있게 디버그하여 찾을 수 있었습니다. 확률적으로 발생하는 재현이 어려운 버그는 진짜 끈기가 필요하네요. 더 스마트한 방법이 있었을지 모르겠지만ㅎㅎ 토,일요일을 갈아넣었더니 테스터를 통과하기는 했네요! 팀원들이 자랑스럽습니다.

다음 학습 계획

  • Webserv 오류잡기

Last updated