2011년 3월 29일 화요일

overlapped IO

http://linkmemo.tistory.com/entry/Overlapped-IO-Note-1

overlapped io에 대한 설명이 잘 되어 있어서 링크한다.
이러한 특성 때문에, IOCP와 overlapped io를 이용한 Win32서버가 더 빠른 것이다.
하지만, 잘 다뤄야 한다. ^^
부디, 잘 다룰 자신 없다만, 쓰지 않길 바란다.;; 일반적인 경우, 쓰지 않아도 성능 차이를 못 느끼는 경우가 많다.

IOCP library로 좋은 오픈소스를 찾았다. 다음을 참조. ^^
http://www.45mercystreet.com/computing/libiocp/index.html

도움이 되셨다면, 광고 클릭을 ㅎㅎ ^^

listening thread in tinyNetworkLib

accept operation은 cost가 큰 operation이다.
그래서 accept만 따로 하는 listening thread를 만들곤 한다.
(Win32에서는 AcceptEx를 사용하여 더욱 더 성능 향상을 한다.)

더우기 accept에 이어서, 새로운 유저에 대한 메모리 생성 및 DB query(login관련)가 이루어지므로, 그 이후에는 더 비싼 operation들이 기다린다.
그래서,  다른 싼 operation과 합쳐서 thread pooling을 하면, 대기하는 operation들이 많아질 수 있게 된다.
그래서, listening thread를 만든다.
그러나, 그 차이가 크지 않다면, 안 만들어도 될 것 같다. 쓰레드 생성은 신중히 선택해야 할 문제이다.

"빨리 받아주고, 빨리 처리 하자"는 맞다.
하지만, "빨리 받지만, 빨리 처리 못하면?" 서비스는 악순환 일로로 가게 된다.
DDoS공격에 매우 취약한 서비스가 될 것이다.
따라서, 빨리 처리할 수 없으면 빨리 받지 않도록 설계에 고려가 되어야 한다.
처리 속도와 accept속도(?)를 측정하여 dynamic하게 조절되어야 할 것이다.
사실 그렇게까지 하는 경우는 별로 없다.

이왕 listening thread를 만들었다고 하면, 다음과 같이 하면 좋겠다.
accpeted user와 관련된 메모리들의 생성과 소멸을 모두 listening thread 한개에서 처리한다면? 다른 thread들에서는 소멸전까지 안전하게 쓸 수 있게 보장만 된다면? lock을 쓰지 않아도 thread safe하게 될 수 있다. ( 쓰더라도, 제한적일 것이고, contention이 적게 일어날 것이다. )또한, 특정 부분에서 multi thread를 위한 memory manager를 따로 만들지 않아도 될 것이다.
생성은 그렇다치고, 소멸까지 처리하려면, destroy stack(소멸처리용 데이터구조)과 같은 것을 통해서 listening thread에서 처리하는 것이 맞을 것 같다. 소멸을 위해서 destroy stack으로 post하고, listening thread에서 delete를 하게 되면, thread safe가 보장된다.

God bless me and you. ^^

도움이 되셨다면, 광고 클릭을 ㅎㅎ ^^

2011년 3월 28일 월요일

using skip list, mulithreaded heap , event polling in tinyNetworkLib

tinyNetworkLib를 코딩중입니다.

몇가지 중요한 결정을 하였습니다.

skip list를 사용하여, dispatched packet에 대한 circular buffer의 index를 보관하고, socket으로부터 recv시 overwrite하지 않도록 보호하는데 쓰기로 했습니다.
(좀 어려운 말인데요;;)
recv시, circular buffer에서 안전한 영역, 즉, 아직 처리 되지 않은 packet이 있지 않은 영역을 확보하기 위해서, circular buffer의 next buffer pointer보다 크고, dispatched packet index중에서 가장 작은 수를 알아내기 위해서 skip list를 사용합니다. logN time이죠.

