Vert.x가 Socket.io 보다 빠르네.

updated 2012.09.06

이번엔 node.js를 클러스터 모듈을 이용해서 실행해봤다. 확실히 빨라졌다. 초당 요청처리량 vert.x와 거의 비슷하다. 단지 차이가 있다면 top으로 지켜볼 때 node.js는 프로세스 ID가 가상 코어 갯수만큼 뜬다. 즉 16개가 뜨고 평균 CPU 사용량은 40% 정도다. 하지만 Vert.x는 프로세스 ID는 한개만 뜬다. 그리고 CPU 사용량은 140% 정도다.

코드를 꼭 http://nodejs.org/api/cluster.html#cluster_cluster 이런식으로 짜야만 서버 리소스를 제대로 활용할 수 있고 여러 프로세스로 나뉘어 실행해야하는 node.js 보다는 vert.x가 더 쓰기 편하고 성능도 결코 node.js에 뒤쳐지지 않는것 같다.

===============================================

빠르지 않다. 둘이 비슷하다. node test.js로 실행할 때는 CPU를 한개만 사용한다. top으로 지켜봤더니 CPU가 100%를 넘지 못한다. vertx run Test.java로 실행했을 때는 150%를 넘어서 돌고 있다. vertx는 JVM을 사용하니까 JVM이 CPU 갯수가 몇개든 다 활용해주는거고 node는 한개만 사용하는듯 한데.. node에 CPU를 전부 다 사용하도록 설정할 수 있는 옵션이 있던가.. 아님 CPU 갯수만큼 node test.js를 실행해줘야 하던가.. 모르겠네;;

대충 2배니까 대충 비슷하다 치고 대충 테스트 끝.

===============================================

뭔가 이유가 있을 것 같은데 아직 모르겠네…

테스트 코드는 2byte 문자를 보내는 아주 단순한 웹 서버. 이 웹 서버로 10명의 동접자가 보내는 요청 5만개를 얼마나 빠른 시간안에 처리하느냐를 테스트 해보기로 결정.

테스트 클라이언트는 아파치 벤치로.

ab -t 10 -c 10 -n 50000 http://테스트할서버:포트/

최대 10초 동안 10개의 동접자가 총 5만개 요청을 보냄.

서버 사양은

  • 물리 CPU 2개.
  • 물리 CPU당 코어 갯수 4개.
  • 가상 코어 총 갯수 16개.
  • CPU 속도는 2.27GHz
  • 메모리는 16G

테스트 결과.

node.js

Server Software:
Server Hostname: xxxx
Server Port: yyyy

Document Path: /
Document Length: 2 bytes

