Time per atlas
Median wall-clock time of one complete size search. Logarithmic scale; shorter is faster.
Benchmarks
Four comparisons on the same machine and the same inputs: choosing an atlas size, inserting into the same fixed bin, inserting into a search-selected square for each packer, and writing pixels into an atlas. Size-search charts show time alongside packing density.
1 · Atlas size search
Each library receives the rectangles and chooses the atlas size itself. Where a library takes a size limit it is 16,384 px per side; rotation is off. Occupancy is the rectangle area divided by the bounding box of all placements. Tedd.RectanglePacker is shown at several efforts and thread counts.
Median wall-clock time of one complete size search. Logarithmic scale; shorter is faster.
Share of the atlas not covered by rectangles. Linear scale; shorter is denser. Rows are in the same order as the time chart.
| Library | Configuration | Median time | Atlas | Occupancy | Allocated per call |
|---|---|---|---|---|---|
| Tedd.RectanglePacker | Skyline Fast · 1 thread | 343 µsmiddle 50%: 327 µs–353 µs | 2,157 × 2,321 | 92.86 % | 32 B |
| Tedd.RectanglePacker | MaxRects Fast · 1 thread | 384 µsmiddle 50%: 368 µs–406 µs | 2,157 × 2,183 | 98.73 % | 32 B |
| Tedd.RectanglePacker | MaxRects Balanced · 32 threads | 3.65 msmiddle 50%: 3.62 ms–3.67 ms | 1,833 × 2,567 | 98.80 % | 3 B |
| Tedd.RectanglePacker | Skyline Balanced · 32 threads | 6.44 msmiddle 50%: 6.36 ms–6.49 ms | 3,235 × 1,520 | 94.55 % | 8 B |
| RectpackSharp | FindBest · 1.2.0 · 1 thread | 11.9 msmiddle 50%: 11.1 ms–13.5 ms | 2,205 × 2,204 | 95.66 % | 48.8 KiB |
| SimulationTree.BinPacker | RecursivePacker FindBest (16384 cap) · 0.3.9 · 1 thread | 12.0 msmiddle 50%: 11.5 ms–12.8 ms | 2,205 × 2,204 | 95.66 % | 47.8 KiB |
| Tedd.RectanglePacker | MaxRects Balanced · 1 thread | 20.3 msmiddle 50%: 19.7 ms–20.7 ms | 1,833 × 2,567 | 98.80 % | 2 B |
| GoldMeridian.RectPack | rectpack2D best packing · 1.0.0 · 1 thread | 28.7 msmiddle 50%: 28.1 ms–29.8 ms | 2,187 × 2,253 | 94.35 % | 4 B |
| Tedd.RectanglePacker | MaxRects Thorough · 32 threads | 685 msmiddle 50%: 680 ms–692 ms | 1,725 × 2,723 | 98.98 % | 165 B |
| ManaBattery.MB.RectangleBinPack | TextureBinPacker · 0.0.4 · 1 thread | 18.52 s1 sample | 2,188 × 2,187 | 97.16 % | 3.2 MiB |
| RectanglePacker | MapperOptimalEfficiency · 1.1.0 · 1 thread | Failed: IndexOutOfRangeException: Index was outside the bounds of the array. | |||
Median wall-clock time of one complete size search. Logarithmic scale; shorter is faster.
Share of the atlas not covered by rectangles. Linear scale; shorter is denser. Rows are in the same order as the time chart.
| Library | Configuration | Median time | Atlas | Occupancy | Allocated per call |
|---|---|---|---|---|---|
| Tedd.RectanglePacker | MaxRects Fast · 1 thread | 251 µsmiddle 50%: 229 µs–272 µs | 931 × 937 | 99.18 % | 32 B |
| Tedd.RectanglePacker | Skyline Fast · 1 thread | 258 µsmiddle 50%: 252 µs–261 µs | 931 × 957 | 97.11 % | 32 B |
| Tedd.RectanglePacker | MaxRects Balanced · 32 threads | 8.95 msmiddle 50%: 8.88 ms–9.05 ms | 1,210 × 720 | 99.31 % | 8 B |
| Tedd.RectanglePacker | Skyline Balanced · 32 threads | 11.9 msmiddle 50%: 11.8 ms–12.0 ms | 1,396 × 626 | 99.00 % | 12 B |
| RectpackSharp | FindBest · 1.2.0 · 1 thread | 20.5 msmiddle 50%: 19.7 ms–21.0 ms | 961 × 988 | 91.12 % | 95.4 KiB |
| SimulationTree.BinPacker | RecursivePacker FindBest (16384 cap) · 0.3.9 · 1 thread | 21.8 msmiddle 50%: 21.1 ms–23.1 ms | 961 × 988 | 91.12 % | 95.1 KiB |
| Tedd.RectanglePacker | MaxRects Balanced · 1 thread | 41.9 msmiddle 50%: 40.6 ms–42.6 ms | 1,210 × 720 | 99.31 % | 3 B |
| GoldMeridian.RectPack | rectpack2D best packing · 1.0.0 · 1 thread | 69.3 msmiddle 50%: 65.9 ms–73.9 ms | 993 × 996 | 87.48 % | 4 B |
| Tedd.RectanglePacker | MaxRects Thorough · 32 threads | 104 msmiddle 50%: 102 ms–107 ms | 838 × 1,036 | 99.66 % | 2.8 KiB |
| ManaBattery.MB.RectangleBinPack | TextureBinPacker · 0.0.4 · 1 thread | Skipped: more than 1,000 rectangles (one run on 2,000 rectangles did not finish within five minutes) | |||
| RectanglePacker | MapperOptimalEfficiency · 1.1.0 · 1 thread | Failed: IndexOutOfRangeException: Index was outside the bounds of the array. | |||
Median wall-clock time of one complete size search. Logarithmic scale; shorter is faster.
Share of the atlas not covered by rectangles. Linear scale; shorter is denser. Rows are in the same order as the time chart.
| Library | Configuration | Median time | Atlas | Occupancy | Allocated per call |
|---|---|---|---|---|---|
| Tedd.RectanglePacker | Skyline Fast · 1 thread | 114 µsmiddle 50%: 112 µs–115 µs | 1,974 × 2,272 | 86.84 % | 32 B |
| Tedd.RectanglePacker | MaxRects Fast · 1 thread | 168 µsmiddle 50%: 167 µs–170 µs | 1,974 × 1,997 | 98.80 % | 32 B |
| Tedd.RectanglePacker | MaxRects Balanced · 32 threads | 1.43 msmiddle 50%: 1.30 ms–1.52 ms | 2,270 × 1,736 | 98.84 % | 1 B |
| Tedd.RectanglePacker | Skyline Balanced · 32 threads | 2.41 msmiddle 50%: 2.13 ms–2.56 ms | 2,961 × 1,438 | 91.47 % | 2 B |
| SimulationTree.BinPacker | RecursivePacker FindBest (16384 cap) · 0.3.9 · 1 thread | 3.33 msmiddle 50%: 3.30 ms–3.43 ms | 2,001 × 1,990 | 97.81 % | 23.6 KiB |
| RectpackSharp | FindBest · 1.2.0 · 1 thread | 3.44 msmiddle 50%: 3.37 ms–3.46 ms | 2,001 × 1,990 | 97.81 % | 23.9 KiB |
| Tedd.RectanglePacker | MaxRects Balanced · 1 thread | 5.96 msmiddle 50%: 5.84 ms–6.00 ms | 2,270 × 1,736 | 98.84 % | 0 B |
| GoldMeridian.RectPack | rectpack2D best packing · 1.0.0 · 1 thread | 9.61 msmiddle 50%: 8.05 ms–10.2 ms | 2,090 × 1,916 | 97.26 % | 0 B |
| Tedd.RectanglePacker | MaxRects Thorough · 32 threads | 124 msmiddle 50%: 117 ms–128 ms | 1,382 × 2,840 | 99.24 % | 5.6 KiB |
| ManaBattery.MB.RectangleBinPack | TextureBinPacker · 0.0.4 · 1 thread | 1.05 smiddle 50%: 1.04 s–1.05 s | 1,982 × 1,982 | 99.15 % | 1.1 MiB |
| RectanglePacker | MapperOptimalEfficiency · 1.1.0 · 1 thread | Failed: ArgumentException: Destination array was not long enough. Check the destination index, length, and the array's lower bounds. (Parameter 'destinationArray') | |||
Median wall-clock time of one complete size search. Logarithmic scale; shorter is faster.
Share of the atlas not covered by rectangles. Linear scale; shorter is denser. Rows are in the same order as the time chart.
| Library | Configuration | Median time | Atlas | Occupancy | Allocated per call |
|---|---|---|---|---|---|
| Tedd.RectanglePacker | Skyline Fast · 1 thread | 540 µsmiddle 50%: 534 µs–553 µs | 2,128 × 2,160 | 99.44 % | 32 B |
| Tedd.RectanglePacker | MaxRects Fast · 1 thread | 588 µsmiddle 50%: 578 µs–591 µs | 2,128 × 2,160 | 99.44 % | 32 B |
| Tedd.RectanglePacker | MaxRects Balanced · 32 threads | 1.43 msmiddle 50%: 1.39 ms–1.58 ms | 1,808 × 2,528 | 100.00 % | 1 B |
| Tedd.RectanglePacker | Skyline Balanced · 32 threads | 1.43 msmiddle 50%: 1.38 ms–1.47 ms | 1,808 × 2,528 | 100.00 % | 1 B |
| Tedd.RectanglePacker | MaxRects Balanced · 1 thread | 3.95 msmiddle 50%: 3.84 ms–4.02 ms | 1,808 × 2,528 | 100.00 % | 0 B |
| Tedd.RectanglePacker | MaxRects Thorough · 32 threads | 8.51 msmiddle 50%: 8.47 ms–8.68 ms | 1,808 × 2,528 | 100.00 % | 7 B |
| GoldMeridian.RectPack | rectpack2D best packing · 1.0.0 · 1 thread | 21.3 msmiddle 50%: 19.0 ms–23.1 ms | 2,144 × 2,144 | 99.43 % | 1 B |
| SimulationTree.BinPacker | RecursivePacker FindBest (16384 cap) · 0.3.9 · 1 thread | 43.5 msmiddle 50%: 40.1 ms–47.9 ms | 2,144 × 2,144 | 99.43 % | 196.4 KiB |
| RectpackSharp | FindBest · 1.2.0 · 1 thread | 46.4 msmiddle 50%: 43.5 ms–48.4 ms | 2,144 × 2,144 | 99.43 % | 198.8 KiB |
| ManaBattery.MB.RectangleBinPack | TextureBinPacker · 0.0.4 · 1 thread | Skipped: more than 1,000 rectangles (one run on 2,000 rectangles did not finish within five minutes) | |||
| RectanglePacker | MapperOptimalEfficiency · 1.1.0 · 1 thread | Failed: IndexOutOfRangeException: Index was outside the bounds of the array. | |||
Median wall-clock time of one complete size search. Logarithmic scale; shorter is faster.
Share of the atlas not covered by rectangles. Linear scale; shorter is denser. Rows are in the same order as the time chart.
| Library | Configuration | Median time | Atlas | Occupancy | Allocated per call |
|---|---|---|---|---|---|
| Tedd.RectanglePacker | Skyline Fast · 1 thread | 1.74 msmiddle 50%: 1.66 ms–1.78 ms | 3,421 × 3,448 | 99.18 % | 32 B |
| Tedd.RectanglePacker | MaxRects Fast · 1 thread | 1.79 msmiddle 50%: 1.72 ms–1.90 ms | 3,421 × 3,422 | 99.93 % | 32 B |
| Tedd.RectanglePacker | MaxRects Balanced · 32 threads | 58.7 msmiddle 50%: 58.6 ms–59.7 ms | 3,421 × 3,422 | 99.93 % | 48 B |
| Tedd.RectanglePacker | Skyline Balanced · 32 threads | 177 msmiddle 50%: 168 ms–183 ms | 5,131 × 2,291 | 99.52 % | 96 B |
| Tedd.RectanglePacker | MaxRects Balanced · 1 thread | 348 msmiddle 50%: 343 ms–350 ms | 3,421 × 3,422 | 99.93 % | 9 B |
| RectpackSharp | FindBest · 1.2.0 · 1 thread | 621 msmiddle 50%: 588 ms–629 ms | 3,443 × 3,444 | 98.66 % | 500.4 KiB |
| SimulationTree.BinPacker | RecursivePacker FindBest (16384 cap) · 0.3.9 · 1 thread | 664 msmiddle 50%: 659 ms–684 ms | 3,443 × 3,444 | 98.66 % | 500.1 KiB |
| Tedd.RectanglePacker | MaxRects Thorough · 32 threads | 1.96 smiddle 50%: 1.95 s–1.96 s | 5,986 × 1,955 | 99.97 % | 262.5 KiB |
| GoldMeridian.RectPack | rectpack2D best packing · 1.0.0 · 1 thread | 1.98 smiddle 50%: 1.92 s–2.00 s | 3,499 × 3,500 | 95.53 % | 16 B |
| ManaBattery.MB.RectangleBinPack | TextureBinPacker · 0.0.4 · 1 thread | Skipped: more than 1,000 rectangles (one run on 2,000 rectangles did not finish within five minutes) | |||
| RectanglePacker | MapperOptimalEfficiency · 1.1.0 · 1 thread | Failed: IndexOutOfRangeException: Index was outside the bounds of the array. | |||
2 · Common fixed bin
Every packer receives the same sequence, sorted by descending height
then width, and the same square side: the greater of the largest
input dimension and ceil(sqrt(total area) × 1.25).
One complete insertion pass is timed. Failures remain visible;
occupancy is constant for successful packers on each dataset.
One insertion pass into a 2,696 × 2,696 square for every packer. Median wall-clock time; logarithmic scale; shorter is faster.
| Library | Configuration | Median time | Square side | Occupancy | Allocated per call |
|---|---|---|---|---|---|
| AtlasAllocator | ShelfAtlasAllocator · 1.0.1 · 1 thread | 91 µsmiddle 50%: 86 µs–99 µs | 2,696 | 63.96 % | 0 B |
| Tedd.RectanglePacker | MaxRects BottomLeft · 1 thread | 275 µsmiddle 50%: 266 µs–297 µs | 2,696 | 63.96 % | 0 B |
| Tedd.RectanglePacker | Skyline BottomLeft · 1 thread | 289 µsmiddle 50%: 267 µs–301 µs | 2,696 | 63.96 % | 0 B |
| RectPacker2 | Packer · 2.1.0 · 1 thread | 509 µsmiddle 50%: 449 µs–519 µs | 2,696 | 63.96 % | 16.2 KiB |
| Tedd.RectanglePacker | MaxRects BestShortSideFit · 1 thread | 573 µsmiddle 50%: 536 µs–677 µs | 2,696 | 63.96 % | 0 B |
| AtlasAllocator | GuillotineAtlasAllocator · 1.0.1 · 1 thread | 1.69 msmiddle 50%: 1.46 ms–1.78 ms | 2,696 | 63.96 % | 0 B |
| Tedd.RectanglePacker | Skyline MinWaste · 1 thread | 2.36 msmiddle 50%: 2.08 ms–2.46 ms | 2,696 | 63.96 % | 0 B |
| RectangleBinPacking | MaxRects BestShortSideFit (new bin) · 1.0.2 · 1 thread | 3.07 msmiddle 50%: 2.78 ms–3.29 ms | 2,696 | 63.96 % | 186.7 KiB |
| StbRectPackSharp | stbrp_pack_rects (skyline) · 1.0.4 · 1 thread | 4.95 msmiddle 50%: 4.92 ms–5.37 ms | 2,696 | 63.96 % | 112 B |
| RectangleBinPack.CSharp | Guillotine BestAreaFit, MinimizeArea · 1.0.4 · 1 thread | 26.7 msmiddle 50%: 24.9 ms–30.2 ms | 2,696 | 63.96 % | 2 B |
| ManaBattery.MB.RectangleBinPack | MaxRects BestShortSideFit · 0.0.4 · 1 thread | 525 msmiddle 50%: 504 ms–532 ms | 2,696 | 63.96 % | 9 B |
| RectangleBinPack.CSharp | MaxRects BestShortSideFit · 1.0.4 · 1 thread | 567 msmiddle 50%: 540 ms–574 ms | 2,696 | 63.96 % | 9 B |
| RectangleBinPack.CSharp | Skyline BottomLeft · 1.0.4 · 1 thread | Skipped: SkylineBinPack always considers rotated placements; no option disables it | |||
| GoldMeridian.RectPack | EmptySpaces (rectpack2D) · 1.0.0 · 1 thread | Failed: PackingFailedException: Input 962 did not fit. | |||
One insertion pass into a 1,163 × 1,163 square for every packer. Median wall-clock time; logarithmic scale; shorter is faster.
| Library | Configuration | Median time | Square side | Occupancy | Allocated per call |
|---|---|---|---|---|---|
| GoldMeridian.RectPack | EmptySpaces (rectpack2D) · 1.0.0 · 1 thread | 45 µsmiddle 50%: 40 µs–47 µs | 1,163 | 63.97 % | 0 B |
| Tedd.RectanglePacker | Skyline BottomLeft · 1 thread | 91 µsmiddle 50%: 89 µs–112 µs | 1,163 | 63.97 % | 0 B |
| Tedd.RectanglePacker | MaxRects BottomLeft · 1 thread | 164 µsmiddle 50%: 151 µs–178 µs | 1,163 | 63.97 % | 0 B |
| RectPacker2 | Packer · 2.1.0 · 1 thread | 169 µsmiddle 50%: 158 µs–184 µs | 1,163 | 63.97 % | 2.1 KiB |
| AtlasAllocator | ShelfAtlasAllocator · 1.0.1 · 1 thread | 188 µsmiddle 50%: 174 µs–199 µs | 1,163 | 63.97 % | 0 B |
| Tedd.RectanglePacker | Skyline MinWaste · 1 thread | 293 µsmiddle 50%: 260 µs–330 µs | 1,163 | 63.97 % | 0 B |
| Tedd.RectanglePacker | MaxRects BestShortSideFit · 1 thread | 1.32 msmiddle 50%: 1.20 ms–1.44 ms | 1,163 | 63.97 % | 0 B |
| AtlasAllocator | GuillotineAtlasAllocator · 1.0.1 · 1 thread | 2.78 msmiddle 50%: 2.54 ms–2.95 ms | 1,163 | 63.97 % | 0 B |
| RectangleBinPack.CSharp | Guillotine BestAreaFit, MinimizeArea · 1.0.4 · 1 thread | 3.49 msmiddle 50%: 3.30 ms–3.59 ms | 1,163 | 63.97 % | 0 B |
| RectangleBinPacking | MaxRects BestShortSideFit (new bin) · 1.0.2 · 1 thread | 10.9 msmiddle 50%: 10.4 ms–11.2 ms | 1,163 | 63.97 % | 359.0 KiB |
| StbRectPackSharp | stbrp_pack_rects (skyline) · 1.0.4 · 1 thread | 13.3 msmiddle 50%: 12.6 ms–13.6 ms | 1,163 | 63.97 % | 113 B |
| ManaBattery.MB.RectangleBinPack | MaxRects BestShortSideFit · 0.0.4 · 1 thread | 1.14 smiddle 50%: 1.13 s–1.15 s | 1,163 | 63.97 % | 16 B |
| RectangleBinPack.CSharp | MaxRects BestShortSideFit · 1.0.4 · 1 thread | 1.17 smiddle 50%: 1.16 s–1.19 s | 1,163 | 63.97 % | 16 B |
| RectangleBinPack.CSharp | Skyline BottomLeft · 1.0.4 · 1 thread | Skipped: SkylineBinPack always considers rotated placements; no option disables it | |||
One insertion pass into a 2,467 × 2,467 square for every packer. Median wall-clock time; logarithmic scale; shorter is faster.
| Library | Configuration | Median time | Square side | Occupancy | Allocated per call |
|---|---|---|---|---|---|
| AtlasAllocator | ShelfAtlasAllocator · 1.0.1 · 1 thread | 43 µsmiddle 50%: 40 µs–44 µs | 2,467 | 64.00 % | 0 B |
| Tedd.RectanglePacker | Skyline BottomLeft · 1 thread | 111 µsmiddle 50%: 110 µs–113 µs | 2,467 | 64.00 % | 0 B |
| Tedd.RectanglePacker | MaxRects BestShortSideFit · 1 thread | 130 µsmiddle 50%: 115 µs–137 µs | 2,467 | 64.00 % | 0 B |
| Tedd.RectanglePacker | MaxRects BottomLeft · 1 thread | 152 µsmiddle 50%: 147 µs–156 µs | 2,467 | 64.00 % | 0 B |
| RectPacker2 | Packer · 2.1.0 · 1 thread | 181 µsmiddle 50%: 172 µs–184 µs | 2,467 | 64.00 % | 8.1 KiB |
| AtlasAllocator | GuillotineAtlasAllocator · 1.0.1 · 1 thread | 346 µsmiddle 50%: 323 µs–352 µs | 2,467 | 64.00 % | 0 B |
| Tedd.RectanglePacker | Skyline MinWaste · 1 thread | 837 µsmiddle 50%: 835 µs–839 µs | 2,467 | 64.00 % | 0 B |
| StbRectPackSharp | stbrp_pack_rects (skyline) · 1.0.4 · 1 thread | 1.39 msmiddle 50%: 1.24 ms–1.45 ms | 2,467 | 64.00 % | 112 B |
| ManaBattery.MB.RectangleBinPack | MaxRects BestShortSideFit · 0.0.4 · 1 thread | 38.1 msmiddle 50%: 36.1 ms–40.5 ms | 2,467 | 64.00 % | 3 B |
| RectangleBinPack.CSharp | MaxRects BestShortSideFit · 1.0.4 · 1 thread | 50.6 msmiddle 50%: 48.9 ms–51.2 ms | 2,467 | 64.00 % | 4 B |
| RectangleBinPacking | MaxRects BestShortSideFit (new bin) · 1.0.2 · 1 thread | Failed: PackingFailedException: Insert returned no placement. | |||
| RectangleBinPack.CSharp | Skyline BottomLeft · 1.0.4 · 1 thread | Skipped: SkylineBinPack always considers rotated placements; no option disables it | |||
| RectangleBinPack.CSharp | Guillotine BestAreaFit, MinimizeArea · 1.0.4 · 1 thread | Failed: PackingFailedException: Input 37 did not fit. | |||
| GoldMeridian.RectPack | EmptySpaces (rectpack2D) · 1.0.0 · 1 thread | Failed: PackingFailedException: Input 263 did not fit. | |||
One insertion pass into a 2,673 × 2,673 square for every packer. Median wall-clock time; logarithmic scale; shorter is faster.
| Library | Configuration | Median time | Square side | Occupancy | Allocated per call |
|---|---|---|---|---|---|
| GoldMeridian.RectPack | EmptySpaces (rectpack2D) · 1.0.0 · 1 thread | 74 µsmiddle 50%: 74 µs–76 µs | 2,673 | 63.97 % | 0 B |
| RectangleBinPack.CSharp | Guillotine BestAreaFit, MinimizeArea · 1.0.4 · 1 thread | 125 µsmiddle 50%: 113 µs–140 µs | 2,673 | 63.97 % | 0 B |
| Tedd.RectanglePacker | Skyline BottomLeft · 1 thread | 218 µsmiddle 50%: 173 µs–226 µs | 2,673 | 63.97 % | 0 B |
| Tedd.RectanglePacker | Skyline MinWaste · 1 thread | 249 µsmiddle 50%: 233 µs–271 µs | 2,673 | 63.97 % | 0 B |
| Tedd.RectanglePacker | MaxRects BestShortSideFit · 1 thread | 272 µsmiddle 50%: 254 µs–294 µs | 2,673 | 63.97 % | 0 B |
| Tedd.RectanglePacker | MaxRects BottomLeft · 1 thread | 302 µsmiddle 50%: 261 µs–322 µs | 2,673 | 63.97 % | 0 B |
| RectangleBinPack.CSharp | MaxRects BestShortSideFit · 1.0.4 · 1 thread | 477 µsmiddle 50%: 448 µs–549 µs | 2,673 | 63.97 % | 0 B |
| RectPacker2 | Packer · 2.1.0 · 1 thread | 581 µsmiddle 50%: 574 µs–610 µs | 2,673 | 63.97 % | 2.1 KiB |
| ManaBattery.MB.RectangleBinPack | MaxRects BestShortSideFit · 0.0.4 · 1 thread | 587 µsmiddle 50%: 558 µs–606 µs | 2,673 | 63.97 % | 0 B |
| AtlasAllocator | ShelfAtlasAllocator · 1.0.1 · 1 thread | 639 µsmiddle 50%: 632 µs–644 µs | 2,673 | 63.97 % | 0 B |
| AtlasAllocator | GuillotineAtlasAllocator · 1.0.1 · 1 thread | 1.91 msmiddle 50%: 1.89 ms–1.92 ms | 2,673 | 63.97 % | 0 B |
| StbRectPackSharp | stbrp_pack_rects (skyline) · 1.0.4 · 1 thread | 3.84 msmiddle 50%: 3.80 ms–3.88 ms | 2,673 | 63.97 % | 112 B |
| RectangleBinPacking | MaxRects BestShortSideFit (new bin) · 1.0.2 · 1 thread | 43.8 msmiddle 50%: 41.8 ms–46.8 ms | 2,673 | 63.97 % | 830.7 KiB |
| RectangleBinPack.CSharp | Skyline BottomLeft · 1.0.4 · 1 thread | Skipped: SkylineBinPack always considers rotated placements; no option disables it | |||
One insertion pass into a 4,276 × 4,276 square for every packer. Median wall-clock time; logarithmic scale; shorter is faster.
| Library | Configuration | Median time | Square side | Occupancy | Allocated per call |
|---|---|---|---|---|---|
| GoldMeridian.RectPack | EmptySpaces (rectpack2D) · 1.0.0 · 1 thread | 237 µsmiddle 50%: 226 µs–244 µs | 4,276 | 63.98 % | 0 B |
| Tedd.RectanglePacker | Skyline BottomLeft · 1 thread | 588 µsmiddle 50%: 568 µs–652 µs | 4,276 | 63.98 % | 0 B |
| Tedd.RectanglePacker | MaxRects BottomLeft · 1 thread | 1.07 msmiddle 50%: 1.06 ms–1.08 ms | 4,276 | 63.98 % | 0 B |
| AtlasAllocator | ShelfAtlasAllocator · 1.0.1 · 1 thread | 1.70 msmiddle 50%: 1.67 ms–1.76 ms | 4,276 | 63.98 % | 0 B |
| RectPacker2 | Packer · 2.1.0 · 1 thread | 2.14 msmiddle 50%: 2.09 ms–2.19 ms | 4,276 | 63.98 % | 4.1 KiB |
| Tedd.RectanglePacker | Skyline MinWaste · 1 thread | 8.66 msmiddle 50%: 8.15 ms–8.86 ms | 4,276 | 63.98 % | 0 B |
| Tedd.RectanglePacker | MaxRects BestShortSideFit · 1 thread | 19.8 msmiddle 50%: 19.3 ms–19.9 ms | 4,276 | 63.98 % | 1 B |
| AtlasAllocator | GuillotineAtlasAllocator · 1.0.1 · 1 thread | 40.3 msmiddle 50%: 38.1 ms–41.3 ms | 4,276 | 63.98 % | 3 B |
| RectangleBinPacking | MaxRects BestShortSideFit (new bin) · 1.0.2 · 1 thread | 274 msmiddle 50%: 260 ms–291 ms | 4,276 | 63.98 % | 1.9 MiB |
| StbRectPackSharp | stbrp_pack_rects (skyline) · 1.0.4 · 1 thread | 352 msmiddle 50%: 344 ms–371 ms | 4,276 | 63.98 % | 121 B |
| RectangleBinPack.CSharp | Guillotine BestAreaFit, MinimizeArea · 1.0.4 · 1 thread | 1.89 smiddle 50%: 1.85 s–1.90 s | 4,276 | 63.98 % | 16 B |
| RectangleBinPack.CSharp | MaxRects BestShortSideFit · 1.0.4 · 1 thread | Skipped: more than 4,096 rectangles (one pass over 2,000 rectangles takes over a second, and the bisection needs a dozen passes) | |||
| RectangleBinPack.CSharp | Skyline BottomLeft · 1.0.4 · 1 thread | Skipped: SkylineBinPack always considers rotated placements; no option disables it | |||
| ManaBattery.MB.RectangleBinPack | MaxRects BestShortSideFit · 0.0.4 · 1 thread | Skipped: more than 4,096 rectangles (one pass over 2,000 rectangles takes over a second, and the bisection needs a dozen passes) | |||
3 · Square search
An untimed growth search and bisection select a successful square for each packer. Greedy packing success need not be monotone in bin size, so this does not establish a global minimum. One insertion pass into that selected square is timed. Bin sizes and insertion difficulty differ; compare density alongside time.
One insertion pass into each packer's search-selected square. Bin sizes differ; logarithmic scale; shorter is faster.
Share of the atlas not covered by rectangles. Linear scale; shorter is denser. Rows are in the same order as the time chart.
| Library | Configuration | Median time | Square side | Occupancy | Allocated per call |
|---|---|---|---|---|---|
| GoldMeridian.RectPack | EmptySpaces (rectpack2D) · 1.0.0 · 1 thread | 20 µsmiddle 50%: 17 µs–23 µs | 2,736 | 62.11 % | 0 B |
| AtlasAllocator | ShelfAtlasAllocator · 1.0.1 · 1 thread | 100 µsmiddle 50%: 98 µs–105 µs | 2,304 | 87.58 % | 0 B |
| Tedd.RectanglePacker | Skyline BottomLeft · 1 thread | 268 µsmiddle 50%: 247 µs–275 µs | 2,223 | 94.08 % | 0 B |
| Tedd.RectanglePacker | MaxRects BottomLeft · 1 thread | 311 µsmiddle 50%: 297 µs–326 µs | 2,169 | 98.82 % | 0 B |
| RectPacker2 | Packer · 2.1.0 · 1 thread | 527 µsmiddle 50%: 507 µs–563 µs | 2,310 | 87.12 % | 16.2 KiB |
| Tedd.RectanglePacker | MaxRects BestShortSideFit · 1 thread | 765 µsmiddle 50%: 724 µs–784 µs | 2,197 | 96.32 % | 0 B |
| AtlasAllocator | GuillotineAtlasAllocator · 1.0.1 · 1 thread | 1.41 msmiddle 50%: 1.36 ms–1.44 ms | 2,183 | 97.56 % | 0 B |
| Tedd.RectanglePacker | Skyline MinWaste · 1 thread | 2.21 msmiddle 50%: 2.11 ms–2.27 ms | 2,568 | 70.50 % | 0 B |
| RectangleBinPacking | MaxRects BestShortSideFit (new bin) · 1.0.2 · 1 thread | 3.81 msmiddle 50%: 3.63 ms–3.91 ms | 2,235 | 93.07 % | 187.2 KiB |
| StbRectPackSharp | stbrp_pack_rects (skyline) · 1.0.4 · 1 thread | 5.14 msmiddle 50%: 5.00 ms–5.22 ms | 2,194 | 96.58 % | 112 B |
| RectangleBinPack.CSharp | Guillotine BestAreaFit, MinimizeArea · 1.0.4 · 1 thread | 12.6 msmiddle 50%: 12.3 ms–13.0 ms | 2,192 | 96.76 % | 1 B |
| ManaBattery.MB.RectangleBinPack | MaxRects BestShortSideFit · 0.0.4 · 1 thread | 583 msmiddle 50%: 571 ms–596 ms | 2,197 | 96.32 % | 9 B |
| RectangleBinPack.CSharp | MaxRects BestShortSideFit · 1.0.4 · 1 thread | 640 msmiddle 50%: 630 ms–655 ms | 2,197 | 96.32 % | 9 B |
| RectangleBinPack.CSharp | Skyline BottomLeft · 1.0.4 · 1 thread | Skipped: SkylineBinPack always considers rotated placements; no option disables it | |||
One insertion pass into each packer's search-selected square. Bin sizes differ; logarithmic scale; shorter is faster.
Share of the atlas not covered by rectangles. Linear scale; shorter is denser. Rows are in the same order as the time chart.
| Library | Configuration | Median time | Square side | Occupancy | Allocated per call |
|---|---|---|---|---|---|
| GoldMeridian.RectPack | EmptySpaces (rectpack2D) · 1.0.0 · 1 thread | 52 µsmiddle 50%: 52 µs–52 µs | 975 | 91.01 % | 0 B |
| Tedd.RectanglePacker | Skyline BottomLeft · 1 thread | 125 µsmiddle 50%: 116 µs–133 µs | 939 | 98.12 % | 0 B |
| RectPacker2 | Packer · 2.1.0 · 1 thread | 146 µsmiddle 50%: 145 µs–146 µs | 939 | 98.12 % | 4.1 KiB |
| AtlasAllocator | ShelfAtlasAllocator · 1.0.1 · 1 thread | 164 µsmiddle 50%: 164 µs–164 µs | 1,000 | 86.52 % | 0 B |
| Tedd.RectanglePacker | MaxRects BottomLeft · 1 thread | 198 µsmiddle 50%: 191 µs–203 µs | 935 | 98.97 % | 0 B |
| Tedd.RectanglePacker | Skyline MinWaste · 1 thread | 397 µsmiddle 50%: 355 µs–411 µs | 942 | 97.50 % | 0 B |
| RectangleBinPack.CSharp | Guillotine BestAreaFit, MinimizeArea · 1.0.4 · 1 thread | 1.15 msmiddle 50%: 1.11 ms–1.20 ms | 939 | 98.12 % | 0 B |
| Tedd.RectanglePacker | MaxRects BestShortSideFit · 1 thread | 1.51 msmiddle 50%: 1.43 ms–1.54 ms | 952 | 95.46 % | 0 B |
| AtlasAllocator | GuillotineAtlasAllocator · 1.0.1 · 1 thread | 3.20 msmiddle 50%: 3.10 ms–3.28 ms | 950 | 95.86 % | 0 B |
| StbRectPackSharp | stbrp_pack_rects (skyline) · 1.0.4 · 1 thread | 9.47 msmiddle 50%: 9.25 ms–9.71 ms | 938 | 98.33 % | 112 B |
| RectangleBinPacking | MaxRects BestShortSideFit (new bin) · 1.0.2 · 1 thread | 10.1 msmiddle 50%: 9.65 ms–11.0 ms | 975 | 91.01 % | 359.5 KiB |
| ManaBattery.MB.RectangleBinPack | MaxRects BestShortSideFit · 0.0.4 · 1 thread | 885 msmiddle 50%: 833 ms–1.09 s | 952 | 95.46 % | 9 B |
| RectangleBinPack.CSharp | MaxRects BestShortSideFit · 1.0.4 · 1 thread | 1.20 smiddle 50%: 1.18 s–1.21 s | 952 | 95.46 % | 16 B |
| RectangleBinPack.CSharp | Skyline BottomLeft · 1.0.4 · 1 thread | Skipped: SkylineBinPack always considers rotated placements; no option disables it | |||
One insertion pass into each packer's search-selected square. Bin sizes differ; logarithmic scale; shorter is faster.
Share of the atlas not covered by rectangles. Linear scale; shorter is denser. Rows are in the same order as the time chart.
| Library | Configuration | Median time | Square side | Occupancy | Allocated per call |
|---|---|---|---|---|---|
| GoldMeridian.RectPack | EmptySpaces (rectpack2D) · 1.0.0 · 1 thread | 9 µsmiddle 50%: 9 µs–9 µs | 2,631 | 56.27 % | 0 B |
| AtlasAllocator | ShelfAtlasAllocator · 1.0.1 · 1 thread | 37 µsmiddle 50%: 37 µs–37 µs | 2,140 | 85.05 % | 0 B |
| Tedd.RectanglePacker | Skyline BottomLeft · 1 thread | 51 µsmiddle 50%: 51 µs–52 µs | 2,122 | 86.50 % | 0 B |
| Tedd.RectanglePacker | MaxRects BottomLeft · 1 thread | 94 µsmiddle 50%: 94 µs–94 µs | 1,985 | 98.85 % | 0 B |
| Tedd.RectanglePacker | MaxRects BestShortSideFit · 1 thread | 98 µsmiddle 50%: 97 µs–98 µs | 1,986 | 98.75 % | 0 B |
| RectPacker2 | Packer · 2.1.0 · 1 thread | 124 µsmiddle 50%: 123 µs–124 µs | 2,370 | 69.34 % | 8.1 KiB |
| AtlasAllocator | GuillotineAtlasAllocator · 1.0.1 · 1 thread | 193 µsmiddle 50%: 192 µs–193 µs | 2,096 | 88.66 % | 0 B |
| Tedd.RectanglePacker | Skyline MinWaste · 1 thread | 388 µsmiddle 50%: 387 µs–388 µs | 2,248 | 77.07 % | 0 B |
| RectangleBinPacking | MaxRects BestShortSideFit (new bin) · 1.0.2 · 1 thread | 580 µsmiddle 50%: 579 µs–584 µs | 2,870 | 47.29 % | 91.2 KiB |
| StbRectPackSharp | stbrp_pack_rects (skyline) · 1.0.4 · 1 thread | 1.03 msmiddle 50%: 984 µs–1.05 ms | 2,112 | 87.32 % | 112 B |
| RectangleBinPack.CSharp | Guillotine BestAreaFit, MinimizeArea · 1.0.4 · 1 thread | 23.8 msmiddle 50%: 23.7 ms–23.8 ms | 3,390 | 33.89 % | 1 B |
| ManaBattery.MB.RectangleBinPack | MaxRects BestShortSideFit · 0.0.4 · 1 thread | 32.7 msmiddle 50%: 32.6 ms–32.7 ms | 1,986 | 98.75 % | 2 B |
| RectangleBinPack.CSharp | MaxRects BestShortSideFit · 1.0.4 · 1 thread | 35.7 msmiddle 50%: 35.3 ms–38.0 ms | 1,986 | 98.75 % | 3 B |
| RectangleBinPack.CSharp | Skyline BottomLeft · 1.0.4 · 1 thread | Skipped: SkylineBinPack always considers rotated placements; no option disables it | |||
One insertion pass into each packer's search-selected square. Bin sizes differ; logarithmic scale; shorter is faster.
Share of the atlas not covered by rectangles. Linear scale; shorter is denser. Rows are in the same order as the time chart.
| Library | Configuration | Median time | Square side | Occupancy | Allocated per call |
|---|---|---|---|---|---|
| GoldMeridian.RectPack | EmptySpaces (rectpack2D) · 1.0.0 · 1 thread | 68 µsmiddle 50%: 58 µs–73 µs | 2,144 | 99.43 % | 0 B |
| Tedd.RectanglePacker | Skyline BottomLeft · 1 thread | 91 µsmiddle 50%: 91 µs–91 µs | 2,144 | 99.43 % | 0 B |
| RectPacker2 | Packer · 2.1.0 · 1 thread | 94 µsmiddle 50%: 85 µs–96 µs | 2,144 | 99.43 % | 1.1 KiB |
| RectangleBinPack.CSharp | Guillotine BestAreaFit, MinimizeArea · 1.0.4 · 1 thread | 123 µsmiddle 50%: 113 µs–128 µs | 2,144 | 99.43 % | 0 B |
| Tedd.RectanglePacker | Skyline MinWaste · 1 thread | 156 µsmiddle 50%: 148 µs–165 µs | 2,144 | 99.43 % | 0 B |
| Tedd.RectanglePacker | MaxRects BottomLeft · 1 thread | 202 µsmiddle 50%: 201 µs–202 µs | 2,144 | 99.43 % | 0 B |
| Tedd.RectanglePacker | MaxRects BestShortSideFit · 1 thread | 215 µsmiddle 50%: 215 µs–215 µs | 2,144 | 99.43 % | 0 B |
| AtlasAllocator | GuillotineAtlasAllocator · 1.0.1 · 1 thread | 320 µsmiddle 50%: 281 µs–360 µs | 2,144 | 99.43 % | 0 B |
| RectangleBinPack.CSharp | MaxRects BestShortSideFit · 1.0.4 · 1 thread | 322 µsmiddle 50%: 280 µs–337 µs | 2,144 | 99.43 % | 0 B |
| ManaBattery.MB.RectangleBinPack | MaxRects BestShortSideFit · 0.0.4 · 1 thread | 334 µsmiddle 50%: 296 µs–349 µs | 2,144 | 99.43 % | 0 B |
| AtlasAllocator | ShelfAtlasAllocator · 1.0.1 · 1 thread | 656 µsmiddle 50%: 617 µs–723 µs | 2,160 | 97.96 % | 0 B |
| StbRectPackSharp | stbrp_pack_rects (skyline) · 1.0.4 · 1 thread | 3.21 msmiddle 50%: 3.01 ms–3.34 ms | 2,144 | 99.43 % | 112 B |
| RectangleBinPacking | MaxRects BestShortSideFit (new bin) · 1.0.2 · 1 thread | 47.6 msmiddle 50%: 42.8 ms–55.8 ms | 2,144 | 99.43 % | 830.8 KiB |
| RectangleBinPack.CSharp | Skyline BottomLeft · 1.0.4 · 1 thread | Skipped: SkylineBinPack always considers rotated placements; no option disables it | |||
One insertion pass into each packer's search-selected square. Bin sizes differ; logarithmic scale; shorter is faster.
Share of the atlas not covered by rectangles. Linear scale; shorter is denser. Rows are in the same order as the time chart.
| Library | Configuration | Median time | Square side | Occupancy | Allocated per call |
|---|---|---|---|---|---|
| GoldMeridian.RectPack | EmptySpaces (rectpack2D) · 1.0.0 · 1 thread | 466 µsmiddle 50%: 415 µs–497 µs | 3,641 | 88.25 % | 0 B |
| Tedd.RectanglePacker | Skyline BottomLeft · 1 thread | 733 µsmiddle 50%: 602 µs–774 µs | 3,436 | 99.09 % | 0 B |
| Tedd.RectanglePacker | MaxRects BottomLeft · 1 thread | 925 µsmiddle 50%: 873 µs–960 µs | 3,422 | 99.90 % | 0 B |
| RectPacker2 | Packer · 2.1.0 · 1 thread | 1.88 msmiddle 50%: 1.83 ms–2.02 ms | 3,423 | 99.84 % | 8.1 KiB |
| AtlasAllocator | ShelfAtlasAllocator · 1.0.1 · 1 thread | 1.95 msmiddle 50%: 1.85 ms–2.00 ms | 3,702 | 85.36 % | 0 B |
| Tedd.RectanglePacker | Skyline MinWaste · 1 thread | 17.1 msmiddle 50%: 16.5 ms–18.5 ms | 3,498 | 95.61 % | 1 B |
| Tedd.RectanglePacker | MaxRects BestShortSideFit · 1 thread | 24.4 msmiddle 50%: 22.7 ms–26.2 ms | 3,439 | 98.92 % | 1 B |
| RectangleBinPack.CSharp | Guillotine BestAreaFit, MinimizeArea · 1.0.4 · 1 thread | 45.0 msmiddle 50%: 42.6 ms–50.5 ms | 3,441 | 98.80 % | 3 B |
| AtlasAllocator | GuillotineAtlasAllocator · 1.0.1 · 1 thread | 48.2 msmiddle 50%: 45.0 ms–49.6 ms | 3,450 | 98.29 % | 3 B |
| RectangleBinPacking | MaxRects BestShortSideFit (new bin) · 1.0.2 · 1 thread | 283 msmiddle 50%: 268 ms–294 ms | 3,527 | 94.04 % | 1.9 MiB |
| StbRectPackSharp | stbrp_pack_rects (skyline) · 1.0.4 · 1 thread | 341 msmiddle 50%: 318 ms–389 ms | 3,429 | 99.50 % | 121 B |
| RectangleBinPack.CSharp | MaxRects BestShortSideFit · 1.0.4 · 1 thread | Skipped: more than 4,096 rectangles (one pass over 2,000 rectangles takes over a second, and the bisection needs a dozen passes) | |||
| RectangleBinPack.CSharp | Skyline BottomLeft · 1.0.4 · 1 thread | Skipped: SkylineBinPack always considers rotated placements; no option disables it | |||
| ManaBattery.MB.RectangleBinPack | MaxRects BestShortSideFit · 0.0.4 · 1 thread | Skipped: more than 4,096 rectangles (one pass over 2,000 rectangles takes over a second, and the bisection needs a dozen passes) | |||
4 · Composition
Every contender writes the same layout: RGBA32 sprites into a reused
RGBA32 atlas, clearing the background first. Every output was compared
byte for byte with the reference. The plain Span.CopyTo
row loop is a single-thread baseline, not a library.
1,833 × 2,567 RGBA32 atlas, megapixels of atlas written per second including the background. Linear scale; longer is faster.
| Library | Configuration | Median time | MP/s | Allocated per call |
|---|---|---|---|---|
| Tedd.RectanglePacker | AtlasBuilder.Compose · 32 threads | 1.94 msmiddle 50%: 1.88 ms–2.12 ms | 2,426 | 2 B |
| Tedd.RectanglePacker | AtlasBuilder.Compose · 1 thread | 3.51 msmiddle 50%: 3.33 ms–4.46 ms | 1,341 | 208 B |
| SkiaSharp | SKCanvas.DrawImage (Src) · 4.153.0 · 1 thread | 5.60 msmiddle 50%: 5.42 ms–6.28 ms | 840 | 0 B |
| Span.CopyTo loop | reference · 1 thread | 5.62 msmiddle 50%: 5.14 ms–6.50 ms | 837 | 0 B |
| SixLabors.ImageSharp | DrawImage (Src) · 3.1.12 · 1 thread | 47.9 msmiddle 50%: 44.5 ms–50.7 ms | 98 | 7.2 MiB |
2,270 × 1,736 RGBA32 atlas, megapixels of atlas written per second including the background. Linear scale; longer is faster.
| Library | Configuration | Median time | MP/s | Allocated per call |
|---|---|---|---|---|
| Tedd.RectanglePacker | AtlasBuilder.Compose · 32 threads | 1.06 msmiddle 50%: 958 µs–1.15 ms | 3,718 | 1 B |
| Tedd.RectanglePacker | AtlasBuilder.Compose · 1 thread | 2.39 msmiddle 50%: 2.27 ms–2.52 ms | 1,651 | 0 B |
| Span.CopyTo loop | reference · 1 thread | 3.64 msmiddle 50%: 3.25 ms–3.79 ms | 1,083 | 0 B |
| SkiaSharp | SKCanvas.DrawImage (Src) · 4.153.0 · 1 thread | 3.92 msmiddle 50%: 3.39 ms–4.21 ms | 1,004 | 0 B |
| SixLabors.ImageSharp | DrawImage (Src) · 3.1.12 · 1 thread | 24.0 msmiddle 50%: 23.1 ms–24.7 ms | 164 | 3.0 MiB |
Method
AMD Ryzen 9 5950X 16-Core Processor, 32 logical
processors, Microsoft Windows 10.0.26200, .NET 11.0.0-rc.1.26425.128,
X64. Measured 2026-09-30 (UTC),
library commit 37274944e775.
20260929. Every library receives identical sizes.sprites-1k): 1,000 sprites, width and height uniform in 8-128 px; total area 4,649,054 px².glyphs-2k): 2,000 font glyphs, width 4-32 px, height 16-32 px; total area 865,179 px².ui-500): 500 UI images: 400 icons of 8-64 px and 100 panels of 64-384 x 32-256 px; total area 3,894,874 px².tiles-4k): 4,096 square tiles of 16, 32 or 64 px (50/35/15 %); total area 4,570,624 px².sprites-10k): 10,000 small sprites, width and height uniform in 4-64 px; total area 11,698,731 px².Excluded or failed configurations:
glyphs-2k, tiles-4k, sprites-10k: Skipped: more than 1,000 rectangles (one run on 2,000 rectangles did not finish within five minutes)sprites-10k: Skipped: more than 4,096 rectangles (one pass over 2,000 rectangles takes over a second, and the bisection needs a dozen passes)sprites-10k: Skipped: more than 4,096 rectangles (one pass over 2,000 rectangles takes over a second, and the bisection needs a dozen passes)sprites-1k, ui-500: Failed: PackingFailedException: Input 962 did not fit. / Failed: PackingFailedException: Input 263 did not fit.ui-500: Failed: PackingFailedException: Insert returned no placement.ui-500: Failed: PackingFailedException: Input 37 did not fit.Raw CSV files, per-sample timing JSON, the environment record and the measured layouts are in benchmarks/results/2026-09-30-3727494-expanded. The harness is src/Tedd.RectanglePacker.Comparison; the command line is in BENCHMARKS.md.