이의 용도에 맞게 최적화 된 Skip List 를 구현할 수도 있지만,
잘 구현된 것을 일단 사용하기로 했습니다. ( http://bit.ly/gGtzuO )

또한, multi thread 환경에서는, 여러개의 thread가 heap을 경쟁합니다. 하나의 thread에서 alloc한 것을 다른 thread에서 free해야 하는 상황이 자주 생깁니다. 그럴 경우, 어쩔 수 없이 lock을 써야 하는데, thread가 많아질 수록 scalability 가 떨어지는 문제가 생깁니다.
이 문제를 해결하기 위해서, 역시 직접 구현하는 것이 맞겠지만...;; Intel TBB의 scalable allocator를 사용하기로 결정하였습니다.

또한, epoll이나 kqueue의 경우, IOCP의 그 역할(? ^^)이 없습니다만,
network thread에서 poll을 해오고, 처리는 event마다 thread pool로 던지는 역할을 위해서, 역시 intel TBB의 task를 쓰기로 했습니다. ^^

God bless me and you. ^^

도움이 되셨다면, 광고 클릭을 ㅎㅎ ^^

2011년 3월 23일 수요일

tinyNetworkLib

0. basic system API, templates
1. socket 과 관련된 cross-platform wrapper API ( listen, accept, send, recv, set_opt 등 )
2. thread,mutex,semaphore 와 관련된 것들( 또는 Intel TBB 사용)
3. socket event handler ( poll,epoll,kqueue,IOCP )
4. circular buffer for zero-copy
5. packet slicer
6. some example packet designs and parsers
7. some network threads
8. packet dispatcher
9. packet serializer/handler
10. packet serialize using google protobuf
11. some example encryper/decryptor
12. some memory managers
13. some send threads
14. some DB threads
15. some log threads
16. some system admin threads
17. some logic worker threads
18. user manager
19. service(daemon) controller/configurator
20. some actor-based logic worker threads
21. ipc using thrift
22. some interfaces to Erlang or Haskell module and script languages(lua,python,ruby)
23. client examples ( c, c++ , lua, objective-c(iphone,MacOSX) , java, java(android), python )
24. benchmark tests

이것들을 포함하는 최소화되어 간단한 network library를 만들고, 이름을 tinyNetworkLib로 짓기로 했다.
목표는 가장 일반화된 서버 머쉰 사양에서 가장 최적화되어 잘 돌아가는 것이다.
업무 외 시간에 함께 하실 분은 연락주세요. ^^
온라인 서비스 개발에 사용하실 분도 연락주세요. ^^

2011년 3월 21일 월요일

zero-copy between network recv threads, dispatcher threads, logic threads

IOCP의 경우에는 여러개의 thread가 경쟁적으로 queue에서 io을 순서대로 가져와서 처리하는 것이 lock없이 처리 가능하다.(kernel level에서 serialized된 대로 user level로 post 되기 때문이다.)
하지만, epoll,kqueue의 경우에는 그러한 역할이 내부적으로 존재하지 않는다.
io event 발생을 polling하고, event들을 iteration하는 loop에서 처리한다.
좀 더 성능 향상을 위해서 iteration을 쪼개서 pararell하게 가능하긴 할 것이다.

어쨌든, 위의 일들은 몇개의 network io thread에서 일어나는 일들이다.
network io thread context에서, recv(socket,buffer,MAX_SIZE)를 통해 buffer에 copy된 것을 packet으로 쪼개고, dispatcher를 통해서 해당 logic thread에 전달하고, 처리되는 과정에서, 그 buffer를 한 번도 copy하지 않으려면 어떻게 해야 하는가?
이 문제가 zero-copy문제이다.

dispatch된 packet이 parse되어, logic function의 input parameter로 변환된 후에는 비로소, 생명을 다해도 된다.
그때까지는 recv를 통해 얻어진 packet에 overwrite되지 않고 보호 되어야 한다. 이 메커니즘을 어떻게 구현할까?
다시 말하면, packet이 circular buffer에서 잘라지고(slice), 전달되고(dispatch), 처리되는(handle) 동안에 어떻게 보호할 수 있을까? 그 동안 circular buffer에는 socket으로부터 새롭게 받아진 stream이 쯔나미처럼 무서운 속도로 다가올 것이다.

slice,dispatch 전까지는 일단 circular buffer를 통해서 zero-copy 구현이 가능하다.

보호하려면, socket에서 buffer로 copy하기 전에 copy해도 되는지 여부를 확인이 가능해야 한다. copy해도 되는지 여부는, slice->dispatch->handle의 과정을 거치고 있는 packet의 memory를 overwrite하는지 여부를 알아내야 하는 것이다.
dispatch까지는, 순서대로 처리가 될 것이기 때문에, 마지막 packet의 index를 검사함으로써 간단히 해결된다.
문제는, dispatch된 후에는 여러개의 thread들이 경쟁적으로 처리할 것이고, 어떤 것이 먼저 처리 될지 알 수 없기 때문에, 마지막이라는 것을 알 수가 없다.

이에 맞는 데이터 구조를 만들어야 한다.
dispatch된 packet의 index를 sorted list로 갖고 있고, dispatch될 때, insert 해주고,
handled되고 나면, list에서 index를 remove한다. 그리고, recv 시 overwrite check여부는 recv index보다 큰 최소값을 체크하면 되므로 가능하다.

이 오퍼레이션들은 network thread,dispatch thread,logic thread가 건들기 때문에, atomic하도록 구현해야 한다.
 lock없이 구현하는 방법은 dispatch에서 logic thread로 전달시 zero-copy를 포기하고 packet을 copy하는 방법일 것이다. 두가지 경우에 대해서 성능 테스트를 해보지 않고서는 섣불리 판단하기 힘들 것 같다.

도움이 되셨다면, 광고 클릭을 ㅎㅎ ^^

2011년 3월 18일 금요일

permit overflow in receiving buffer of socket stream

보통 socket connection당 공평하게 동등한
recv buffer size(socet에서 memory로 읽어들이는 버퍼)를 유지한다.
socket buffer size도 마찬가지이다.

socket buffer는 full이 나거나 ready가 안될때 would block이 발생하는데,
would block이 발생하는 경우는 send측에서 알아서 처리하게 된다.
(기다렸다가 재시도 한다.)
그러므로, socket buffer에 대해서는 size와 option(nagle 과 같은) 대해서만 신경쓰면 될 것 같다.

recv의 경우는 socket buffer에 읽을꺼리가 있는데, 프로그래머가 정한 recv buffer가 full이 될 경우에 어떻게 처리할까?
buffer를 늘려서 읽어 놓거나, 읽는 것을 나중에 하는 일이다.
선택에 달린 문제일 것이다.

1) buffer를 늘리고 읽는 정책으로 한다면,
특정 connection에만 읽게 해주게 되서, 사소한 특혜같은 것이 생긴다.
logic에서 제때 처리를 못해주면, 다시 또 buffer overflow가 생길 수 있다.
메모리를 재할당해야하는 부담감도 생길 수 있다.
잦은 재할당은 메모리 fragmentation으로 이어져 성능에 결국 악영향을 줄 것이다.
재할당을 해야 하면 사용하던 pointer도 invalidate되어서, zero copy가 힘들어진다.
또한, 멀티쓰레드 환경에서는 lock을 해야 할 것들이 한두개라도 더 많아진다.
다만, IO에서는 delay가 생기지 않는다.

