2013-06-18 4 views
5

Mam program Java, który jest przeznaczony do wyświetlania obrazów w niestandardowym formacie pliku, czytać biblioteki C++ przy użyciu JNI. Dane są ładowane do tablicy znaków po stronie C++ i przenoszone do obrazu BufferedImage po stronie Java. Ponieważ sekcje obrazu mogą zostać usunięte z pamięci i muszą być ładowane dość regularnie, więc chcę, aby te operacje były tak szybkie, jak to tylko możliwe.Skutecznie przenieść dużą ilość danych bajtowych z C++ na Javę

Sposób, w jaki aktualnie to robię, polega na tym, że dane są odczytywane z pliku do bufora w pamięci biblioteki C++. Aby wypełnić obraz BufferedImage, kod Java wykonuje wywołanie funkcji JNI dla każdego piksela do odczytu z tego bufora i, jeśli to konieczne, ładuje kolejny fragment danych do bufora. Działa to, ale z większym obciążeniem niż chciałbym.

To, co planowałem zrobić, aby to poprawić, to przekazanie obiektu BufferedImage do kodu C++ za pomocą wywołania JNI i wywołanie funkcji z tej strony. Badałem JNI tak bardzo, jak tylko mogłem, ale nie byłem w stanie dowiedzieć się, czy jest jakiś koszt modyfikacji obiektów Java z biblioteki C++, która została załadowana przez maszynę JVM. Czy jest to dobry sposób na wdrożenie tego, czy istnieje szybszy sposób przesyłania dużych ilości danych bajtowych za pomocą JNI?

+4

Połączenie na piksel brzmi okropnie! To byłoby miliardy wezwań do większych obrazów. Co powiesz na pobieranie bloków lub linii rastrowych (na przykład jednostek większych obrazów) na raz? Czy linie rastrowe można odczytywać sekwencyjnie jako spakowane i unikać dodatkowych konwersji? – user2246674

+0

Tak, linie i bloki mogą być odczytywane do bufora po stronie C++. Zrobiłem trochę optymalizacji tego po stronie C++. Problem polega na tym, że nie znam skutecznego sposobu przesyłania tych danych z powrotem do java, więc wykonuję oddzielne wywołanie każdego piksela, aby odczytać dane z bufora C++. – resueman

+1

@resuerman Czy coś [WritableRaster.setSamples] (http://docs.oracle.com/javase/1.5.0/docs/api/java/awt/image/WritableRaster.html#setSamples (int,% 20int,% 20int ,% 20int,% 20int,% 20double [])) są używane? Jeśli to możliwe, może to być po prostu znalezienie sposobu (najefektywniejszego) załadowania danych do tablicy Javy. Czy istnieje sposób na przypięcie tablicy i/lub zwinięcie pamięci [C++] i uniknięcie [pierwotnej] kopii? Nawet z dodatkową operacją kopiowania (C++ -> Java Array-> Raster), powinna ona znacznie zmniejszyć liczbę wywołań JNI. Również (i śmiem twierdzić, że brzmi to "ekstra sprytnie"), czy można tu użyć OpenGL (tekstury)? – user2246674

Odpowiedz

1

Najbardziej efektywnym sposobem przenoszenia danych przez granicę JNI jest prawdopodobnie bezpośrednia ByteBuffers. Powinieneś poruszać się tak bardzo, jak to możliwe jednocześnie, ponieważ przekracza on samą granicę, która jest nieefektywna, a nie transfer. Z pewnością więcej niż jeden piksel, najlepiej megabajty na raz.

+0

Awesome. To brzmi jak dokładnie to, czego szukałem. Dziękuję Ci. – resueman