1. V8 Add-On With Middleware
Modules
Code name Ib. js 데이터 솔루션 팀 Jay
2. INDEX
V8 소개
V8 Add-on이란
V8 Add-on을 위한 사전 지식
실전
테스트 Echo Server & Client
Let’s Discuss !
3. V8 소개
Well-Maden Java-script Engine
Chrome의 Java script 엔진으로 유명세를 타기 시작함
모두 C++ 코드로 짜여짐
Build는 GYP를 활용한 makefile 방식
타고난 성능으로 인해 다양한 open-source project에 활용되고 있다.
프로젝트 사이트 : https://code.google.com/p/v8/
특징
가비지 콜렉터 성능이 다른 엔진에 비해 매우 좋다.
광범위한 캐싱의 활용
C++모듈의 추가나 다른 C++로 짜여진 application에 이식이 용이
단, 메모리의 점유가 많은 편
4. V8 Add-on 이란?
정의? (거창하네..)
C++모듈을 추가하여 V8의 Java-script를 확장하는 방법
C++모듈을 추가하여 확장한 javascript 규격을 빌드한 v8에서 활용하여 코딩이 가능하다!
Node.js역시 이러한 방법을 이용해 다양한 규격을 제공.
기본적인 Add-on방식
확장할 규격을 정하여 javascript에 공개할 형식을 정한다.
Object?
Function?
정해진 형식으로 Template을 만든다.
Template을 통해 Instance를 만들고 Javascript Heap에 올려준다.
5. V8 Add-on을 위한 사전 지식
주요 클래스 정리
Isolate
V8 instance를 생성하고 관리하는 클래스.
Context
JavaScript를 사용하기 위한 Context instance를 생성하고 관리하는 클래스
HandleScope
GC가 동작하는 기준이 되는 Scope를 생성하는 클래스. 이 클래스의 인스턴스가 생성되고 파괴되면 해당 범위에서 생성된 Handle들은 모두 GC의 대상이 된다.
Handle
Heap에 관리되는 객체를 생성하고 접근할 수 있게 해주는 클래스
Local - HandleScope에 영향을 받는 handle 클래스
Persistant - HandleScope에 영향을 받지 않는 handle 클래스
FunctionTemplate
Javascript측에 Function을 노출하기 위해 사용하는 클래스로, 한 번 Function Template 만들어 두면 해당 객체를 통해 간단하게 Javascript측에 노출할 Function 객체를 생성할 수
있다.(ex: 여러개의 isolate에 동일한 규격으로 함수를 노출할 때)
ObjectTemplate
Javascript측에 Object를 노출하기 위해 사용하는 클래스로, 한 번 Object Template을 만들어 두면 해당 객체를 통해 간단하게 Javascript측에 노출할 Object의 객체를 생성 할 수
있다.(ex: 특정 Function을 new 를 통해 생성시키는 경우 Constructor에서 사용)
7. V8 Add-on을 위한 사전 지식
GYP (Generate your project)
Json 문법을 이용해 프로젝트 파일을 만들어 주는 Opensource project
Makefile뿐만 아니라 Xcode와 VisualStudio용 프로젝트 파일들도 생성 가능하다!!
V8 프로젝트의 모든 makefile이 gyp를 통해 만들어짐.
프로젝트 사이트 : https://code.google.com/p/gyp/
C++모듈을 추가할 때 해당 모듈들에 대한 gyp파일을 생성하고 해당 gyp파일을 v8 빌드에 include시켜야
한다.
Clean 룰은 별도로 만들어야 함.(v8 add-on 작업시에는 v8에서 만들어 둔 rule을 사용하면 됨)
8. 실전 – ib.js 구상
어떤 모듈을 노출해 볼까?
IChannel
멀티스레드를 기반으로 동작하는 네트워크 클래스
CSessionSock
IChannel에서 사용하는 세션 클래스
모듈들을 어떻게 노출 할까?
Function !!
Object ?
Function vs Object
Win! 상속 처리 Lose
Win! 메모리 사용 Lose
9. 실전 – ib.js 살 붙이기
Namespace를 쓰고 싶은데…
net.ib.Channel
Net.ib.SessionSock
Function Template 만들기
Function을 통해 클래스를 노출하고, 각각의 Api들은 Javascript의 prototype을 통해 노출되도록 하자
상속을 위해서
Javascript로 부터 호출된 C++함수에서 리턴값 처리는?
void InsertAllModules()
{
//make "net" object
v8::Local<v8::FunctionTemplate> netFTempl =
v8::FunctionTemplate::New(V8Isolate::get());
//make "ib" object
v8::Local<v8::FunctionTemplate>ibFTempl=
v8::FunctionTemplate::New(V8Isolate::get());
//set net into ib
ibFTempl->Set(V8Isolate::get(),"net", netFTempl);
//BufferExtern::InstallStrBuffer(netFTempl, NULL);
ChannelExtern::getInstance()->installClass(netFTempl, (char*)"Channel");
SessionSockExtern::getInstance()->installClass(netFTempl, (char*)"SessionSocket");
//create global obj template to set into global context
v8::Local<v8::ObjectTemplate>global= V8Global::get();
//insert apiset object to global ObjectTemplate.
global->Set(V8Isolate::get(), "ib", ibFTempl);
}
void
IExternBase::installClass(v8::Local<v8::Template> target, char* name)
{
//make inner template & save it
Local<FunctionTemplate> tmpl =
FunctionTemplate::New(V8Isolate::get());
//install methods to template
installPrototypeFunctions(tmpl);
if (_funcTemplate.IsEmpty()) _funcTemplate = tmpl;
//make outer template & expose it
Local<FunctionTemplate> outerTempl =
FunctionTemplate::New(V8Isolate::get(), constructorCallback);
installPrototypeFunctions(outerTempl);
//set to target
if (target.IsEmpty() == false)
target->Set(V8Isolate::get(), name, outerTempl);
}
void SessionSockExtern::PopFrontRecvBuf(
const v8::FunctionCallbackInfo<v8::Value>& info)
{
CSessionSock* ptr=
(CSessionSock*)Unwrap<CSessionSock>(info.Holder());
intres= ptr->PopFrontRecvBuf(info[0]->Int32Value());
info.GetReturnValue().Set(res);
}
10. 실전 – ib.js 살 붙이기
어라? IChannel은 Interface 클래스다..
순수 가상 함수를 어쩐다…
악~! 생성자가 계속 호출된다!!(recursive calling)
Thread safety 문제가…
스레드에서 javascript 함수 호출이 되지 않는다!!
가상 함수를 구현한 자식 클래스를
만들어 해당 클래스를 노출하기로
결정
동일한 FunctionTemplate을 2개
만들어 외부 노출용과 객체 생성용으로
구분하여 생성자에서 호출하도록 수정
메인 스레드에 간단한 이벤트 루프를
구성하여 스레드에서 해당 이벤트
루프에 함수 호출을 위임
11. 실전 – ib.js 완성?!
끝으로 main 함수에서 할 일이 뭘까?
빌드를 위한 gyp 설정하기
ibShell 완성~
• Context 생성
• 확장 모듈 노출을 위한 install
• 소스 스크립트 컴파일
• 스크립트 실행
V8/build/all.gyp 파일 수정
{
'targets': [
{
'target_name': 'All',
'type': 'none',
'dependencies': [
'../samples/samples.gyp:*',
'../src/d8.gyp:d8',
#steady add line
'../../middleware/V8Extern/build/ib.gyp:*'
# '../test/cctest/cctest.gyp:*',
],
'conditions': [
['component!="shared_library"', {
'dependencies': [
'../tools/lexer-shell.gyp:lexer-shell',
'../tools/lexer-shell.gyp:parser-shell',
],
}],
]
}
]
}
12. Test Echo Server&Client
ib.js 테스트
단순 Echoing Server 를 javascript로 구현
Session 맺고 곧바로 8Byte의 데이터를 송신하는 Client를 javascript로 구현
비교 테스트
동일한 로직의 C++ Echoing Server/client 작성하여 비교 테스트 수행.
(동일한 Middleware Module들 사용하여 구현)
Memory Usage Client
(60,000 sessions set)
Server
(500,000 sessions capable)
Idle state 3,489,136 bytes 15,722,292 bytes
Running 2,933,420 bytes 11,381,124 bytes
60,000 Session &
60,000 Req. & Res.
Not changed Not changed
Speed Checking Ib.js C++
60,000 Sessions&
60,000 Req. & Res.
Avg. 9.6 Avg. 9.3
★ 서버 테스트 장비 : 172.16.0.162 (cpu: i5-3570 3.4 GHz, ram: 16GB)
★ 클라이언트 테스트 장비 : 172.16.0.194(cpu: Q8300 2.5GHz(2.0) ram: 4GB)
★ 최적화에 대한 고민 없이 한 테스트로 최적화 수행 후 결과는 차이가 있을 수 있음.
13. Let’s Discuss !
V8의 성능은 서버로 쓸 만 한가?
Node.js의 성능은?
Java JNI : v8(Javascript) Add-on
앞으로 해봐야 할 것들은?