|
Replies:
31
-
Pages:
3
[
1
2
3
| Next
]
-
Last Post:
13 Jan 25, 20:32
Last Post By: MarkusD
|
Threads:
[
Previous
|
Next
]
|
|
Posts:
3,622
Registered:
18-Oct-2002
|
|
|
Faster image reading and writing with jpeg-turbo
Posted:
7 Jan 25, 20:19
|
|
|
I've discovered a way to speed up JPEG reads 3x and JPEG writes up to 7x. This is possible by integrating the "jpeg-turbo" ( https://libjpeg-turbo.org/) native code library into jAlbum. Java's standard JPEG image reader and writer is already using native code, but jpeg-turbo uses special "SIMD" assembly instructions. SIMD stands for "Single Instruction Multiple Data" and is a set of instructions that operates on multiple data sets ( https://en.wikipedia.org/wiki/Single_instruction,_multiple_data). It obviously makes a huge difference when it comes to multimedia processing. The jpeg-turbo library has accelerated native code for all modern CPUs, including Intel/AMD 64 and arm CPUs (including Apple's M-series).
To try out this library, install https://jalbum.net/download/imageio-turbojpeg.jar into jAlbum's lib folder and restart jAlbum. You can also get a further speed boost by doing a core update so you get v36.1.2.
The Java integration I've made here currently has one limitation: It doesn't pass along EXIF metadata to generated images.
Apart from being super fast, the jpeg-turbo library is supposed to be good at handling "corner case" JPEGs.
On my Mac (M4 CPU) I get 84% faster builds of "Sample Project" compared with the official v36.1
On Windows, I get 55% faster builds of "Sample Project", but this is when emulating Intel. I'd like to hear what you get on a genuine Intel/AMD Windows machine.
I've also tested this library on Linux (aarch64), but not on Linux (amd64)
What do you think?
|
|
|
Posts:
3,992
Registered:
4-Aug-2006
|
|
|
Re: Faster image reading and writing with jpeg-turbo
Posted:
7 Jan 25, 20:40
in response to: davidekholm
|
|
|
M2 Mac, 8MB
jAlbum 36.1 "Sample Project" made in 6.339s
jAlbum 36.1.2 "Sample Project" made in 7.293s
jAlbum 36.1.2 Turbo "Sample Project" made in 5.142s (19% quicker)
|
|
|
Posts:
8,435
Registered:
31-Jan-2006
|
|
|
Re: Faster image reading and writing with jpeg-turbo
Posted:
7 Jan 25, 20:40
in response to: davidekholm
|
|
|
The Java integration I've made here currently has one limitation: It doesn't pass along EXIF metadata to generated images.
For that kind of speed improvement, I'd say that's an acceptable trade-off. Writing EXIF to the generated images has always been a little dodgy.
And I'm a bit of a purist - I say that EXIF should consist only of information the camera writes to an image file when you shoot the photo. It's not the place for other, user-generated content. And since the generated images aren't coming from a camera, EXIF data have no business being in them, anyway.
Will do some time trials, and post back later....
|
|
|
Posts:
3,622
Registered:
18-Oct-2002
|
|
|
Re: Faster image reading and writing with jpeg-turbo
Posted:
7 Jan 25, 20:58
in response to: RobM
|
|
|
M2 Mac, 8MB
jAlbum 36.1 "Sample Project" made in 6.339s
jAlbum 36.1.2 "Sample Project" made in 7.293s
jAlbum 36.1.2 Turbo "Sample Project" made in 5.142s (19% quicker)
Interesting that you don't get that "radical" differences. I did a 3x "warmup build" on both "before" and "after", but even without any warmup I get a 77% improvement. Can you share your data from Profiler.instance? Here's my data (Sample Project):
Original:
FileFilters.saveImage: 210 calls 0,644s
FileFilters.loadImage: 57 calls 0,508s
HardwareSmoothScaler.scale: 159 calls 0,502s
FileFilters.unifyColorModel: 57 calls 0,09s
AlbumBean.makeIndexPages: 4 calls 0,032s
AlbumBean.registerVariables: 58 calls 0,024s
Process compiled expression: 7 calls 0,023s
init: 1 calls 0,022s
Executing compiled scriptlet: 63 calls 0,02s
Create MediaRSS: 4 calls 0,014s
AlbumObjectImpl.getProperties: 57 calls 0,011s
AlbumObjectImpl.getXmpManager: 63 calls 0,01s
Executing interpreted scriptlet: 368 calls 0,009s
AlbumObjectImpl.getMetadata: 57 calls 0,009s
AlbumObjectProperties.load: 13 calls 0,009s
RecoveryTool.createLifeboat: 1 calls 0,008s
FileFilters.getBasicImageInfo: 57 calls 0,005s
AlbumBean.pushVars: 158 calls 0,004s
Reading file attributes: 55 calls 0,004s
AlbumBean.popVars: 157 calls 0,002s
AlbumBean.countTotalFiles: 1 calls 0,002s
predir processing: 4 calls 0,002s
JAlbumUtilities.countCategories: 8 calls 0,001s
Process expression: 1 calls 0,001s
Copy res files: 1 calls 0,001s
Compiling scriptlets: 46 calls 0s
AlbumBean.getFolderProperties: 5 calls 0s
AlbumBean.processFilters: 264 calls 0s
Writing pages: 12 calls 0s
Total: 1948 calls 1,957s
Turbo:
HardwareSmoothScaler.scale: 159 calls 0,304s
FileFilters.saveImage: 210 calls 0,283s
FileFilters.loadImage: 57 calls 0,142s
AlbumBean.registerVariables: 58 calls 0,035s
AlbumBean.makeIndexPages: 4 calls 0,031s
Process compiled expression: 7 calls 0,029s
init: 1 calls 0,027s
Executing compiled scriptlet: 63 calls 0,018s
Create MediaRSS: 4 calls 0,013s
AlbumObjectProperties.load: 13 calls 0,01s
AlbumObjectImpl.getProperties: 57 calls 0,01s
AlbumObjectImpl.getXmpManager: 53 calls 0,008s
Executing interpreted scriptlet: 368 calls 0,008s
AlbumObjectImpl.getMetadata: 57 calls 0,008s
RecoveryTool.createLifeboat: 1 calls 0,007s
AlbumBean.pushVars: 158 calls 0,006s
AlbumBean.popVars: 157 calls 0,005s
FileFilters.getBasicImageInfo: 57 calls 0,005s
predir processing: 4 calls 0,004s
Reading file attributes: 55 calls 0,003s
Process expression: 1 calls 0,002s
AlbumBean.countTotalFiles: 1 calls 0,002s
JAlbumUtilities.countCategories: 8 calls 0,001s
Compiling scriptlets: 46 calls 0,001s
AlbumBean.getFolderProperties: 5 calls 0s
Copy res files: 1 calls 0s
AlbumBean.processFilters: 264 calls 0s
Writing pages: 12 calls 0s
Total: 1881 calls 0,962s
|
|
|
Posts:
8,435
Registered:
31-Jan-2006
|
|
|
Re: Faster image reading and writing with jpeg-turbo
Posted:
7 Jan 25, 21:10
in response to: JeffTucker
|
|
|
Oh, this is definitely a "keeper." In fact, I'd call it jAlbum 37.
Just don't forget to get rid of the option to write EXIF to the output images.
I fed a project 100 recent JPG's from my iPhone 14. My PC is aging, but it's got an Intel i7 8700 3.20GHz chip, 16GB RAM, and an SSD drive.
Three "start from no output" trials. Before: 11.8s. After: 5.2s. That cuts 56% off the build time.
ETA: That also indicates that your Intel emulator is pretty reliable!
|
|
|
Posts:
3,622
Registered:
18-Oct-2002
|
|
|
Re: Faster image reading and writing with jpeg-turbo
Posted:
7 Jan 25, 21:30
in response to: JeffTucker
|
|
|
Great!
Short album build tests may be biased negatively as there is a short load time for the library itself. You can preload the native code library by issuing: org.libjpegturbo.turbojpeg.TJLoader.load();
from the system console.
|
|
|
Posts:
8,435
Registered:
31-Jan-2006
|
|
|
Re: Faster image reading and writing with jpeg-turbo
Posted:
7 Jan 25, 21:39
in response to: JeffTucker
|
|
|
On my M2 Mac, with the same 100 JPG's, the new version shaves 39% off the build time.
|
|
|
Posts:
8,435
Registered:
31-Jan-2006
|
|
|
Re: Faster image reading and writing with jpeg-turbo
Posted:
7 Jan 25, 21:42
in response to: davidekholm
|
|
|
You can preload the native code library by issuing: org.libjpegturbo.turbojpeg.TJLoader.load();
from the system console.
On the PC, that doesn't yield any improvement. On the Mac, it results in a 45% faster build, rather than 39%.
|
|
|
Posts:
3,992
Registered:
4-Aug-2006
|
|
|
Re: Faster image reading and writing with jpeg-turbo
Posted:
7 Jan 25, 22:04
in response to: davidekholm
|
|
|
All single clean builds of the album, used two skins Missive and Plain.
Missive skin times 8.229s v 5.225s (36.5% gain)
Plain skin times 7.482s v 4.218s (43% gain)
36.1.1 No Turbo
(Missive skin)
"Sample Project" made in 8.229s
0.028s ==>
FileFilters.loadImage: 96 calls 2.497s
FileFilters.saveImage: 81 calls 2.131s
HardwareSmoothScaler.scale: 77 calls 1.218s
AlbumBean.makeIndexPages: 4 calls 0.85s
init: 1 calls 0.74s
Compiling script: 4 calls 0.531s
Compiling scriptlets: 51 calls 0.519s
Executing compiled scriptlet: 627 calls 0.341s
Process compiled expression: 10 calls 0.302s
FileFilters.unifyColorModel: 96 calls 0.183s
AlbumBean.registerVariables: 116 calls 0.103s
Create MediaRSS: 4 calls 0.063s
Executing interpreted scriptlet: 382 calls 0.05s
AlbumObjectImpl.getXmpManager: 79 calls 0.048s
AlbumObjectImpl.getMetadata: 71 calls 0.044s
AlbumObjectProperties.load: 37 calls 0.036s
Copy res files: 1 calls 0.035s
AlbumObjectImpl.getProperties: 82 calls 0.035s
predir processing: 4 calls 0.031s
BetterMediumScaler.scale: 10 calls 0.021s
FileFilters.getBasicImageInfo: 70 calls 0.02s
RecoveryTool.createLifeboat: 1 calls 0.019s
Reading file attributes: 88 calls 0.015s
Writing pages: 12 calls 0.01s
Process expression: 1 calls 0.006s
JAlbumUtilities.countCategories: 15 calls 0.004s
AlbumBean.popVars: 322 calls 0.003s
AlbumBean.countTotalFiles: 1 calls 0.003s
AlbumBean.pushVars: 323 calls 0.002s
AlbumBean.getFolderProperties: 13 calls 0.001s
Emptying res folder: 1 calls 0s
AlbumBean.processFilters: 178 calls 0s
Total: 2858 calls 9.861s
(Plain skin)
"Sample Project" made in 7.482s
0.002s ==>
FileFilters.saveImage: 218 calls 3.767s
FileFilters.loadImage: 75 calls 1.995s
HardwareSmoothScaler.scale: 165 calls 1.239s
init: 1 calls 0.758s
Process compiled expression: 7 calls 0.399s
Compiling script: 4 calls 0.368s
Executing compiled scriptlet: 63 calls 0.198s
AlbumBean.makeIndexPages: 4 calls 0.18s
FileFilters.unifyColorModel: 75 calls 0.165s
Compiling scriptlets: 46 calls 0.061s
AlbumBean.registerVariables: 60 calls 0.05s
Create MediaRSS: 4 calls 0.032s
Executing interpreted scriptlet: 382 calls 0.022s
AlbumObjectProperties.load: 27 calls 0.02s
AlbumObjectImpl.getProperties: 70 calls 0.018s
AlbumBean.pushVars: 162 calls 0.015s
predir processing: 4 calls 0.015s
AlbumObjectImpl.getXmpManager: 68 calls 0.014s
AlbumObjectImpl.getMetadata: 65 calls 0.013s
RecoveryTool.createLifeboat: 1 calls 0.012s
BetterMediumScaler.scale: 5 calls 0.011s
AlbumBean.popVars: 161 calls 0.009s
FileFilters.getBasicImageInfo: 64 calls 0.009s
Reading file attributes: 69 calls 0.007s
Copy res files: 1 calls 0.006s
Process expression: 1 calls 0.003s
AlbumBean.countTotalFiles: 1 calls 0.003s
Writing pages: 12 calls 0.003s
AlbumBean.processFilters: 274 calls 0.002s
JAlbumUtilities.countCategories: 8 calls 0.001s
AlbumBean.getFolderProperties: 9 calls 0s
Emptying res folder: 1 calls 0s
Total: 2107 calls 9.395s
36.1.2 Turbo
(Missive Skin)
"Sample Project" made in 5.225s
0.002s ==>
HardwareSmoothScaler.scale: 77 calls 1.308s
init: 1 calls 0.919s
FileFilters.loadImage: 96 calls 0.818s
AlbumBean.makeIndexPages: 4 calls 0.733s
Compiling script: 4 calls 0.663s
Compiling scriptlets: 58 calls 0.545s
Process compiled expression: 10 calls 0.366s
Executing compiled scriptlet: 991 calls 0.34s
FileFilters.saveImage: 81 calls 0.306s
AlbumBean.registerVariables: 116 calls 0.152s
AlbumBean.makeSlide: 52 calls 0.135s
Create MediaRSS: 4 calls 0.073s
Executing interpreted scriptlet: 382 calls 0.059s
FileFilters.getBasicImageInfo: 70 calls 0.056s
AlbumObjectImpl.getXmpManager: 79 calls 0.048s
predir processing: 4 calls 0.047s
AlbumObjectImpl.getMetadata: 71 calls 0.044s
Copy res files: 1 calls 0.038s
AlbumObjectProperties.load: 37 calls 0.033s
AlbumObjectImpl.getProperties: 82 calls 0.032s
BetterMediumScaler.scale: 10 calls 0.025s
Writing pages: 64 calls 0.019s
RecoveryTool.createLifeboat: 1 calls 0.016s
Reading file attributes: 87 calls 0.013s
Process expression: 1 calls 0.006s
AlbumBean.popVars: 530 calls 0.004s
JAlbumUtilities.countCategories: 15 calls 0.003s
AlbumBean.countTotalFiles: 1 calls 0.003s
AlbumBean.pushVars: 531 calls 0.003s
AlbumBean.getFolderProperties: 13 calls 0.001s
AlbumBean.processFilters: 178 calls 0s
Total: 3651 calls 6.808s
(Plain skin)
"Sample Project" made in 4.218s
0.002s ==>
HardwareSmoothScaler.scale: 165 calls 1.2s
FileFilters.saveImage: 218 calls 0.73s
init: 1 calls 0.679s
FileFilters.loadImage: 75 calls 0.565s
Compiling script: 4 calls 0.411s
Process compiled expression: 7 calls 0.278s
Compiling scriptlets: 46 calls 0.185s
AlbumBean.makeIndexPages: 4 calls 0.17s
Executing compiled scriptlet: 63 calls 0.146s
AlbumBean.registerVariables: 60 calls 0.059s
Create MediaRSS: 4 calls 0.032s
Executing interpreted scriptlet: 382 calls 0.023s
AlbumObjectProperties.load: 27 calls 0.019s
AlbumObjectImpl.getProperties: 70 calls 0.018s
predir processing: 4 calls 0.016s
AlbumBean.pushVars: 162 calls 0.014s
FileFilters.getBasicImageInfo: 64 calls 0.013s
AlbumObjectImpl.getXmpManager: 68 calls 0.012s
RecoveryTool.createLifeboat: 1 calls 0.012s
AlbumObjectImpl.getMetadata: 65 calls 0.011s
BetterMediumScaler.scale: 5 calls 0.009s
AlbumBean.popVars: 161 calls 0.007s
Copy res files: 1 calls 0.007s
Reading file attributes: 69 calls 0.007s
Process expression: 1 calls 0.004s
AlbumBean.countTotalFiles: 1 calls 0.002s
Writing pages: 12 calls 0.002s
JAlbumUtilities.countCategories: 8 calls 0.001s
AlbumBean.processFilters: 274 calls 0.001s
AlbumBean.getFolderProperties: 9 calls 0s
Emptying res folder: 1 calls 0s
Total: 2032 calls 4.633s
|
|
|
Posts:
3,992
Registered:
4-Aug-2006
|
|
|
Re: Faster image reading and writing with jpeg-turbo
Posted:
7 Jan 25, 22:14
in response to: davidekholm
|
|
|
Great!
Short album build tests may be biased negatively as there is a short load time for the library itself. You can preload the native code library by issuing: org.libjpegturbo.turbojpeg.TJLoader.load();
from the system console.
Preloading for me, using Plain skin goes from 4.218s to 3.39s (19.6% gain)
|
|
|
Posts:
682
Registered:
13-Apr-2006
|
|
|
Re: Faster image reading and writing with jpeg-turbo
Posted:
7 Jan 25, 22:55
in response to: davidekholm
|
|
|
What do you think?
David, bei allem Respekt, aber das wird im Alltag kaum einen Unterschied machen, ob das Erzeugen einer JPG-Datei nun 20%, 30% oder 50% schneller wird. Warum? Weil ich nur extrem selten neue Dateien in meinem Projekt habe wenn ich es compiliere. In 9 von 10 Fällen compiliere ich ein Projekt neu, weil ich Kommentare, Titel oder Schlüsselworte verändert habe. Und dieser Prozess dauert bei einem Real-World-Projekt weit über 10 Minuten.
Und ich frage mich bis heute, was macht JA in dieser Zeit? Das ist immer wieder sehr frustrierend.
Was ich sehr häufig während des Compilierens sehe ist die Meldung, dass Metadaten gelesen werden. Aber wieso werden Metadaten von fast 12.000 Objekten (Bildern und Video) gelesen, wenn keine einzige Datei davon neu ist (alle diese Infos stehen doch in den .info-Dateien)?
Auch bei PNG-Dateien werden Metadaten gelesen, so viel ich weiß haben PNG-Dateien überhaupt keine Metadaten. Alleine das Compilieren einiger tausend PNG-Dateien dauert eine halbe Ewigkeit.
Wenn du wirklich die Performance von JA steigern willst, dann musst du meiner Meinung nach an völlig anderen Prozessen optimieren.
Bitte verstehe das alles als sehr wohlmeinende positive Kritik.
Bitte entschuldige den Text auf Deutsch.
Gruß, Markus
|
|
|
Posts:
8,435
Registered:
31-Jan-2006
|
|
|
Re: Faster image reading and writing with jpeg-turbo
Posted:
7 Jan 25, 23:05
in response to: MarkusD
|
|
|
David will correct me if I'm wrong, but I believe that when the message refers to reading metadata, that doesn't mean just embedded metadata, like EXIF and XMP. It also means all the other ancillary data you have entered for images and folders - titles, comments, keywords, etc.
I suspect that if you had projects that had only brief, concise titles, you would not see the message about reading metadata. My family album has over 6000 objects (mostly JPG's, but a lot of videos, as well), in about 50 folders, and I have never seen a message about "reading metadata." If it happens, it flickers by so quickly, there isn't even time to read it.
|
|
|
Posts:
3,622
Registered:
18-Oct-2002
|
|
|
Re: Faster image reading and writing with jpeg-turbo
Posted:
7 Jan 25, 23:30
in response to: MarkusD
|
|
|
Markus, I understand your point of view. Usage varies between users and in your case, you'd benefit from having metadata reading optimized. Can you please open the system console after that long album build and issue Profiler.instance, then copy and paste the result here.
|
|
|
Posts:
3,622
Registered:
18-Oct-2002
|
|
|
Re: Faster image reading and writing with jpeg-turbo
Posted:
7 Jan 25, 23:32
in response to: JeffTucker
|
|
|
David will correct me if I'm wrong, but I believe that when the message refers to reading metadata, that doesn't mean just embedded metadata, like EXIF and XMP. It also means all the other ancillary data you have entered for images and folders - titles, comments, keywords, etc.
I suspect that if you had projects that had only brief, concise titles, you would not see the message about reading metadata. My family album has over 6000 objects (mostly JPG's, but a lot of videos, as well), in about 50 folders, and I have never seen a message about "reading metadata." If it happens, it flickers by so quickly, there isn't even time to read it.
I believe it refers to all metadata, but the VAST majority of time is done unpacking EXIF and xmp metadata from the large images. I guess a good improvement would be to detect if an image hasn't been touched and instead grab the metadata from the already generated .json files... That would speed up these kinds of album updates significantly
|
|
|
Posts:
8,435
Registered:
31-Jan-2006
|
|
|
Re: Faster image reading and writing with jpeg-turbo
Posted:
8 Jan 25, 01:07
in response to: davidekholm
|
|
|
That still leaves me head-scratching a bit about why I've never noticed this message. Could it be because I'm not using any JSON-based skins? Does generating those files account for the overhead?
ETA: Just as a point of comparison, if I add a few images to my big family album and hit Make Album (letting it process all subdirectories), the process finishes in well under one minute.
|
|
|
|
Legend
|
|
Forum admins
|
|
Helpful Answer
|
|
Correct Answer
|
|