Trafiłem na TJ na node-canvas o przyspieszenie kodu pracuję nad rozwidleniem modułu węzła, który jest autorem i utrzymuje.nodejs natywny C++ błąd pamięci modułu NMM, przetwarzanie obrazu w kairu
Znalazłem Canvas.toBuffer(), aby zabić zasoby naszego potoku i stworzyłem alternatywę, która po prostu zamieniłaby obraz z Canvas na obraz bez przechodzenia przez bufor png/URL mediów. Problem polega na tym, że cairo jest tajemniczą bestią i istnieje dodatkowy poziom troski o pamięć przydzieloną w modułach węzła, aby nie uzyskać GCd od matki v8. Dodałem odpowiednie HandleScopes do wszystkich wymaganych funkcji, które uzyskują dostęp do danych V8.
Byłem w stanie przetestować metodę Canvas.loadImage (obraz) tysięcy razy na mojej konfiguracji mac (6.18), a także samodzielne testy na naszych serwerach ubuntu/produkcyjnych z tą samą wersją węzła. Ale kiedy kod jest uruchamiany jako proces w tle/serwer i koordynowany przez Gearmana, otrzymuję kilka "interesujących" pamięci/segfaultów.
Ponadto mam problemy z wywołaniem dowolnej z metod klas zdefiniowanych w kanale węzłowym, które nie są wstawiane wewnątrz plików nagłówkowych. Jako pytanie boczne: Jaki jest najlepszy sposób tworzenia popularnych pakietów kodu źródłowego, na których mogą polegać inne moduły węzłów?
Próbowałem odtworzyć problem i uruchomić go za pomocą gdb, node_g i wszystkich modułów węzła zbudowanych z symboli i flag debugowania. Ale błąd pojawia się w bibliotece poza źródłem, z którego mogę pobrać ślad stosu.
dla odniesienia tutaj, gdzie wywołuję loadImageData i podczas gdy działa lokalnie w różnych warunkach, w naszym środowisku produkcyjnym, gdy ostrożnie schowany w serwerze ramek wydaje się, że powoduje on segfaults (spędził dzień wczoraj próbując gdb node_g nasz Kod serwer ale serwery ramy są skopany przez gearman ... TL; DR nie dostać ślad stosu przyczyna)
https://github.com/victusfate/node-canvas/blob/master/src/Canvas.cc#L497
Handle<Value>
Canvas::LoadImage(const Arguments &args) {
HandleScope scope;
LogStream mout(LOG_DEBUG,"node-canvas.paint.ccode.Canvas.LoadImage");
mout << "Canvas::LoadImage top " << LogStream::endl;
Canvas *canvas = ObjectWrap::Unwrap<Canvas>(args.This());
if (args.Length() < 1) {
mout << "Canvas::LoadImage Error requires one argument of Image type " << LogStream::endl;
return ThrowException(Exception::TypeError(String::New("Canvas::LoadImage requires one argument of Image type")));
}
Local<Object> obj = args[0]->ToObject();
Image *img = ObjectWrap::Unwrap<Image>(obj);
canvas->loadImageData(img);
return Undefined();
}
void Canvas::loadImageData(Image *img) {
LogStream mout(LOG_DEBUG,"node-canvas.paint.ccode.Canvas.loadImageData");
if (this->isPDF()) {
mout << "Canvas::loadImageData pdf canvas type " << LogStream::endl;
cairo_surface_finish(this->surface());
closure_t *closure = (closure_t *) this->closure();
int w = cairo_image_surface_get_width(this->surface());
int h = cairo_image_surface_get_height(this->surface());
img->loadFromDataBuffer(closure->data,w,h);
mout << "Canvas::loadImageData pdf type, finished loading image" << LogStream::endl;
}
else {
mout << "Canvas::loadImageData data canvas type " << LogStream::endl;
cairo_surface_flush(this->surface());
int w = cairo_image_surface_get_width(this->surface());
int h = cairo_image_surface_get_height(this->surface());
img->loadFromDataBuffer(cairo_image_surface_get_data(this->surface()),w,h);
mout << "Canvas::loadImageData image type, finished loading image" << LogStream::endl;
}
}
i oto co obecna metoda wygląda Image (Usunąłem niektóre skomentowane informacje dotyczące logowania) https://github.com/victusfate/node-canvas/blob/master/src/Image.cc#L240
/*
* load from data buffer width*height*4 bytes
*/
cairo_status_t
Image::loadFromDataBuffer(uint8_t *buf, int width, int height) {
this->clearData();
int stride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32, width); // 4*width + ?
this->_surface = cairo_image_surface_create_for_data(buf,CAIRO_FORMAT_ARGB32,width,height,stride);
this->data_mode = DATA_IMAGE;
this->loaded();
cairo_status_t status = cairo_surface_status(_surface);
if (status) return status;
return CAIRO_STATUS_SUCCESS;
}
Każda pomoc, porady, pomoc lub słowa zachęty byłyby mile widziane.
Pochodzi z google groups
Używamy również płótna węzłowego w produkcji i mamy procesy autonomiczne, które są zabijane i restartowane po wykonaniu ~ 200 obrazów (z powodu wycieków pamięci i fragmentacji). Sprawdź swoje natywne rozszerzenia z Valgrind dla przekroczenia pamięci: http://valgrind.org/docs/manual/QuickStart.html To narzędzie powinno ujawnić powód naruszenia segmentacji już w testowaniu env. –
dzięki teemu, zbieramy i budujemy między partiami obrazów ~ 24-> 100 lub więcej. –
@TeemuIkonen Miałem problemy z wcześniejszym korzystaniem z valgrindu zarówno na stronie osx jak i linuxie, wszelkie wskazówki dotyczące sensownego wyniku (zamrożone natychmiast na os x, wykonałem kilka połączeń, by wspomnieć o błędzie po stronie Linux) –