2) buffer size를 절대적으로 고정한다면,
recv event에도 무시하고, recv buffer가 비워지고 읽을 수 있을때까지 기다려야 한다.

메모리 재할당은 없다.  따라서, zero copy가 가능해진다.
읽지 않더라도 socket buffer 에 쌓이게 되므로, 잃어버릴 염려는 없다.
다만, recv buffer가 비워질때까지의 시간만큼 io에서 delay가 생기는 것이다.
최소한 recv event round(event round time)까지 기다려야 하고, 그때도 비워지지 않는다면, 다시 기다려야 할 것이다.
그러나, 리얼타임서버의 임무는 요청을 일정시간 내에 응답해야하고, 더우기 모든 유저들에게 동등하게 처리해줄 의무가 있는 서버라면, logic round time도 존재한다.
logic round time이란, 요청된 request를 모두 소화하는 시간으로 정의할 수 있을 것이다.

클라이언트 입장에서 허용되는 maximum latency(client permit latency?)를 50ms라고 한다면,
network latency(C->S + S->C) + logic round time + event round time < 50ms 이어야 할 것이다.

* 나는 buffer size 를 고정하기로 했다. ( file transfer용 서버가 아니라면 말이다. )

도움이 되셨다면, 광고 클릭을 ㅎㅎ ^^

