LocalizedFontProcessor extremely poor performance #7351
Comments
|
There are 3 nested foreach in one of the method in LocalizedFontProcessor.cs :) That's why. It's an easy fix. Would like to help, but my C# is rusty. |
|
CharacterCollection (which pretty much just wraps a list, nothing else) uses a List instead of a HashSet. |
|
So I taken a deeper look at LocalizedFontProcessor.cs . It would make more sense to cache the content of .resx file in a HashSet of XMLDocuments, instead of constructing new XMLDocuments in foreach loop, whenever "Process" method is called. So instead of O(n3), we get O(n2) time complexity with O(n) space. What do you think @tomspilman ? |
|
Actually i think for me the hot-path was trying to place a sprite for each glyph doing a linear loop of every other sprite in the sheet to test for overlap/collision, and then offsetting by a single pixel and repeating -- this gets very very slow when you have thousands of glyphs. The optimizations i had in mind are ...
|
|
Any optimization would be welcome here. Have you run a profiler over this? I would definitely assume |
|
This is a rectangle packing problem. Here's a great paper on it: http://pds25.egloos.com/pds/201504/21/98/RectangleBinPack.pdf. A good algorithm for this problem is called MaxRects. I have a C# port of it here. Feel free to copy and adapt it as required. |
|
The next improvement would be recognizing missing glyphs and skipping them/reusing one "missing glyph" for every other. |
|
What's the performance difference? If you want a really huge .resx example i could email you one privately. Also, you might want to check if the new algorithm is deterministic. That is, if you run it with the same inputs a second time, it outputs the same (read: identical) sprite sheet. That's important for games that version assets, ship patches, etc. |
|
The performance on my 1120 char sample was 33x faster though it may be a slightly less efficient at packing. |
|
@TechnologicalPizza My email is visible on my account, but yours is not, can you contact me? |
|
And the PR #7464 is practically done, now it's just to wait for review. |
|
I took a shot at this problem and came up with a near linear time and space Glyph packer. It follows the kiss principal. You can find the branch here: develop...stromkos:GlyphPackerImprovements I am sure it is not as tightly packed as other implementations, and may be slower on smaller glyph counts: the above range took 539ms compared to 287ms(Stock 3.8). It does two passes the first to calculate the output size (512 x ???) and the second is to place using the square root of the calculated size as width. All of the drawbacks above notwithstanding, this code produced a spritefont XNB file containing all 41354 unique glyphs in The change to Texture2D.cs allows loading of compressed files up to 168384 x 16383 (Assuming 16 to 1 compression ratio like DXT3). The test range from previous posts: [32..126] and [19968..20992] Stock: Arial 12 200785, 5.2288785 512 x 288 |








LocalizedFontProcessor tends to have a very large number of glyphs, and its performance tanks terribly as the number increases. Actually I believe what needs to be optimized is the glyph arrangement algorithm in the base type FontDescriptionProcessor, which currently has performance like or worse than N^N.
What version of MonoGame does the bug occur on:
What operating system are you using:
What MonoGame platform are you using:
The text was updated successfully, but these errors were encountered: