Rota oħra: aħna naħżnu kordi Unicode 30-60% aktar kompatti minn UTF-8

Rota oħra: aħna naħżnu kordi Unicode 30-60% aktar kompatti minn UTF-8

Jekk inti żviluppatur u qed tiffaċċja l-kompitu li tagħżel kodifikazzjoni, allura Unicode kważi dejjem ikun is-soluzzjoni t-tajba. Il-metodu ta 'rappreżentazzjoni speċifika jiddependi fuq il-kuntest, iżda ħafna drabi hemm tweġiba universali hawn ukoll - UTF-8. Il-ħaġa tajba dwarha hija li tippermettilek tuża l-karattri Unicode kollha mingħajr ma tonfoq wisq ħafna bytes fil-biċċa l-kbira tal-każijiet. Veru, għal-lingwi li jużaw aktar minn sempliċiment l-alfabett Latin, "mhux wisq" hija għall-inqas żewġ bytes għal kull karattru. Nistgħu nagħmlu aħjar mingħajr ma nerġgħu lura għal kodifikazzjonijiet preistoriċi li jillimitawna għal 256 karattru disponibbli biss?

Hawn taħt nipproponi li tiffamiljarizza ruħek mat-tentattiv tiegħi li nwieġeb din il-mistoqsija u nimplimenta algoritmu relattivament sempliċi li jippermettilek taħżen linji fil-biċċa l-kbira tal-lingwi tad-dinja mingħajr ma żżid ir-redundancy li hija fl-UTF-8.

Ċaħda. Immedjatament se nagħmel ftit riżervi importanti: is-soluzzjoni deskritta mhix offruta bħala sostitut universali għal UTF-8, huwa adattat biss f'lista dejqa ta 'każijiet (aktar dwarhom hawn taħt), u fl-ebda każ m'għandu jintuża biex jinteraġixxi ma' APIs ta 'partijiet terzi (li lanqas biss jafu biha). Ħafna drabi, algoritmi ta 'kompressjoni għal skopijiet ġenerali (per eżempju, deflate) huma adattati għall-ħażna kompatta ta' volumi kbar ta 'dejta tat-test. Barra minn hekk, diġà fil-proċess tal-ħolqien tas-soluzzjoni tiegħi, sibt standard eżistenti fl-Unicode innifsu, li jsolvi l-istess problema - huwa kemmxejn aktar ikkumplikat (u ħafna drabi agħar), iżda xorta huwa standard aċċettat, u mhux biss jitqiegħed flimkien fuq l-irkoppa. Ngħidlek ukoll dwaru.

Dwar Unicode u UTF-8

Biex tibda, ftit kliem dwar x'inhu Unicode и UTF-8.

Kif tafu, kodifikazzjonijiet 8-bit kienu popolari. Magħhom, kollox kien sempliċi: 256 karattru jistgħu jiġu nnumerati b'numri minn 0 sa 255, u numri minn 0 sa 255 jistgħu ovvjament jiġu rappreżentati bħala byte wieħed. Jekk immorru lura għall-bidu nett, il-kodifikazzjoni ASCII hija kompletament limitata għal 7 bits, għalhekk l-aktar bit sinifikanti fir-rappreżentazzjoni tal-byte tagħha hija żero, u l-biċċa l-kbira tal-kodifikazzjonijiet ta '8 bits huma kompatibbli magħha (ivarjaw biss fil-"fuq" parti, fejn l-aktar bit sinifikanti huwa wieħed ).

Kif tvarja l-Unicode minn dawk il-kodifikazzjonijiet u għaliex hemm tant rappreżentazzjonijiet speċifiċi assoċjati magħha - UTF-8, UTF-16 (BE u LE), UTF-32? Ejja issolviha fl-ordni.