2011년 3월 17일 목요일

count of send threads in MMOG

MMOG에서는 하나의 플레이어가 한 행동을 그 플레이어를 관심 영역에 둔 플레이들에게
보여줘야한다.

즉, 1:N으로 비례해서 늘어난다.
recv되는 양에 비해서 N배로 send해야 된다는 뜻이다.
단순히 생각하면 recv thread갯수가 r개라면,
send thread갯수는 N*r개로 늘어나야 원활히 돌아가게 될 것이다.

적절한 N은 몇일까?
그것을 변화시킬 factor들은 무엇들일까?

만약, recv량이 send를 digestion(소화)하기 전에 쌓인다면,
send해야 할 량은 계속 쌓이게 될 것이고, 적체되어 latency는 점점 늘어나게 될 것이다.
적체되지 않고 적절한 latency를 유지하는 것. 그것이 디자인 목표가 되어야 한다.

그에 맞게 갯수를 조절해주면 된다.

한 플레이어의 평균 관심(Area of Interest) 플레이어수는 몇일까?
수백 수천명이 함께 전투하는 공성전과 같은 상황에서는 그 평균은 엄청나게 많아진다.
그렇다고 무작정 thread 갯수를 늘리면, context switch가 많아져서 오히려 resource contention시간과 context switch time 자체의 허비만 하게 될 것이다.


또한 다른 쓰레드의 수를 생각하지 않을 수 없다.
멀티쓰레드를 통해서 어플리케이션이 빨라지는 이유는 IO가 blocking되는
시간 동안 CPU를 놀리지 않고 쓰기 때문이다.
IO blocking이 일어날 수 있는 thread는 모두 multi threading의 대상이 될 수 있다.
그렇다고 CPU가 무한하지 않다.
쓰레드만 늘린다고 모두 원활하게 돌아가지 않는다는 뜻이다.

전체적으로 봤을때,
recv thread가 r개, send thread s개, logic thread가 l개, 기타 async call을 하는 thread가 t개 라면,
(r+s*s'+l+t)*CPU 갯수 정도가 아닐까? ( s'는 평균 group broad casting 량)

이 갯수는 실전에서 테스트 해보지 않으면 알 수 없고,
어플리케이션에 따라서 매우 다를 수 있다.
단순한 채팅 서버에서는 특히 다를 것이기 때문이다.

도움이 되셨다면, 광고 클릭을 ㅎㅎ ^^

Return Error Code or Throw Exception

예외처리는 빠짐없이 하는 것이 안정적인 프로그래밍을 위해서 가장!! 중요하다.
그 다음에는  예외처리의 강도를 잘 구분하는 것 또한 중요하다.

보통의 함수처리에서의 에러처리는 return code로 하던가, exception을 throw하게 된다.
return code로 error처리를 할 경우에는
caller에게 successful scenario대로 이뤄지지 않았음을 알려주고, error code를 리턴한다.
( error_code를 리턴하는 것은 exception catch보다 코딩이 편리하기 때문에 애용된다.)
그렇지 않고 return value가 필요한 경우가 많기 때문에,
error code를 받아야 할 경우에는, Exception으로 처리하기도 한다.
이에 대한 일관성이 필요하다.

또는, exception은 caller에게 '너 미쳤니?' 또는 '나 미쳤어!'라는 메시지를 알려주기 위해서 쓰인다. ( 미쳤다는 뜻은, assumption(가정)에 어긋나는 것에 대해서 메시지를 전달하는 비유적 표현이다. )
즉, caller는 callee와는 약속에 의해서 진행되는데,
약속에 없는 값을 주게되면, '너 미쳤니?'라고 말할 수 있다.
또는 caller의 책임이 없지만, callee가 해당 약속을 못 지키게 되면 '나 미쳤어!'라고 전달하는 것이다.

