Pull to refresh

Использование V8, заключение

Reading time4 min
Views2.6K
Использование V8, заключение

Часть 3 находится здесь: habrahabr.ru/blogs/development/72765

Часть 2 находится здесь: habrahabr.ru/blogs/development/72592

Часть 1 находится здесь: habrahabr.ru/blogs/development/72474



В заключении пробежимся по всяким мелочам.

— Память

Алгоритм работы сборщика мусора в V8 предназначен для хорошей работы в Chrome, то есть его основная задача — минимизация задержек. Отсюда его желание как можно дольше откладывать очистку мусора. Это плохая новость для серверного приложения. Хорошая новость в том, что имеется способ вызвать очистку мусора вручную. Для этого нужно перед сборкой v8.lib исправить файл flag-definitions.h.

В файле flag-definitions.h необходимо найти строку с expose_gc:

DEFINE_bool(expose_gc, false, "expose gc extension")

И прописать "true" (вместо "false").

После сборки v8.lib в глобальном объекте JavaScript доступна функция "gc()", которая и выполняет полную сборку мусора. Однако, по моему опыту трудно найти время ее вызова. Если это делать после завершения некоторой сессии, то массовый останов сессий вызовет длительную задержку. Одним словом, надо использовать gc() как-то хитро, не «в лоб».

Внимание! После исправления файла flag-definitions.h он перестанет быть управляемым subversion. Перед очередным скачиванием исходников из ветки trunk восстановите файл (или удалите, чтобы снова скачался).

— Обработка ошибок

В примере консольного приложения, выполняющего JavaScript, обработка ошибок довольно примитивна. На самом деле, информация про ошибку, вызвавшую исключение, более обширна. Можно обратиться к файлу samples/shell.cc и поизучать функцию ReportException:

void ReportException(v8::TryCatch* try_catch) {
 v8::HandleScope handle_scope;
 v8::String::Utf8Value exception(try_catch->Exception());
 const char* exception_string = ToCString(exception);
 v8::Handle<v8::Message> message = try_catch->Message();
 if (message.IsEmpty()) {
  // V8 didn't provide any extra information about this error; just
  // print the exception.
  printf("%s\n", exception_string);
 } else {
  // Print (filename):(line number): (message).
  v8::String::Utf8Value filename(message->GetScriptResourceName());
  const char* filename_string = ToCString(filename);
  int linenum = message->GetLineNumber();
  printf("%s:%i: %s\n", filename_string, linenum, exception_string);
  // Print line of source code.
  v8::String::Utf8Value sourceline(message->GetSourceLine());
  const char* sourceline_string = ToCString(sourceline);
  printf("%s\n", sourceline_string);
  // Print wavy underline (GetUnderline is deprecated).
  int start = message->GetStartColumn();
  for (int i = 0; i < start; i++) {
   printf(" ");
  }
  int end = message->GetEndColumn();
  for (int i = start; i < end; i++) {
   printf("^");
  }
  printf("\n");
 }
}

* This source code was highlighted with Source Code Highlighter.


— Получение текущего контекста

Иногда внутри обратного вызова функции C++ нам требуется получить текущий контекст V8. В классе Context есть несколько методов:

 static Local<Context> GetCurrent(); // контекст на вершине стека V8

 static Local<Context> GetEntered(); // контекст на "дне" стека V8

 static Local<Context> GetCalling(); // контекст функции, которая вызвала нашу

* This source code was highlighted with Source Code Highlighter.

Обычно следует использовать GetCurrent().

— Перечисление свойств объекта V8

Для получения списка свойств объекта V8 используется вызов GetPropertyNames(). Получить имена и значения всех свойств объекта можно так:

Local<Object> rec; // объект

Local<Array> names = rec->GetPropertyNames(); // получаем список имен свойств
for (unsigned j = 0; j < names->Length(); j++)
{
// получаем имя
    Local<String> name = Local<String>::Cast(names->Get(Integer::New(j)));
// получаем значение
    Local<Value> val = rec->Get(name);
// ...
}

* This source code was highlighted with Source Code Highlighter.


— Создание контекста с привязкой глобального объекта к функционалу

В предыдущих частях мы рассматривали лишь создание пустого контекста (с помощью вызова Context::New() без параметров). V8 позволяет использовать для глобального объекта тепмлейт объекта:

...
// создаем темплейт глобального объекта
Handle<ObjectTemplate> global = ObjectTemplate::New(); 

// прописываем функции
global->Set(String::NewSymbol("foo"), FunctionTemplate::New(Foo));
global->Set(String::NewSymbol("bar"), FunctionTemplate::New(Bar));

// создаем контекст
Context::New(NULL, global);

* This source code was highlighted with Source Code Highlighter.


— Заключение

В целом мы довольны встраиванием V8. Если будет время я напишу о нашей платформе. Вкратце, мы «обернули» в JavaScript встроенную SQLITE, обработку запросов HTTP и обмен асинхронными сообщениями. Это немного похоже на то, что делает ERLANG, но на более «человеческом» языке; более простое и удобное в использовании.

UPD: Вот, кстати, ссылка на мою статью про эту платформу: habrahabr.ru/blogs/development/48842
Tags:
Hubs:
+11
Comments6

Articles

Change theme settings