Lua 5.2가 나온다고 합니다.
| 루아 5.2가 나온다고 합니다. 아래는 관련 주소입니다. http://lua-users.org/lists/lua-l/2010-01/msg00260.html 현재 정식버전은 아니고 캔디데이트 버전(work1) 비슷한 것 같습니다. 최종 기능은 마지막 버전에서 최종 결정 된다고 하는데 어떻게 바뀔까 기대가 되는군요. |
| 루아 5.2가 나온다고 합니다. 아래는 관련 주소입니다. http://lua-users.org/lists/lua-l/2010-01/msg00260.html 현재 정식버전은 아니고 캔디데이트 버전(work1) 비슷한 것 같습니다. 최종 기능은 마지막 버전에서 최종 결정 된다고 하는데 어떻게 바뀔까 기대가 되는군요. |
| 기존에 클라이언트에서 영상 포맷을 분석 한 후 메타데이터를 분리하는 과정을 서버에서 하기로 했다. 결정한지는 오래됬는데 여차 바쁘다보니... 암튼.. 이런 결정을 한 계기는 서비스 특성상 서버가 네트워크 부하가 크고 CPU 는 팽팽 노는 현상이 발생 하기 때문에 서버의 중요기능인 트래픽 스로틀 기능을 메타데이터에 적용 할 때 활성 여부를 서버에서 수행하기 위함이다. 현재 구조는 재생 시작시 대부분의 영상 파일은 메타데이터를 가지고 있다. 파일 헤더와 인덱스 등이 그에 해당한다. 예를 들면 avi의 경우에는 인덱스와 데이터가 구분 되어 있으며 dshow 필터에서 초기 로딩시 인덱스에 접근하여 이를 로딩하는 과정을 거친다. 그런데 스토틀 기능이 최대 비트레이트 이상은 보내주지 않기 때문에 메타데이터가 커지면 초기 동영상 로딩이 느려진다는 단점이 있다. 이를 극복하기 위하여 클라이언트에서 메타데이터를 로딩 할 때 서버에서 이 사실을 알려주도록 구성이 되어있으나 클라이언트 판단을 서버가 전적으로 믿는 방식이므로 문제가 있다. 따라서 서버에서 동영상 정보를 스캔 할 때 메타데이터 정보 위치를 계산하여 저장 후 클라이언트가 데이터 요청시 메타데이터 영역을 요청한다면 스로틀을 끈 상태에서 최대 속도로 보내주도록 설계를 바꾸게 되었다. 기능의 특성상 서버 플러그인 방식으로 구현을 하는게 나을것 같긴 한데.. 기능 규모, 유지보수성등을 고려해서 좀 더 생각을 해보고.. |
![]() 요놈의 UI 때문에 서버 만드는것 보다 최소 두배는 시간이 더 걸리는듯 ㄱ- 그냥 네트워크 모듈을 다시 만들고 패킷 구조체 변환 노가다를 하는 일이 있더라도 C#으로 할 껄 그랬나... |
| 요즘과 같은 다중코어 시대의 컴퓨터의 CPU 활용도를 쭉쭉 끌어올리기 위해서는 동시성을 잘 활용해야한다. 그런데 다들 아시다시피 스레드를 이용하여 공유 메모리를 접근 하기 위해서는 해당 메모리를 다른 스레드에서 접근하지 못하도록 동기화 객체로 묶어야한다. 이런 동기화 행위 자체가 성능은 그렇다치더라도 생산성을 너무나도 크게 해친다. 싱글 스레드 프로그램과 같이 그냥 대충 짜다간 데드락 걸리기 십상이다. 구조 설계하는데도 애로사항이 꽃핀다. 위에서 말한 데드락을 회피하기 위한 단방향 접근 방식 설계가 필수이고 생산성을 올리기 위해 동기화 객체 사용을 자동화 할려고 해도 쉬운게 아니다. 전날 술이라도 먹고 아침에 해롱한 상태로 코딩이라도 했다간 지옥을 맛보게 될터이니 말이다. 프로그래머 정신력을 제물로 성능을 이끌어내는 것이라 할 수 있으며 이로써 성능이 올라가는거야 좋긴 하지만 효율이 너무 떨어진다. 코드 한줄 짜더라도 신경쓸게 너무 많고 싱글 스레드에 비해서 문제점이 바로 드러나지도 않고 나중에 들어나더라도 단박에 찾기도 힘들다. 오히려 이러한 사항들 때문에 멀티 스레드 프로그래밍을 하는 진입장벽이 높아지긴 하지만... 밥그릇 챙기기에 대한 대가로 치자면 귀찮은걸 싫어하고 반복적인걸 싫어하고 숟가락만 얹으면 되는걸 좋아하는 게으른 프로그래머로써는 여간 신경 쓰이는게 아닐수 없다. 그래서 나온게 intel TBB나 OpenMP와 같은게 있긴 하다. 서버 프로그래밍을 하면서 이런 해악에 좀더 숟가락만 얹고 싶어하는 욕망이 샘솓기 때문에 어느새 정신차리고 보면 저런 라이브러리와 비슷한 행동을 하는 패턴으로 설계를 하는 본인을 본다. 그러다보니 이미 잘 차려진 밥상을 그냥 지나치기는 좀 아깝다. STL도 멀티스레드에 최적화된 자료구조가 아니다보니 접근시 동기화 기준을 전체 컨테이너 기준으로 동기화가 진행되어야 하다보니 성능도 좀 안습니다. 대부분 멀티 스레드 프로그래밍에서 연산은 읽기가 주되다보니 어쩌다 가끔 쓰기하는 경우와 동기화 하기 위해서 매번 락을 걸어야하는 부분도 성능을 떨어뜨리는 요인이 된다. 그래서 많은 접근이 필요한 부분은 read-write lock으로 구성을 하여 성능을 꾀하긴 하지만 이런것 또한 일일히 신경을 써줘야하고 컨테이너의 일부 원소만 접근 할 때도 전체를 동기화 해야하는 사실은 변함이 없기 때문에 근본적인 해결은 되지 못한다. 그런면에서 intel TBB와 OpenMP를 보자면 OpenMP는 멀티스레드에 최적화된 자료구조를 제공하진 않는다. 단지 컴파일러 레벨에서 코드에 명시된 블럭을 멀티 스레드로 빼주는 역할을 하고 해당 코드 블럭을 수행하는 스레드간에 동기화를 보장해주는 정도 밖에 안된다.(이부분은 OpenMP를 본지가 오래되서 요즘은 어떤지 모르겠지만 아직까지 Visual studio에서 지원하는 OpenMP 버전이 그대로인걸 보면 별반 다를건 없다고 생각한다.) 그와 반대로 intel TBB는 자체 자료구조를 제공한다. OpenMP와 같은 코드 단위 병렬화를 하지는 않고 라이브러리이기 때문에 템플릿을 이용하여 코드블럭의 병렬화를 지원하긴하지만 OpenMP에 비하자면 좀 쓰기가 거시기 하다. 간편하게 병렬화가 안되고(OpenMP의 컴파일러 지시자를 이용하는 방법보다) 클래스를 만들고 이를 이용하여 템플릿으로 작성을 해야하기 때문에 솔직히 OpenMP에 비해서 코드 흐름 면에서는 영.. 꽝이다. 하지만 c++ x0가 나오고 익명 함수나 클로저를 그대로 쓸 수 있다면 또 다른 이야기가 될 수 도 있다. 그렇기 때문에 코드 블럭은 OpenMP를 이용하여 병렬화 시키고 자료구조는 intel TBB를 이용하여 동기화 시킨다면 뭔가 궁합이 잘 맞아 떨어지지 않을까 생각도 해보긴 한다. 소프트웨어 트랜젝션 메모리(STM)라는 것이 존재하긴 하지만 아직까지 만능이 될수는 없고 싱글 스레드 프로그래밍과 같이 대충 짜도 될 정도의 라이브러리가 존재하는건 아직 못봤다. 그런다고 직접 구현하기에는 배보다 배꼽이 크다. 하드웨어 트렌젝션 메모리가 구현이 된다면 운영체제 레벨에서 지원을 해주는 그날이 올 때 이런 문제점과 안녕을 고할수 있을지 모르겠지만... 아직까지는 넘사벽이고.. 현존하는 라이브러리를 이용한다면 intel TBB + OpenMP 조합이 괜찮지 않을까 싶다.(어디까지 추측이며 시도 해보진 않았다) 그렇지만 이 둘도 만능은 아니기에 일반적인 해법이 될 수는 없다. 결론은.. 아.. 멀티 스레드 프로그램하기 짱나 |
| 대략 상황설명을 하자면.. 파일 서버가 있고 실 서버가 따로 있다. 실 서버에서는 프로그램만 돌아가고 파일 서버는 데이터 저장용으로 쓰고 있다. 그래서 네트워크 드라이브로 파일서버의 경로를 드라이브에 마운트 시키고.. 심볼릭 링크로 실 서버의 특정 디렉토리에 네트워크 드라이브의 특정 디렉토리를 링크 시켰다. 그래놓고 쓰고 있는데 어느날.............. 로그를 보다 보니 특정 파일의 접근이 실패하는 것이었다. MediaInfo 라이브러리로 동영상의 정보를 스캔하는 짓을 하는데 실패했다는 로그가 특정 파일에서 나타났던 것이다. 처음에는 동영상이 깨진 것으로 생각해서 MediaInfo 유틸리티 버전을 받아서 열어봤지만 아주 잘 나왔다. 그래서 서버 프로그램에 문제가 있나 싶어서 해당 동영상을 받아서 로컬에서 테스트 해봤는데 스캔 아주 잘 되신다....... 이건 멍미.. 그래서 이번에는 로컬에 서버에서 실패했던 파일의 경로를 그대로 만들고 그 경로에 해당 파일을 넣어서 테스트 해볼려고 디렉토리를 만들고 파일을 복사 해넣을려고 하니.. 경로가 너무 길덴다.. 대략 msdn을 찾아보니 MAX_PATH가 260이래서 실패했던 파일의 경로(파일이름포함)를 보니 약 270자가 조금 넘었다. 그래서 구글에게 물어보니 해결 했다는 사람은 한명도 안보였다. 다시 msdn을 찾아보니 유니코드 버전의 API는 최대 32k까지 된다고 해서 CreateFileW를 호출해서 해보니 되긴 된다. 단 조건이 있는데.. 경로 앞에 "\\?\"를 붙여야한다... 즉 \\?\F:\users\chadr\desktop\~~~ 이런식이어야 한다. 내참... 지금이 어느 윈도98 쓰는 시절도 아니고 파일시스템은 기본이 NTFS가 대부분인 이 시대에 경로의 최대 길이는 파일시스템에 맡기지는 왜 아스키 버전에서는 아예 안되고 유니코드 버전에서는 저런 해괴망측한 것을 앞에 붙여야지만 되는지.. API에서 막을게 아니라 에러처리는 파일시스템에게 맡기는게 훨씬 유연할 텐데 말이지.. |
| 뭐 많이 써본건 아니지만 설치하고 이것저것 빈 프로젝트 만들어서 본 결과.. 아직도 느리긴 느리다. 물론 2008보다는 아주조금눈꼽만치 빨라지긴 한거 같은데 새로운 문서 열거나 닫을때 느껴지는 그 답답함은 어쩔수 없다. 무려 쿼드코어 2.87인데도 말이다. 정말 반응속도는 6.0이 최고였는데.. 그래도 2003까진 괜찮았다. 젭알 2010에서는 속도좀 최적화 했으면 하는 바람이다. 그래도 몇가지 편리한 기능은 좋긴하다. 그래도 속도좀.... 아무리 편리해도 뜨는데 1초 이상 걸리면 그것도 자주 쓰는 기능이면 답답함이 그지없다. ps. 기본 글꼴은 LCD에서 보기에는 안티앨리어싱이 너무 먹어서 눈이 아프다. |
| 이번학기는 무슨 프로젝트가 이렇게 많은지.. 12시 이전에 자본지가 언제인지 기억도 안난다.. 미칠듯이 죽어나가던 서버는 겨우 동기화 문제를 해결 했고.. 네트워크 프로그래밍 실습 과목에서 배운건 없지만 딱 하나 있다면 IOCP 구조를 좀 파악 했다는거.. 별거 아닌거 같은데 비동기.. 그것도 커널로 넘어갔다가 오는 정보를 처리 하다보니 IOCP를 제대로 정확히 이해하고 있지 않으면 나같이 몇일 고생을 하게 된다. 여튼.... 서버 죽는건 해결 했고.. 나머지 구현 하면 땡.. 아.. 잠 좀 자자.. |
| 대략 구조가 accept를 하는 스레드와 worker스레드로 서버가 구성되어있다. accept를 하는 스레드는 큰 입출력이 필요 없으므로 간결한 구조로 가기 위해 non-blocking 모드로 소켓을 생성하고 무한 루프를 돌렸다. 그리고 서버 가용성 테스트를 위해서 0.05초에 약 170바이트 정도의 패킷을 전송하는 더미 클라이언트를 64개 정도 붙였다. 그리고 나서 accept 스레드를 종료하여 서버를 종료 시키기 위해 루프가 멎을수 있도록 조건값을 변경 시켰다. 그런데도 감감 무소식...... 디버거로 accept 스레드의 루프에 브레이크 포인트를 걸었으나 안걸림... 이게 뭔일이디야.. 그래서 혹시나 해서 EventSelect로 바꿔보았다.. 잘 된다... 이걸 어찌 설명해야할지.. IOCP하고 non-blocking 소켓은 쓰지 말아야 하는건가? 클라이언트를 한두개 붙였을 때는 non-blocking으로 해도 잘 걸렸는데 worker스레드가 좀 바쁘게 돌아가면 감감 무소식이다. 스레드 우선순위에서 밀리는 것인가.. 모르겠군.. |
| 기존에 폰트를 렌더링 할 시 baseline을 계산하기 위해 ascender를 계산 한 후 face->glyph->bitmap_top을 이용하여 baseline과 합하여 폰트가 그려질 0,0을 찾았다. 그런데 이것이 일정 크기가 넘어가면 baseline이 안맞는 현상이 발생했다. 조사해보니 bitmap_top이 문제였다. 이 값이 계속 0이 나와서 매뉴얼을 다시 뒤져보니.. 이 값은 FT_GLYPH_FORMAT_BITMAP일 때만 유효하다더라.. 즉.. 일정 크기가 넘어가면 트루타입 폰트는 스케일이 가능한 FT_GLYPH_FORMAT_OUTLINE으로 리턴을 한다. 따라서 bitmap_top을 이용해서는 안되고.. face->glyph->metrics.horiBearingY를 이용하여야 한다. 이 값은 FT_GLYPH_FORMAT_BITMAP일 때도 유효하니 무조건 이거만 써도 무방하다. 이 값을 픽셀값으로 변환할려면 64로 나누어야한다. ps. freetype 튜토리얼 개나 주세요. |
댓글을 달아 주세요