L-istandard bażiku tal-Unicode jiddeskrivi biss il-korrispondenza bejn il-karattri (u f'xi każijiet, il-komponenti individwali tal-karattri) u n-numri tagħhom. U hemm ħafna numri possibbli f'dan l-istandard - minn 0x00 li 0x10FFFF (1 biċċa). Kieku ridna npoġġu numru f'firxa bħal din f'varjabbli, la 114 u lanqas 112 bytes ma jkunu biżżejjed għalina. U peress li l-proċessuri tagħna ma tantx huma ddisinjati biex jaħdmu b'numri ta 'tliet bytes, inkunu sfurzati nużaw daqs 1 bytes għal kull karattru! Dan huwa UTF-2, iżda huwa preċiżament minħabba din il-"ħela" li dan il-format mhuwiex popolari.

Fortunatament, l-ordni tal-karattri fi ħdan Unicode mhix każwali. Is-sett kollu tagħhom huwa maqsum fi 17 "ajruplani", li kull wieħed minnhom fih 65536 (0x10000) «punti tal-kodiċi" Il-kunċett ta '"punt ta' kodiċi" hawnhekk huwa sempliċiment numru tal-karattru, assenjat lilha minn Unicode. Iżda, kif imsemmi hawn fuq, fl-Unicode mhux biss il-karattri individwali huma nnumerati, iżda wkoll il-komponenti u l-marki tas-servizz tagħhom (u xi kultant xejn ma jikkorrispondi man-numru - forsi għalissa, iżda għalina dan mhux daqshekk importanti), għalhekk huwa aktar korrett dejjem jitkellmu speċifikament dwar in-numru ta 'numri nfushom, u mhux simboli. Madankollu, f'dan li ġej, għal raġunijiet ta' qosor, spiss nuża l-kelma "simbolu", li timplika t-terminu "punt tal-kodiċi".

Rota oħra: aħna naħżnu kordi Unicode 30-60% aktar kompatti minn UTF-8
Ajruplani Unicode. Kif tistgħu taraw, ħafna minnu (ajruplani 4 sa 13) għadu mhux użat.

L-aktar notevoli huwa li l-"polpa" prinċipali kollha tinsab fil-pjan żero, tissejjaħ "Ajru Multilingwi Bażiku". Jekk linja fiha test f'waħda mil-lingwi moderni (inkluż iċ-Ċiniż), ma tmurx lil hinn minn dan il-pjan. Iżda lanqas ma tista 'taqta' l-bqija ta 'Unicode - pereżempju, l-emoji jinsabu prinċipalment fl-aħħar ta' l-ajruplan li jmiss,"Ajru Multilingwi Supplimentari"(jistendi minn 0x10000 li 0x1FFFF). Allura UTF-16 jagħmel dan: il-karattri kollha li jaqgħu fi ħdan Ajru Multilingwi Bażiku, huma kodifikati "kif inhuma" b'numru ta' żewġ byte korrispondenti. Madankollu, xi wħud min-numri f'din il-firxa ma jindikawx karattri speċifiċi, iżda jindikaw li wara dan il-par ta 'bytes għandna bżonn nikkunsidraw ieħor - billi ngħaqqdu l-valuri ta' dawn l-erba 'bytes flimkien, ikollna numru li jkopri il-firxa Unicode valida kollha. Din l-​idea tissejjaħ “koppji surrogati”—forsi smajt bihom.

Allura UTF-16 teħtieġ żewġ jew (f'każijiet rari ħafna) erba 'bytes għal kull "punt ta' kodiċi". Dan huwa aħjar milli tuża erba 'bytes il-ħin kollu, iżda l-Latin (u karattri ASCII oħra) meta kkodifikati b'dan il-mod jaħli nofs l-ispazju fuq żerijiet. UTF-8 huwa ddisinjat biex jikkoreġi dan: ASCII fih jokkupa, bħal qabel, byte wieħed biss; kodiċi minn 0x80 li 0x7FF - żewġ bytes; minn 0x800 li 0xFFFF - tlieta, u minn 0x10000 li 0x10FFFF - erbgħa. Min-naħa waħda, l-alfabett Latin sar tajjeb: il-kompatibilità ma 'ASCII reġgħet lura, u d-distribuzzjoni hija "mifruxa" b'mod aktar ugwali minn 1 sa 4 bytes. Iżda alfabeti minbarra Latin, sfortunatament, ma jibbenefikaw bl-ebda mod meta mqabbla ma 'UTF-16, u ħafna issa jeħtieġu tliet bytes minflok tnejn - il-firxa koperta minn rekord ta' żewġ byte naqset bi 32 darba, bi 0xFFFF li 0x7FF, u la Ċiniż u lanqas, pereżempju, Ġorġjan huma inklużi fiha. Ċirilliku u ħames alfabeti oħra - hurray - xxurtjati, 2 bytes għal kull karattru.

Għaliex jiġri dan? Ejja naraw kif l-UTF-8 tirrappreżenta l-kodiċi tal-karattri:
Rota oħra: aħna naħżnu kordi Unicode 30-60% aktar kompatti minn UTF-8
Direttament biex jirrappreżentaw in-numri, il-bits immarkati bis-simbolu jintużaw hawnhekk x. Wieħed jista’ jara li f’rekord ta’ żewġ byte hemm biss 11-il bit bħal dawn (minn 16). Il-bits ewlenin hawn għandhom biss funzjoni awżiljarja. Fil-każ ta 'rekord ta' erba 'byte, 21 minn 32 bit huma allokati għan-numru tal-punt tal-kodiċi - jidher li tliet bytes (li jagħtu total ta' 24 bit) ikunu biżżejjed, iżda l-markaturi tas-servizz jieklu wisq.

Dan huwa ħażin? Mhux ezatt. Min-naħa l-waħda, jekk aħna jimpurtahom ħafna mill-ispazju, għandna algoritmi ta 'kompressjoni li jistgħu faċilment jeliminaw l-entropija u r-redundancy żejda kollha. Min-naħa l-oħra, l-għan tal-Unicode kien li jipprovdi l-aktar kodifikazzjoni universali possibbli. Pereżempju, nistgħu nafdaw linja kodifikata f'UTF-8 biex tikkodifika li qabel kienet taħdem biss bl-ASCII, u ma nibżgħux li se tara karattru mill-firxa ASCII li fil-fatt mhux hemm (wara kollox, f'UTF-8 kollha bytes li jibdew mill-bit żero - dan huwa eżattament dak ASCII). U jekk f'daqqa waħda rridu naqtgħu denb żgħir minn spag kbir mingħajr ma niddekodifikawh mill-bidu nett (jew nirrestawraw parti mill-informazzjoni wara sezzjoni bil-ħsara), huwa faċli għalina li nsibu l-offset fejn jibda karattru (biżżejjed biex taqbeż bytes li għandhom daqsxejn prefiss 10).

Għaliex allura nivvintaw xi ħaġa ġdida?

Fl-istess ħin, kultant ikun hemm sitwazzjonijiet meta algoritmi ta 'kompressjoni bħal deflate ma tantx japplikaw, imma trid tikseb ħażna kompatta ta' kordi. Personalment, iltqajt ma' din il-problema meta ħsibt dwar il-bini siġra tal-prefiss kompressat għal dizzjunarju kbir li jinkludi kliem f’lingwi arbitrarji. Min-naħa waħda, kull kelma hija qasira ħafna, għalhekk il-kompressjoni tagħha tkun ineffettiva. Min-naħa l-oħra, l-implimentazzjoni tas-siġra li qiest kienet iddisinjata sabiex kull byte tas-sekwenza maħżuna ġġenera vertiċi tas-siġra separat, u għalhekk it-tnaqqis tan-numru tagħhom kien utli ħafna. Fil-librerija tiegħi Az.js (Bħal fi pimorfija2, li fuqha hija bbażata) problema simili tista 'tiġi solvuta sempliċiment - kordi ppakkjati fi DAWG-dizzjunarju, maħżun hemm fi CP1251 antik tajjeb. Iżda, kif huwa faċli biex jinftiehem, dan jaħdem tajjeb biss għal alfabett limitat - linja fiċ-Ċiniż ma tistax tiżdied ma 'tali dizzjunarju.

Separatament, nixtieq ninnota sfumatura spjaċevoli oħra li tqum meta tuża UTF-8 f'tali struttura tad-dejta. L-istampa ta’ hawn fuq turi li meta karattru jinkiteb bħala żewġ bytes, il-bits relatati man-numru tiegħu ma jiġux f’ringiela, iżda huma separati b’par bits 10 fin-nofs: 110xxxxx 10xxxxxx. Minħabba dan, meta s-6 bits aktar baxxi tat-tieni byte overflow fil-kodiċi tal-karattru (jiġifieri, isseħħ transizzjoni 1011111110000000), allura l-ewwel byte jinbidel ukoll. Jirriżulta li l-ittra "p" hija indikata b'bytes 0xD0 0xBF, u l-"r" li jmiss huwa diġà 0xD1 0x80. F'siġra tal-prefiss, dan iwassal għall-qsim tan-nodu ġenitur fi tnejn - wieħed għall-prefiss 0xD0, u ieħor għal 0xD1 (għalkemm l-alfabett Ċirilliku kollu jista’ jiġi kkodifikat biss mit-tieni byte).

Dak li ħadt

Quddiem din il-problema, iddeċidejt li nipprattika l-logħob bil-bits, u fl-istess ħin issir familjari ftit aħjar mal-istruttura tal-Unicode kollha kemm hi. Ir-riżultat kien il-format ta 'kodifikazzjoni UTF-C ("C" għal kompatti), li tonfoq mhux aktar minn 3 bytes għal kull punt tal-kodiċi, u ħafna drabi jippermettilek tonfoq biss byte wieħed żejjed għal-linja kodifikata kollha. Dan iwassal għall-fatt li fuq ħafna alfabeti mhux ASCII tali kodifikazzjoni tirriżulta li hija 30-60% aktar kompatti minn UTF-8.

Jien ippreżentajt eżempji ta 'implimentazzjoni ta' algoritmi ta 'kodifikazzjoni u dekodifikazzjoni fil-forma Libreriji JavaScript u Go, tista 'tużahom liberament fil-kodiċi tiegħek. Imma xorta se nenfasizza li f'ċertu sens dan il-format jibqa '"rota", u ma nirrakkomandax li tużah mingħajr ma tirrealizza għaliex għandek bżonnha. Dan għadu aktar esperiment minn "titjib tal-UTF-8" serju. Madankollu, il-kodiċi hemm miktub pulit, b'mod konċiż, b'numru kbir ta 'kummenti u kopertura tat-test.

Rota oħra: aħna naħżnu kordi Unicode 30-60% aktar kompatti minn UTF-8
Riżultati tat-test u tqabbil ma 'UTF-8

Għamilt ukoll paġna demo, fejn tista 'tevalwa l-prestazzjoni tal-algoritmu, u mbagħad ngħidlek aktar dwar il-prinċipji u l-proċess ta' żvilupp tiegħu.

Jeliminaw bits żejda

Ħadt UTF-8 bħala bażi, ovvjament. L-ewwel u l-aktar ħaġa ovvja li tista 'tiġi mibdula fiha hija li jitnaqqas in-numru ta' bits tas-servizz f'kull byte. Pereżempju, l-ewwel byte f'UTF-8 dejjem jibda bi kwalunkwe waħda 0, jew bi 11 - prefiss 10 Il-bytes li ġejjin biss għandhom dan. Ejja nibdel il-prefiss 11 fuq 1, u għall-bytes li jmiss se nneħħu l-prefissi kompletament. X'se jiġri?

0xxxxxxx — 1 byte
10xxxxxx xxxxxxxx - 2 bytes
110xxxxx xxxxxxxx xxxxxxxx - 3 bytes

Stenna, fejn hu r-rekord ta’ erba’ byte? Iżda m'għadhiex meħtieġa - meta tikteb fi tliet bytes, issa għandna 21 bit disponibbli u dan huwa biżżejjed għan-numri kollha sa 0x10FFFF.

X’sagrifikajna hawn? L-iktar ħaġa importanti hija l-iskoperta tal-konfini tal-karattri minn post arbitrarju fil-buffer. Ma nistgħux nippuntaw lejn byte arbitrarju u nsibu l-bidu tal-karattru li jmiss minnu. Din hija limitazzjoni tal-format tagħna, iżda fil-prattika dan rari huwa meħtieġ. Normalment inkunu kapaċi ngħaddu mill-buffer mill-bidu nett (speċjalment meta niġu għal linji qosra).

Is-sitwazzjoni li tkopri lingwi b'2 bytes saret aħjar ukoll: issa l-format ta 'żewġ byte jagħti firxa ta' 14-il bit, u dawn huma kodiċi sa 0x3FFF. Iċ-Ċiniżi huma sfortunati (il-karattri tagħhom ivarjaw l-aktar minn 0x4E00 li 0x9FFF), iżda l-Ġorġjani u ħafna popli oħra jieħdu pjaċir aktar - il-lingwi tagħhom jidħlu wkoll f'2 bytes għal kull karattru.

Daħħal l-istat tal-kodifikatur

Ejja issa naħsbu dwar il-proprjetajiet tal-linji nfushom. Id-dizzjunarju ħafna drabi jkun fih kliem miktub b’karattri tal-istess alfabett, u dan jgħodd ukoll għal ħafna testi oħra. Ikun tajjeb li tindika dan l-alfabett darba, u mbagħad tindika biss in-numru tal-ittra fi ħdanu. Ejja naraw jekk l-arranġament tal-karattri fit-tabella Unicode jgħinna.

Kif imsemmi hawn fuq, Unicode huwa maqsum fi ajruplan 65536 kodiċi kull wieħed. Iżda din mhix diviżjoni utli ħafna (kif diġà ntqal, ħafna drabi aħna qegħdin fil-pjan żero). Aktar interessanti hija d-diviżjoni minn blokki. Dawn il-firxiet m'għadx għandhom tul fiss, u huma aktar sinifikanti - bħala regola, kull wieħed jgħaqqad karattri mill-istess alfabett.

Rota oħra: aħna naħżnu kordi Unicode 30-60% aktar kompatti minn UTF-8
Blokk li fih karattri tal-alfabett Bengali. Sfortunatament, għal raġunijiet storiċi, dan huwa eżempju ta 'imballaġġ mhux dens ħafna - 96 karattru huma mferrxa b'mod kaotiku fuq 128 punt tal-kodiċi tal-blokk.

Il-bidu tal-blokki u d-daqsijiet tagħhom huma dejjem multipli ta '16 - dan isir sempliċement għall-konvenjenza. Barra minn hekk, ħafna blokki jibdew u jispiċċaw fuq valuri li huma multipli ta '128 jew saħansitra 256 - pereżempju, l-alfabett Ċirilliku bażiku jieħu 256 byte minn 0x0400 li 0x04FF. Dan huwa pjuttost konvenjenti: jekk insalvaw il-prefiss darba 0x04, allura kwalunkwe karattru Ċirilliku jista' jinkiteb f'byte wieħed. Veru, b'dan il-mod se nitilfu l-opportunità li nerġgħu lura għall-ASCII (u għal kwalunkwe karattri oħra b'mod ġenerali). Għalhekk nagħmlu dan:

  1. Żewġ bytes 10yyyyyy yxxxxxxx mhux biss jindikaw simbolu b'numru yyyyyy yxxxxxxx, iżda wkoll bidla alfabett kurrenti fuq yyyyyy y0000000 (jiġifieri niftakru l-bits kollha ħlief dawk l-inqas sinifikanti Bit 7);
  2. Byte wieħed 0xxxxxxx dan huwa l-karattru tal-alfabett kurrenti. Jeħtieġ biss li jiżdied mal-offset li ftakarna fil-pass 1. Filwaqt li ma bdilniex l-alfabett, l-offset huwa żero, għalhekk żammejna l-kompatibilità mal-ASCII.

Bl-istess mod għall-kodiċijiet li jeħtieġu 3 bytes:

  1. Tliet bytes 110yyyyy yxxxxxxx xxxxxxxx jindika simbolu b'numru yyyyyy yxxxxxxx xxxxxxxx, bidla alfabett kurrenti fuq yyyyyy y0000000 00000000 (ftakar kollox ħlief iż-żgħar Bit 15), u iċċekkja l-kaxxa li qegħdin fiha twil mod (meta nbiddlu l-alfabett lura għal wieħed b'byte doppju, aħna se reset din il-bandiera);
  2. Żewġ bytes 0xxxxxxx xxxxxxxx fil-modalità twila huwa l-karattru tal-alfabett kurrenti. Bl-istess mod, inżiduha bl-offset mill-pass 1. L-unika differenza hija li issa naqraw żewġ bytes (għax qlibna għal din il-modalità).