도움이 되셨다면, 광고 클릭을 ㅎㅎ ^^

2011년 3월 16일 수요일

a pitfall using Mutex

multi-threaded application에서 mutex(lock)을 많이 쓴다.

프로그래머들이 흔히 저지르는 실수가 있다.
바로, lock이 풀리는 순서는 정해져있지 않다는 것이다.

예를 들면, A,B,C의 Thread에서 순서대로(시간 순) 공유 리소스에 lock을 걸었고, 모두 wait상태였다고 치자.
lock이 풀리는 순간, A,B,C의 순서로 권한을 주는 것이 아니다. 예측할 수 없는 순서대로 기회가 주어진다. 즉, Thread Scheduling 알고리즘에 따라서 바뀐다.

도움이 되셨다면, 광고 클릭을 ㅎㅎ ^^

2011년 3월 14일 월요일

Memory Allocator for Multithreaded Applications

tcMalloc : google에서 만듬. 작은 사이즈의 allocation에 최적화 된 것으로 보임.linux에서만 테스트.
Intel TBB scalable_allocator : Intel TBB에 포함. new/malloc도 대체함.
 scalable_allocator를 통해서 thread specific heap을 제공함.
libHoard : Emery Berge 박사가 만듬. 꽤 오래된 라이브러리. thread증가에 따라서 선형적으로 speed up이 나타나는 그래프가 인상적. GPL license.
nedMalloc : 오픈소스. 간단함. 다른 것들보다 다 빠르다고 주장함. Windows에 최적화.dlmalloc이 근간.bitwise tries 인상적.
MTS : memory tuning system ( evaluation을 신청해야 구할 수 있음. ) whitepaper내용이 부실한 것으로 봐서 신뢰가 잘 안 감.
jemalloc : linux,macosx에 최적화.firefox에서 쓰임.



어떤 것을 선택하느냐는, 어플리케이션에 따라 달라져야 한다고 본다.
그런데, 기본적으로 선택해야 할 기준은 있다. 바로 안정성이다.
* 안정성 : 속도가 빠르다고 해서 안정성을 해쳐서는 안된다. 더구나 근간이 되는 메모리 할당에 관해서는 절대적으로 필요한 요소이다.

시간이 되면, 테스트 프로그램을 만들어, 결과를 올려봐야겠다.
현재로서는 nedMalloc과 Intel TBB을 함께 쓰면 어떨까한다.

도움이 되셨다면, 광고 클릭을 ㅎㅎ ^^

2011년 3월 13일 일요일

circular queue buffer

나는 client socket으로부터 recv를 한 후에, packet parsing을 위해 저장을 해 둘 buffer로 circular queue 형식의 buffer를 사용한다.
그것은 고정 사이즈이다.
그 이유는 다음과 같다.

예를 들어, user(connection)당 100KB의 buffer를 정해 놓았다면, 최대 6만명(60k)이 동시에 접속한다면, 6000MB=6GB의 메모리를 사용하게 된다.
그런데, user당 할당되는 100KB의 사이즈는 서비스의 성격에 따라 달라져야 한다.
왜냐하면, 100KB의 의미는, pending packet들의 크기의 합의 최대치이다.
파일 전송과 같은 전송을 위해서는, 100KB는 모자랄 것이다. 요즘 인터넷 속도는 평균적으로 10~100Mbps(bits per sec)정도로 봐야 하기 때문이다.
속도가 1~10MBPS(bytes per sec)에서 100KB의 버퍼로 원활히 서비스 하려면,
100KB의 버퍼의 처리 속도로는 초당 100~1000번 버퍼를 비울 수 있어야 한다.

즉, 버퍼를 비우는 속도가 인터넷으로 들어오는 upload 속도보다 느리다면, buffer는 full이 날 것이다. 이런 경우는 서비스를 유지할 수 없다.