Concurrency Level: 10
Time taken for tests: 6.769 seconds
Complete requests: 50000
Failed requests: 0
Write errors: 0
Total transferred: 3300000 bytes
HTML transferred: 100000 bytes
Requests per second: 7386.61 [#/sec] (mean)
Time per request: 1.354 [ms] (mean)
Time per request: 0.135 [ms] (mean, across all concurrent requests)
Transfer rate: 476.09 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.1 0 2
Processing: 0 1 0.5 1 11
Waiting: 0 1 0.5 1 11
Total: 1 1 0.5 1 11

Percentage of the requests served within a certain time (ms)
50% 1
66% 1
75% 1
80% 1
90% 1
95% 1
98% 2
99% 2
100% 11 (longest request)

vert.x

Server Software:
Server Hostname: xxxx
Server Port: yyyy

Document Path: /
Document Length: 2 bytes

Concurrency Level: 10
Time taken for tests: 3.865 seconds
Complete requests: 50000
Failed requests: 0
Write errors: 0
Total transferred: 3300000 bytes
HTML transferred: 100000 bytes
Requests per second: 12935.92 [#/sec] (mean)
Time per request: 0.773 [ms] (mean)
Time per request: 0.077 [ms] (mean, across all concurrent requests)
Transfer rate: 833.76 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.0 0 0
Processing: 0 1 1.0 0 49
Waiting: 0 1 1.0 0 49
Total: 0 1 1.0 0 49
WARNING: The median and mean for the processing time are not within a normal deviation
These results are probably not that reliable.
WARNING: The median and mean for the waiting time are not within a normal deviation
These results are probably not that reliable.
WARNING: The median and mean for the total time are not within a normal deviation
These results are probably not that reliable.

Percentage of the requests served within a certain time (ms)
50% 0
66% 1
75% 1
80% 1
90% 2
95% 2
98% 3
99% 4
100% 49 (longest request)

대략 2배가 차이나는데 많게는 어떤때는 3개 가까이 차이 날때도 있다. 아마도 node test.js를 실행했을 때는 물리 CPU를 1개밖에 사용하지 않는것 같고 vertx run Test.java를 실행했을 때는 물리 CPU 2개를 모두 사용하는 것 같다.

정말 그래서 생긴 차이라면 사실 이 둘의 성능은 비슷하다고 볼 수 있는거 아닌가 싶다.

[Node.js] 윤군의 아래 코드 개선안

크하하 완전 재밌게 풀었다. 잡습도 리플렉션이 있구나..

[javascript]
var params = {‘port’:port,
‘username’:req.session.username,
‘p_id’:req.params.id,
‘title’:”,
‘diffCount ‘ : 0,
‘disCount’ : 0,
‘sameCount’ : 0,
‘likeCount’ : 0,
‘queCount’ : 0,
‘allCount’ : 0
},
presentFn = function(){
Presentations.findById(req.params.id, function(err, p){
if(!p){
res.redirect(‘/list’);
} else {
params.title = p.title;
res.render(‘presentation’,params);
}
});
},
countFn = function(args){
var arg = args[idx++];
var param = {‘to’:params.p_id};
if(arg.emotion){
param.emotion = arg.emotion;
}
Comments.find(param).count(function(err, count){
params[arg.countNm] = count;
arg.callBack.call(this,args);
});
},
functions = [{’emotion’ : ‘불만이 있습니다.’, ‘countNm’ : ‘disCount’, ‘callBack’ :countFn},
{’emotion’ : ‘다르게 생각합니다.’, ‘countNm’ : ‘diffCount’, ‘callBack’ :countFn},
{’emotion’ : ‘좋아합니다.’, ‘countNm’ : ‘likeCount’, ‘callBack’ :countFn},
{’emotion’ : ‘공감하고 있습니다.’, ‘countNm’ : ‘sameCount’, ‘callBack’ :countFn},
{’emotion’ : ‘궁금해 합니다.’, ‘countNm’ : ‘queCount’, ‘callBack’ :countFn},
{‘countNm’ : ‘allCount’, ‘callBack’ :presentFn}
],
idx = 0;

countFn(functions);
[/javascript]

하지만… 결국 돌아가는건 아래 코드랑 똑같자나. 난 직관적인 코드가 더 좋으니, 내 코드에 손을 들겠다. 음하하핫!

그렇다고 고치진 않을께. 잡습 공부하긴 좋은 코드로구나.. +_+


[Node.js] mongoos로 MongoDB에 데이터 저장하기

1. mongoose 모듈 로딩(로딩이라는 표현이 맞는지는 모르겠다. node.js에서는 뭐라고 한담?)

(1.5) db 커넥션 정의하기

2. 스키마 정의

3. 사용하기

이런 3단계가 매우 쉽다. 좀 더 구체적으로.. 모델 정보를 담을 js 파일을 만들었다. 이름은 models.js 그리고 그 안에서..

var mongoose = require(‘mongoose’);

이것으로 1번 끝.

var db = mongoose.connect(‘mongodb://localhost/rtfeedback’);

이것으로 2번 끝. 이제 스키마를 정의해보자.

var Schema = mongoose.Schema,
ObjectId = Schema.ObjectId;

var Comments = new Schema({
id :ObjectId,
from :String,
to :String,
body :String,
date :Date
});
mongoose.model(“Comments”, Comments);

이것으로 3번 끝..

마지막으로 이 models.js를 하나의 모듈처럼 사용할 수 있도록 exports에 Comments를 추가해주자. 이건 node.js의 모듈 시스템 동작 원리인데.. 뭔가 참 심플해 보인다.

var Comments = exports.Comments = db.model(‘Comments’);

이것으로 모듈화 끝.

이제 models.js를 사용할 apps.js로 넘어가자.

var models = require(‘./lib/models’),
Comments = models.Comments;

여기 보면 models.Comments라고해서 아까 위에서 exports에 추가한 것을 사용할 수 있다.

이제 저장해볼까?

var newComments = new Comments();
newComments.to = channel;
newComments.from = from;
newComments.body = msg;
newComments.date = new Date();
newComments.save(function(err){
console.log(err);
});

끝이닷!!


[Node.js] socket.io로 채널 기능 구현하기

시리즈가 되어야 할 것 같다. 우선 지금까지 구현한 상황을 공유하자면…

이렇다. 처음에는 파폭에서 메시지를 보낸뒤에, 서버에서 해당 메시지를 다시 보내주는지 확인했고, 다음에는 왼쪽에 있는 크롬 브라우저에서 입력한 값을 오른쪽에 있는 파폭으로 전달 됐는지 확인했다.

사실, 초간단 실시간 웹 앱 개발은 매우 간단하다. 그러나… 내가 개발하고자 하는 앱은 채널 개념이 필요하다. 그런데.. Socket.IO에는 채널 개념이 없어서 직접 구현해 줘야 한다.

우선 내가 세운 전략은 이렇다.

1. 브라우저에서 특정 채널이 관리하는 페이지가 뜨면, 메시지에 {‘type’:’subscribe’, ‘channel’:’1′} 이런 식으로 구독할 채널 이름과 구독하겠다는 행위를 알려준다.

– 해당 페이지를 클릭한 순간 구독자가 되는 것이고, 실시간으로 데이터를 전달 받게 된다.

– 그럼 서버가 해당 Map> 형태의 콜렉션에다 client를 집어 넣는다.

2. 해당 페이지에서 메시지를 입력하면 {‘type’:’publish’, ‘channel’:’1′, ‘msg’:’할말’} 이런식으로 메시지를 보낸다.

– 그럼 서버가 Map.get(Channel)을 호출해서 가져온 List를 순회하면서 메시지를 쫙.. send() 해준다.

– 그러면 각 클라이언트로 메시지가 전달 되고..

3. 각 클라이언트의 브라우저에서 소켓으로부터 메시지를 전달 받았을 때 console.log를 찍도록 해봤다.

오예!!! 됐~~~다!!

ps: 아침에 머리감고, 면도하고, 이빨닦는데.. 회사 가기가 무척이나 싫었다.. 그래서 급하게 연차를 내고 집에서 오전에 코딩좀 하고 오후에는 펑펑 놀려고 한다. 이제 ‘구독 해지’만 구현하면 땡이다. 놀자!!!!