[mono] Decompress ICU data during iOS/tvOS app startup (#64967)
This change adds support for decompressing ICU data files using the lzfse decompressor built into Apple OSes. If the data file path passed to `GlobalizationNative_LoadICUData` does not have `.lzfse` as a suffix, then the contents of this file will be mapped into shareable memory and passed directly to ICU. Otherwise, the contents are decompressed using a fixed-size working buffer and are stored inside a cache file with a name that contains a decimal encoded representation of the originating compressed file's inode number, modification time, and size. This filesystem metadata is extremely likely to change if the contents of the source file ever changes, so there's no need to compute a checksum of the data to determine if the cache is still valid. If a cache file with an appropriate name is already present then it is mapped into shareable memory and passed to ICU. Stale cache files (defined here to be any file with a filename that ends with "-icudt.dat.uncompressed" that doesn't exactly match the desired cache file name) are purged on startup. `icudt.dat` for mobile is 2126 KiB right now; when compressed with lzfse it shrinks to 675 KiB. On an iPhone SE 1st gen, this takes 4ms to decompress. The "decompression framework" also supports lz4, zlib, and lzma. They are all worse either in decompression time (lzma especially + zlib) or compression ratio (lz4): | Algorithm | icudt.dat compressed size | decompression time | | --------- | ------------------------- | ------------------ | | lz4 | 1031 KiB | 2.41 ms | | lzfse | 675 KiB | 4.20 ms | | zlib | 659 KiB | 9.61 ms | | lzma | 427 KiB | 49.20 ms | I am not comfortable adding 50ms to app startup time. On this same iPhone SE 1st gen, the "Contacts" app takes 166.7ms to display app-generated pixels. This is end-to-end latency, from the first indication that iOS has recognized my finger tap, to the display displaying any non-placeholder content. This was measured with with a 240fps camera. A barebones xamarin-macios app takes 125ms to display a "Hello world!" message. This uses the filename's suffix to control decompression for simplicity, but it would also be possible to instead frame compressed data with a very simple header consisting of a long-enough magic number and a decompressed payload size that can be used as a buffer sizing hint to the decompression loop. Miscellany: - On iOS, the cache-directory appears to be app-specific. Example: `/var/mobile/Containers/Data/Application/0C22E0D1-26CD-46CB-9EBC-6CF55B513ED1/Library/Caches/`. - https://www.usenix.org/system/files/conference/osdi14/osdi14-paper-pillai.pdf
Showing
想要评论请 注册 或 登录