매우 빠른 액션 게임과 같은 경우에는 버퍼를 빠르게 비울 수 있어야 할 것이다.
그보다 느린 MMORPG의 경우는 그 보단 버퍼의 크기가 크지만, 버퍼를 비우는 속도는 그 보단 느려도 될 것이다.
이러한 인터넷속도,버퍼크기,버퍼 비우는 속도(througput)를 고려하여 버퍼의 크기를 정하여야 하고, 적당한 circular buffer size를 정하여야 할 것이다.
또한, socket내의 buffer size option과 nagle option등도 정하여야 할 것이다.

만약 계산적으로 적절한 socket buffer size,option, 그리고 buffer size까지 정하였다면, 비정상적인 최대치도 계산이 될 것이다. 그에 맞게 circular queue buffer size를 정하고, 비정상인 경우는, abrnomal state로 생각하여, 오류 처리를 해주면 된다. 즉, buffer size를 동적으로 늘리면 안된다는 뜻이다. 만약, DDoS공격이라도 온다면, 비정상 커넥션은 빨리 끊어주는 것이 필요한 것이다.

반면에, 웹서버는 close될때까지 한번의 리퀘스트만 하는 것이므로, 버퍼는 필요없고, 모두 저장해 놓으면 된다. 그리고 핸들러에게 넘겨주면 되는 간단한 작업이다.

도움이 되셨다면, 광고 클릭을 ㅎㅎ ^^

Mutex

Critical Section , Shared Resource의 동기화를 위한 것이다.
Mutex는 프로그래머들이 잘 이해하고 있는 것 같다.
하지만, 사용 방법에 대해서 좀 더 넓은 시각이 필요하다.

이젠, 바야흐로 멀티 프로세서시대이다.
2개가 아니라. 4개. 4개가 아니라 8개이상이 쓰인다.
젓가락이 두개가 아니라, 8개 이상 쓰일 경우가 많아진다는 뜻이다.
그런데, 제공되는 음식은 1개씩 먹으라고 한다면, 젓가락을 들고 있는 시간이
많아질 수 밖에 없다.

이제, 동시에 제공되는 음식 접시 수를 늘려야한다!

도움이 되셨다면, 광고 클릭을 ㅎㅎ ^^

2011년 3월 11일 금요일

on Hot Code Upgrade in Erlang



1) 재컴파일 %erl -make

2) 업그레이드 >stdlib:upgrade(XXX).

용도는 다음과 같다.

1) 잘못된 패치 수정

서비스중에 업그레이드하는 것은 물론 위험하다.
하지만, 잘못된 패치를 고치기 위해, 전체를 셧다운 시키고, 업그레이드하는 것은 정말 원하는 것이다. 하루에 매출에 24억이라면, 2시간 셧다운은 2억. 심정적인 매출 피해는 그보다 더 할 것이다. 특히, 이벤트로 프로모션중에 전체를 셧다운 시키다면, 프로그래머들은 신뢰를 잃기 쉽다. 신뢰를 잃지 않더라도, 좋은 신뢰를 주긴 어렵지 않겠는가? 책임자 입장에서 할 말이 없고, 핑계만 댈 뿐이다. 
24시간 서비스를 해야하는 커뮤니케이션 시스템을 위해서라면, 특히 필요한 기능이라고 본다.

2) 클라이언트 디펜던시가 없는 서버 업데이트를 런타임에

클라이언트 수정이 필요하다면, 클라이언트까지 업그레이드까지 필요하기 때문에, 추가적인 업그레이드 시스템이 필요할 것이다. 그 문제는 따로 다뤄야 할 것이다.


클라이언트 수정이 필요없는 업데이트라면, 새로운 서비스를 런타임에 추가할 것이다.
물론 위험한 일이다. 왜냐하면, 업그레이드간의 디펜던시가 복잡할 경우에는 기존 서비스가 작동하지 않을 것이기 때문이다.