Ħsejjes tajjeb: issa filwaqt li għandna bżonn nikkodifikaw karattri mill-istess firxa Unicode ta '7-bit, nonfqu byte 1 żejjed fil-bidu u total ta' byte wieħed għal kull karattru.

Rota oħra: aħna naħżnu kordi Unicode 30-60% aktar kompatti minn UTF-8
Ħidma minn waħda mill-verżjonijiet preċedenti. Diġà spiss jegħleb l-UTF-8, iżda għad hemm lok għal titjib.

X'hemm agħar? L-ewwelnett, għandna kundizzjoni, jiġifieri offset kurrenti tal-alfabett u checkbox modalità twila. Dan ikompli jillimita: issa l-istess karattri jistgħu jiġu kodifikati b'mod differenti f'kuntesti differenti. It-tiftix għas-substrings, pereżempju, irid isir billi jitqies dan, u mhux biss billi jitqabblu l-bytes. It-tieni nett, hekk kif bdilna l-alfabett, sar ħażin bl-kodifikazzjoni ta 'karattri ASCII (u dan mhux biss l-alfabett Latin, iżda wkoll punteġġjatura bażika, inklużi l-ispazji) - jeħtieġu li l-alfabett jerġa' jinbidel għal 0, jiġifieri, għal darb'oħra byte żejjed (u mbagħad ieħor biex terġa' lura għall-punt ewlieni tagħna).

Alfabett wieħed huwa tajjeb, tnejn aħjar

Ejja nippruvaw nibdlu xi ftit il-prefissi tal-bit tagħna, billi nagħslu waħda oħra mat-tlieta deskritti hawn fuq:

0xxxxxxx — 1 byte fil-modalità normali, 2 fil-modalità twila
11xxxxxx — 1 byte
100xxxxx xxxxxxxx - 2 bytes
101xxxxx xxxxxxxx xxxxxxxx - 3 bytes

Rota oħra: aħna naħżnu kordi Unicode 30-60% aktar kompatti minn UTF-8

Issa f'rekord ta 'żewġ byte hemm bit inqas disponibbli - punti ta' kodiċi sa 0x1FFFimma le 0x3FFF. Madankollu, għadu notevoli akbar milli fil-kodiċijiet UTF-8 b'byte doppju, l-aktar lingwi komuni għadhom jidħlu fihom, l-aktar telf notevoli waqa' hiragana и katakana, il-Ġappuniżi huma imdejjaq.

X'inhu dan il-kodiċi ġdid? 11xxxxxx? Din hija "stash" żgħira ta' 64 karattru, tikkumplimenta l-alfabett ewlieni tagħna, għalhekk sejħitha awżiljarja (awżiljarju) alfabett. Meta naqlbu l-alfabett attwali, biċċa mill-alfabett l-antik issir awżiljarju. Pereżempju, qlibna minn ASCII għal Ċirilliku - l-istash issa fih 64 karattru li fihom Alfabett Latin, numri, spazju u virgola (inserzjonijiet l-aktar frekwenti f'testi mhux ASCII). Aqleb lura għall-ASCII - u l-parti prinċipali tal-alfabett Ċirilliku ssir l-alfabett awżiljarju.

Grazzi għall-aċċess għal żewġ alfabeti, nistgħu nittrattaw numru kbir ta 'testi bi spejjeż minimi għall-bidla tal-alfabeti (il-punteġġjatura ħafna drabi twassal għal ritorn għal ASCII, iżda wara dan se nġibu ħafna karattri mhux ASCII mill-alfabett addizzjonali, mingħajr jaqilbu mill-ġdid).

Bonus: il-prefiss tas-sub-alfabett 11xxxxxx u tagħżel l-offset inizjali tagħha li jkun 0xC0, Ikollna kompatibilità parzjali ma 'CP1252. Fi kliem ieħor, ħafna (iżda mhux kollha) testi Ewropej tal-Punent kodifikati f'CP1252 se jidhru l-istess f'UTF-C.

Hawnhekk, madankollu, tqum diffikultà: kif tikseb waħda awżiljarja mill-alfabett prinċipali? Tista 'tħalli l-istess offset, iżda - sfortunatament - hawn l-istruttura Unicode diġà qed tilgħab kontra tagħna. Ħafna drabi l-parti prinċipali tal-alfabett mhix fil-bidu tal-blokk (per eżempju, il-kapital Russa "A" għandha l-kodiċi 0x0410, għalkemm il-blokk Ċirilliku jibda bi 0x0400). Għalhekk, wara li ħadna l-ewwel 64 karattru fil-stash, nistgħu nitilfu l-aċċess għall-parti tad-denb tal-alfabett.

Biex nirranġa din il-problema, għaddejt manwalment minn xi blokki li jikkorrispondu għal lingwi differenti, u speċifikajt l-offset tal-alfabett awżiljarju fi ħdan dak prinċipali għalihom. L-alfabett Latin, bħala eċċezzjoni, kien ġeneralment ordnat mill-ġdid bħal bażi64.

Rota oħra: aħna naħżnu kordi Unicode 30-60% aktar kompatti minn UTF-8

Irtokki finali

Ejja fl-aħħar naħsbu dwar fejn inkella nistgħu ntejbu xi ħaġa.

Innota li l-format 101xxxxx xxxxxxxx xxxxxxxx jippermettilek tikkodifika numri sa 0x1FFFFF, u Unicode jintemm qabel, fi 0x10FFFF. Fi kliem ieħor, l-aħħar punt tal-kodiċi se jkun rappreżentat bħala 10110000 11111111 11111111. Għalhekk, nistgħu ngħidu li jekk l-ewwel byte huwa tal-forma 1011xxxx (Fejn xxxx akbar minn 0), allura jfisser xi ħaġa oħra. Pereżempju, tista 'żżid 15-il karattru ieħor hemmhekk li huma kontinwament disponibbli għall-kodifikazzjoni f'byte wieħed, iżda ddeċidejt li nagħmilha differenti.

Ejja nħarsu lejn dawk il-blokki Unicode li jeħtieġu tliet bytes issa. Bażikament, kif diġà ssemma, dawn huma karattri Ċiniżi - iżda huwa diffiċli li tagħmel xi ħaġa magħhom, hemm 21 elf minnhom. Iżda hiragana u katakana wkoll tellgħu hemm - u m'għadhomx daqstant minnhom, inqas minn mitejn. U, peress li ftakarna l-Ġappuniżi, hemm ukoll emojis (fil-fatt, huma mferrxa f'ħafna postijiet f'Unicode, iżda l-blokki ewlenin huma fil-medda 0x1F300 - 0x1FBFF). Jekk taħseb dwar il-fatt li issa hemm emojis li huma mmuntati minn diversi punti tal-kodiċi f'daqqa (per eżempju, l-emoji ‍‍‍Rota oħra: aħna naħżnu kordi Unicode 30-60% aktar kompatti minn UTF-8 tikkonsisti minn 7 kodiċijiet!), imbagħad issir tal-mistħija sħiħa li tonfoq tliet bytes fuq kull wieħed (7 × 3 = 21 bytes għall-fini ta 'ikona waħda, ħmar il-lejl).

Għalhekk, aħna nagħżlu ftit firxiet magħżula li jikkorrispondu għal emoji, hiragana u katakana, innumerawhom mill-ġdid f'lista waħda kontinwa u nikkodifikawhom bħala żewġ bytes minflok tlieta:

1011xxxx xxxxxxxx

Kbir: l-emoji msemmi hawn fuqRota oħra: aħna naħżnu kordi Unicode 30-60% aktar kompatti minn UTF-8, li jikkonsisti f'7 punti ta' kodiċi, jieħu 8 bytes f'UTF-25, u nidħlu fih 14 (eżatt żewġ bytes għal kull punt tal-kodiċi). Mill-mod, Habr irrifjuta li jiddiġerixxiha (kemm fl-editur il-qadim kif ukoll fl-editur il-ġdid), għalhekk kelli ndaħħalha bi stampa.

Ejja nippruvaw nirranġaw problema oħra. Kif niftakru, l-alfabett bażiku huwa essenzjalment għoli 6 bits, li aħna nżommu f'moħħna u nwaħħal mal-kodiċi ta 'kull simbolu dekodifikat li jmiss. Fil-każ ta 'karattri Ċiniżi li huma fil-blokk 0x4E00 - 0x9FFF, dan huwa jew bit 0 jew 1. Dan mhux konvenjenti ħafna: ser ikollna bżonn naqleb kontinwament l-alfabett bejn dawn iż-żewġ valuri (jiġifieri jonfqu tliet bytes). Imma innota li fil-modalità twila, mill-kodiċi innifsu nistgħu nnaqqsu n-numru ta 'karattri li nikkodifikaw bl-użu tal-modalità qasira (wara t-tricks kollha deskritti hawn fuq, dan huwa 10240) - allura l-firxa ta' hieroglyphs tinbidel għal 0x2600 - 0x77FF, u f'dan il-każ, matul din il-firxa kollha, l-aktar sinifikanti 6 bits (minn 21) se jkunu ugwali għal 0. Għalhekk, sekwenzi ta 'ġeroglifi se jużaw żewġ bytes għal kull hieroglyph (li huwa ottimali għal firxa daqshekk kbira), mingħajr li tikkawża swiċċijiet tal-alfabett.

Soluzzjonijiet alternattivi: SCSU, BOCU-1

L-esperti Unicode, li għadhom kemm qraw it-titlu tal-artiklu, x'aktarx iħaffu jfakkruk li direttament fost l-istandards Unicode hemm Skema ta' Kompressjoni Standard għall-Unicode (SCSU), li jiddeskrivi metodu ta 'kodifikazzjoni simili ħafna għal dak deskritt fl-artikolu.

Nammetti onestament: tgħallimt dwar l-eżistenza tagħha biss wara li kont mgħaddas profondament fil-kitba tad-deċiżjoni tiegħi. Kieku kont naf dwarha mill-bidu, probabbilment kont nipprova nikteb implimentazzjoni minflok ma noħroġ bl-approċċ tiegħi stess.

X'inhu interessanti hu li l-SCSU juża ideat simili ħafna għal dawk li ħriġt bihom waħdi (minflok il-kunċett ta '"alfabeti" huma jużaw "twieqi", u hemm aktar minnhom disponibbli milli għandi). Fl-istess ħin, dan il-format għandu wkoll żvantaġġi: huwa ftit eqreb lejn algoritmi ta 'kompressjoni minn dawk ta' kodifikazzjoni. B'mod partikolari, l-istandard jagħti ħafna metodi ta 'rappreżentazzjoni, iżda ma jgħidx kif tagħżel l-aħjar waħda - għal dan, l-encoder għandu juża xi tip ta' euristiku. Għalhekk, SCSU encoder li jipproduċi ippakkjar tajjeb se jkun aktar kumpless u aktar ingombranti mill-algoritmu tiegħi.

Għal paragun, ittrasferijt implimentazzjoni relattivament sempliċi ta 'SCSU għal JavaScript - f'termini ta' volum tal-kodiċi rriżulta li kien komparabbli mal-UTF-C tiegħi, iżda f'xi każijiet ir-riżultat kien għexieren ta 'mija agħar (xi kultant jista' jaqbeż, iżda mhux bil-hafna). Pereżempju, testi bl-Ebrajk u bil-Grieg ġew kodifikati minn UTF-C 60% aħjar minn SCSU (probabbilment minħabba l-alfabeti kompatti tagħhom).

Separatament, inżid li minbarra SCSU hemm ukoll mod ieħor biex tirrappreżenta Unicode b'mod kompatt - BOCU-1, iżda timmira għal kompatibilità MIME (li ma kellix bżonn) u tieħu approċċ kemmxejn differenti għall-kodifikazzjoni. Ma vvalutajtx l-effettività tiegħu, iżda jidhirli li x'aktarx li ma tkunx ogħla minn SCSU.

Titjib possibbli

L-algoritmu li ppreżentajt mhuwiex universali fid-disinn (dan huwa probabbilment fejn l-għanijiet tiegħi jvarjaw l-aktar mill-għanijiet tal-Konsorzju Unicode). Diġà semmejt li ġie żviluppat primarjament għal kompitu wieħed (il-ħażna ta 'dizzjunarju multilingwi f'siġra tal-prefiss), u xi wħud mill-karatteristiċi tiegħu jistgħu ma jkunux adattati tajjeb għal kompiti oħra. Iżda l-fatt li mhuwiex standard jista 'jkun plus - tista 'faċilment timmodifikaha biex taqdi l-bżonnijiet tiegħek.

Per eżempju, bil-mod ovvju tista 'teħles mill-preżenza ta' stat, tagħmel kodifikazzjoni mingħajr stat - sempliċement taġġornax varjabbli offs, auxOffs и is21Bit fl-encoder u decoder. F'dan il-każ, mhux se jkun possibbli li jiġu ppakkjati b'mod effettiv sekwenzi ta 'karattri ta' l-istess alfabett, iżda se jkun hemm garanzija li l-istess karattru dejjem ikun kodifikat bl-istess bytes, irrispettivament mill-kuntest.

Barra minn hekk, tista 'tfassal l-encoder għal lingwa speċifika billi tibdel l-istat default - per eżempju, tiffoka fuq testi Russi, issettja l-encoder u d-decoder fil-bidu offs = 0x0400 и auxOffs = 0. Dan jagħmel sens speċjalment fil-każ tal-modalità mingħajr stat. B'mod ġenerali, dan ikun simili għall-użu tal-kodifikazzjoni antik ta 'tmien bit, iżda mingħajr ma titneħħa l-abbiltà li tiddaħħal karattri mill-Unicode kollha kif meħtieġ.

Żvantaġġ ieħor imsemmi qabel huwa li f'test kbir kodifikat f'UTF-C m'hemm l-ebda mod rapidu biex issib il-konfini tal-karattri l-eqreb għal byte arbitrarju. Jekk taqta 'l-aħħar, ngħidu aħna, 100 bytes mill-buffer kodifikat, tirriskja li tikseb żibel li ma tista' tagħmel xejn bih. Il-kodifikazzjoni mhix iddisinjata għall-ħażna ta 'zkuk b'ħafna gigabyte, iżda b'mod ġenerali dan jista' jiġi kkoreġut. Byte 0xBF qatt m'għandu jidher bħala l-ewwel byte (iżda jista' jkun it-tieni jew it-tielet). Għalhekk, meta tikkodifika, tista 'daħħal is-sekwenza 0xBF 0xBF 0xBF kull, ngħidu aħna, 10 KB - imbagħad, jekk għandek bżonn issib konfini, ikun biżżejjed li tiskennja l-biċċa magħżula sakemm jinstab markatur simili. Wara l-aħħar 0xBF huwa garantit li jkun il-bidu ta 'karattru. (Meta d-dekodifikazzjoni, din is-sekwenza ta’ tliet bytes, ovvjament, trid tiġi injorata.)

Bħala sinteżi

Jekk qrajt s'issa, prosit! Nispera li, bħali, tgħallimt xi ħaġa ġdida (jew aggornat il-memorja tiegħek) dwar l-istruttura tal-Unicode.

Rota oħra: aħna naħżnu kordi Unicode 30-60% aktar kompatti minn UTF-8
Paġna demo. L-eżempju tal-Ebrajk juri l-vantaġġi kemm fuq UTF-8 kif ukoll fuq SCSU.

Ir-riċerka deskritta hawn fuq m'għandhiex titqies bħala invażjoni fuq l-istandards. Madankollu, ġeneralment jien sodisfatt bir-riżultati tax-xogħol tiegħi, għalhekk jien kuntent bihom sehem: per eżempju, librerija JS minifikata tiżen biss 1710 bytes (u m'għandha l-ebda dipendenzi, ovvjament). Kif semmejt hawn fuq, ix-xogħol tagħha jista’ jinstab fuq paġna demo (hemm ukoll sett ta 'testi li fuqhom jista' jitqabbel ma 'UTF-8 u SCSU).

Fl-aħħar nett, għal darb'oħra niġbed l-attenzjoni għal każijiet li fihom jintuża l-UTF-C mhux worth it:

  • Jekk il-linji tiegħek huma twal biżżejjed (minn 100-200 karattru). F'dan il-każ, għandek taħseb dwar l-użu ta 'algoritmi ta' kompressjoni bħal deflate.
  • Jekk għandek bżonn Trasparenza ASCII, jiġifieri, huwa importanti għalik li s-sekwenzi kodifikati ma fihomx kodiċi ASCII li ma kinux fis-sekwenza oriġinali. Il-ħtieġa għal dan tista 'tiġi evitata jekk, meta jinteraġixxu ma' APIs ta 'partijiet terzi (per eżempju, taħdem ma' database), tgħaddi r-riżultat tal-kodifikazzjoni bħala sett astratt ta 'bytes, u mhux bħala strings. Inkella, tirriskja li tikseb vulnerabbiltajiet mhux mistennija.
  • Jekk trid tkun tista' ssib malajr il-konfini tal-karattri f'offset arbitrarju (per eżempju, meta parti minn linja tkun bil-ħsara). Dan jista 'jsir, iżda biss billi tiskennja l-linja mill-bidu (jew tapplika l-modifika deskritta fit-taqsima preċedenti).
  • Jekk għandek bżonn twettaq malajr operazzjonijiet fuq il-kontenut ta 'kordi (issortjahom, fittex substrings fihom, konkatena). Dan jeħtieġ li l-kordi jiġu dekodifikati l-ewwel, għalhekk UTF-C se jkun aktar bil-mod minn UTF-8 f'dawn il-każijiet (iżda aktar mgħaġġla mill-algoritmi ta 'kompressjoni). Peress li l-istess sekwenza hija dejjem kodifikata bl-istess mod, paragun eżatt tad-dekodifikazzjoni mhuwiex meħtieġ u jista 'jsir fuq bażi byte b'byte.

Aġġornament: utent Tyomitch fil-kummenti hawn taħt ippubblika graff li jenfasizza l-limiti tal-applikabbiltà tal-UTF-C. Juri li UTF-C huwa aktar effiċjenti minn algoritmu ta' kompressjoni għal skopijiet ġenerali (varjazzjoni ta' LZW) sakemm is-sekwenza ppakkjata tkun iqsar ~140 karattru (madankollu, ninnota li t-tqabbil sar fuq test wieħed; għal lingwi oħra r-riżultat jista’ jkun differenti).
Rota oħra: aħna naħżnu kordi Unicode 30-60% aktar kompatti minn UTF-8

Sors: www.habr.com

Żid kumment