LPMUD와 같은 시스템은 이런 식으로 업그레이드를 했었던 사례가 있다. LPMUD와 같은 시스템에서는 개발자가 모든 것을 결정했었다. 자신이 결정하고, 자신이 프로그램했다. 그러기에 가능했다.또한, 클라인트는 단순한 tty터미널이었다. LPMUD를 운영해본 사람이라면, 그 매력을 잊을 수 없으리라. 그래서, 이 시스템을 현재의 3D MMOG에도 적용하고 싶을 것이다.

하지만, 요즘과 같이 복잡한 시스템을 런타임에 수정한다는 것은 미친짓 일 것이다. 따라서, 서비스 중에 업그레이드는 하는 것은 꼼꼼히 따져보고 봐야 할 일이고, 생각해 볼 문제이다. 아직 그런 체계를 어떻게 해야 할지는 아직 모르겠다. 프로젝트를 진행해보면서 풀어야 할 문제로 보인다.

다만,최소한 개발팀내에서 개발중의 업데이트는 가능할 것 같다. 크게 메리트는 아닐지 몰라도...

도움이 되셨다면, 광고 클릭을 ㅎㅎ ^^

2011년 3월 9일 수요일

개발환경 구축과 이미지 출력

corona sdk로 SmartPhone App을 만들기로 결정했다.



아무리 앱 개발이 시시해보이지만, 차근차근 해보자.



개발환경부터 해보자.

http://www.anscamobile.com/corona/

여기서 corona SDK를 다운로드 하고 설치한다.

그리고, 프로젝트 관리툴인 CPM을 설치한다. 유료이다. 선택이긴 하지만, 본인은 쓰기로 했다.

http://coronaprojectmanager.com/



일단, 이미지 출력부터 해보자. 다음 동영상을 보면 이해가 쉽게 될 것이다. 한글 자막도 제공된다.









1) 프로젝트를 수행할 폴더(e.g. /home/users/workspace_corona/project1) 를 선택한다.

2) CPM(Corona Project Manager)에서 New Project를 선택한다.

3) 프로젝트 옵션들을 선택한다. 나중에 에디트가 가능하므로, 대충해도 된다.

4) image file을 project1폴더 밑에 images 폴더를 만들어 copy한다.

5) CPM에서 New Asset을 하여 4번의 image를 선택한다.

6) main.lua에서 다음과 같이 입력한다.(images/apple.jpg가 아니다.)

     local apple=display.newImage("apple.jpg");

   다음과 같이 출력된다. 

2011년 3월 7일 월요일

on History of Erlang

http://www.erlang.org/course/history.html

Erlang에 대해서, 확신을 못 갖은 사람들에게 다음을 소개합니다.

1982-1985
The language must be a very high level symbolic language in order to achive productivity gains.
생산성을 높이려면, 매우 높은 수준의 심볼릭 언어가 되어야 한다.
-> Lisp,Prolog,Parlog만 남음.

1985-1986
The language must contain primitives for concurrency and error recovery, and the execution model must not have back-tracking.
언어자체에서 concurrency,error recovery가 있어야 하고, back-tracking이 없는 실행모델이 필요하다.
-> Lisp,Prolog가 제외.

It must also have a granularity of concurrency such that one asyncronous telephony process is represented by one process in the language.
-> 하나의 언어로 구현된 하나의 프로세스에서 async 프로세스도 구현되는 수준의 concurrency가 필요하다.
-> Parlog도 제외.

그래서 Erlang을 만들기로 결정했다고 합니다.

도움이 되셨다면, 광고 클릭을 ㅎㅎ ^^

2011년 3월 3일 목요일

Implementing SSO using Scalaris in Erlang?



SSO(Single Sign On) Service는 다음과 같은 역할을 가진 서비스이다.
1. 인증 - 한번 로그인(인증)을 함으로써, 해당 서비스사의 다른 서비스를 위해 다시 인증을 하지 않아도 되게 한다. Kerberos 구조로 구현한다. 보안이 잘 되어야 한다.
2. 이중 접속 방지 - 어떤 서비스는 동시에 단 한 사람만이 이용할 수 있도록 해야 한다. 온라인 게임들이 주로 그렇다. 이중 접속을 체크하려면, 현재 사용 하는 사람들의 ID와 접속 상황을 실시간으로 업데이트하고 있어야 한다.
3. 1번에 붙여서, 서비스 사용에 대한 권한조회까지 할 수 있어야 한다.

이것을 구현하기 위해서, 예전에는 동시접속자 20만 정도의 수준 이하에서는 C++로 구현한 단일 서버에 사용하였다. 그런데, 결국 200만명 이상이 되자, 단일 서버로 구현하기 힘들게 되고, 인증구조와 이중 접속 방지를 위해 다시 구조를 만들어야 했다.

따라서, 새로 만드는 SSO는 scalable, distributed 특징이 가장 필요하다.

Erlang으로 구현한 Scalaris가 이 용도에 딱 적합하다.
처리 용량과 속도는 구현후에 공유하도록 해야겠다.

Scalaris is a scalable, transactional, distributed key-value store. It can be used for building scalable Web 2.0 services.



2011년 3월 1일 화요일

JVM and jMonkey

Python -> Jython
Ruby -> jRuby
Haskell -> lambdavm
Erlang -> Erjang

모두 JVM Implementation이 나와 있다.
jRuby가 그 중 가장 안정적인 것으로 알고 있다.

JVM기반인 언어들...
clojure
scala

즉,java가 싫은 사람들도 여러가지 선택이 있다.

오픈소스 자바3D엔진인 jMonkeyEngine을 사용하면, 그 중 익숙한 언어로 구현할 수 있다.
jMonkeyEngine은 Sun에서 Java3D를 포기하고 지원할 정도라고 한다.

아직 시험은 못 해봤지만, jRuby로 테스트해 본 사람은 있다.
http://localbiz404.blogspot.com/2008/08/jruby-jmonkeyengine-hello-3d-world.html

도움이 되셨다면, 광고 클릭을 ㅎㅎ ^^

Boolean Algebra and Comparison Operators

erl>true and false.

hs>True && False

erl>false or true

hs>False || True

erl>not false.

hs>not False



erl> 5 =:= 5.

hs> 5 == 5

erl> 1 =:= 0.

hs> 1 == 0

erl> 1 =/= 0.

hs> 1 /= 0



erl> 5.0 =:= 5.

hs> 5.0 == 5



erl> 1<2.

hs> 1<2

erl> 1>=1.

hs> 1>=1

erl> 1=<1.

hs> 1<=1



erl> 5=:=true.

false

hs> 5 == True





<interactive>:1:0:

    No instance for (Num Bool)

      arising from the literal `5' at <interactive>:1:0

    Possible fix: add an instance declaration for (Num Bool)

    In the first argument of `(==)', namely `5'

    In the expression: 5 == True

    In the definition of `it': it = 5 == True





erl> 0==false.

false

Invariable Variables

http://learnyousomeerlang.com/starting-out-for-real#invariable-variables





erl> One=1.

hs> let one=1



haskell에서는 대문자로 시작하면 안된다.

(In Haskell, variables cannot start in capital letters.)

erlang에서는 대문자로 시작해야 한다.

(In Erlang, variables needs to start in capital letters.)

erl>One=2.



** exception error: no match of right hand side value 2



hs>let one=2



erlang에서는 invariable variable이 되지만,

(Erlang permits only invariable variables.)

haskell에서는 let으로 하면 허용된다.

(Haskell permits variables by let.)

haskell에서는 invariable variable을 지원하지 않는다.

(Haskell doesn't support invariable variables.)



erl> Two=One+One.

hs> let two=one+one







erl> Two=Two+1.
erl>** exception error: no match of right hand side value 3
erl> two=2.

** exception error: no match of right hand side value 2



erl> 47=45+2.
47
erl> 48=45+2.
** exception error: no match of right hand side value 48






Numbers

erl> 2+5.

hs> 2+5



erl> 49*100.

hs> 49*100



erl>1892-1472.

hs> 1892-1472



erl> 5/2.

hs> 5/2



erl> 5 div 2.



erl> 2#101011.

erl> 8#6077.

erl>16#AE.