30 Setembru 2023 nullprogram.com/blog/2023/09/30/ Artigu meu liuhaduk konaba duni ba alokasaun arena. Artigu oin ne’e hatudu teknika atu konstrui hash map personalizadu ne’ebe kompozisaun di’ak ho alokasaun arena. Iha mos, sira ne’e ki’ik, di’ak, no automatikamente eskala ba problema ne’ebe bele rezolve ho hash map iha memória. Hodi evita redimensaun — tanba atu hadi’a suporta arena no simplifika implementasaun — sira ne’e iha rekizitus memoria ligeiramente boot. Deseniu, ne’ebe ita sei koalia hanesan hash-trie, resultadu kolaborasaun produtivu ho NRK, ne’ebe artigu simili inklui benchmark nian. Ne’e estrutura dadus favoritu foun ida, no hatudu ona utilidade maka’as. Ho atomiku aqurir / rekolla balansu di’ak, ami bele sai mos nia hash map konkorrente livre hela. Ami ona hein antes kona-ba tabela hash MSI, mapa di’ak no la’os boot, ne’ebe bele implementa ho di’ak liu husi buat foun ida, ajusta ba problema ida-idak ne’ebe iha. Troka ho ne’e, ita presiza hatene limitasaun boot di’ak hodi redimensionsaun ba array — ne’ebe liga ho alokasaun arena. Arvore buska eskala di’ak liu, tanba laiha array baziku, maibe balansu arvore tende sai sensivel no komplikadu, la’os apropriadu ba implementasaun rapidu no hodi husu. Ami hakarak fahe fahezin MSI hash tabela ho eskala arvore. Ami sei motivasaun diskusaun ho ezemplu funsionamentu. Suponha katak ami iha array string ne’ebe konten ba ponteiru + string nia loron, hanesan definidu dala rua: typedef struct { uint8_t *data; ptrdiff_t len; } str; No ami presiza funsaun ne’ebe hamosu duplicado iha fatin ida, maibe (momentu ne’e) la preokupa kona-ba prezerva ordom. Ne’e bele halo ho modu simples iha tempu kuadratiku. Diak liu mak ordena, depois buka iha run. Iha fatin ne’e, ami uza hash map atu rastreia string ne’ebe mak hetan. Ne’e mapea str ba bool, no ne’e representa hanesan tipo strmap ho funsaun inserir + buka, upsert. // Inserir / buka bool valor ba str ne’ebe iha klau. bool *upsert(strmap **, str klau, arena *); ptrdiff_t uniku(str *strings, ptrdiff_t len, arena scratch) { ptrdiff_t konta = 0; strmap *hatene = 0; wainhira (konta < len) { bool *b = upsert(&hatene, strings[konta], &scratch); wainhira (*b) { // wainhira antes (hakat) strings[konta] = strings[--len]; } seluk { // wainhira foun (manten) konta++; *b = 1; } } retorna konta; } Espesifikamente, hatene: Ponteiru null ne'ebe hamosu hash map balu ne'ebe la iha konteudu no inicializasaun ne'e di'ak. Hanesan diskuti iha artigu oin, prinsipiu alokasaun arena ida nian ne'e inicializasaun predefinidu-zero. Rua-tersu, ne'e signifika estrutura dadus ne'ebe inklui mapa iha ona mapa ne'ebe hamosu ne'ebe la iha konteudu atu uza duni. Mapa ne'e halo alokasaun hosi arena scratch entaun halo liberta automatikamente wainhira fila mai. Hanesan lixo koleksaun. Mapa uza direta string sira iha array input nian hanesan klau, ho la halo kopia no la preokupa kona-ba propriedade. Arena nia propriedade, la'os referensia. Wainhira ami hakarak hatama klau fixu hosi uma-laran, ami bele atu inserir string estatik. upsert buka ba ponteiru ba valor. Ne'e duni, ponteiru iha mapa. Ne'e la'os estritamente rekizitu, maibe normalmente halo interface simples. Wainhira entrada foun, valor ne'e sei falsu (inicializasaun-zero). Tanba ne'e estrutura interface di'ak liu. Tanba ami nia ne'ebe maka lisu, valor foun ne'ebe maka la'os hatudu wainhira klau la hetan. Entaun, estrutura dadus ida-ne'e liu atu deteta elementu foun ne'ebe mai to'o ba fatin ida. Iha kazu balun, ami bele halo kopu ida iha arena ida liuhosi klau dala ida hodi hatama iha mapa. Klau ne'ebe iha bele nu'udar temporariu (e.g. sprintf) ne'ebe mapa la'os durasaun loron ho nia, no ema ne'ebe bolu la presiza alokasaun klau ida ne'ebe durasaun di'ak ba menos ne'e. Ne'e parte husi hetan mapa problema ne'ebe bele halo tan ne'e boot no di'ak liu! Atu fó dalan tomak Halibur ita hotu, uniku bele halo hanesan iha mai ne'e, ho strmap / upsert naran muda ba strset / ismember: uint64_t hash(str s) { uint64_t h = 0x100; for (ptrdiff_t i = 0; i < s.len; i++) { h ^= s.data[i]; h *= 1111111111111111111u; } return h; } bool equals(str a, str b) { return a.len==b.len && !memcmp(a.data, b.data, a.len); } typedef struct { strset *child[4]; str key; } strset; static bool ismember(strset **m, str key, arena *perm) { for (uint64_t h = hash(key); *m; h <<= 2) { if (equals(key, (*m)->key)) { return 1; } m = &(*m)->child[h>>62]; } *m = new(perm, strset); (*m)->key = key; return 0; } ptrdiff_t unique(str *strings, ptrdiff_t len, arena scratch) { ptrdiff_t konta = 0; for (strset *hatene = 0; konta < len;) { if (ismember(&hatene, strings[konta], &scratch)) { strings[konta] = strings[--len]; } seluk { konta++; } } retorna konta; } Multiplikador hash FNV hanesan 19 ida, prime favoritu ida ne'e. Ha'u la preokupa ho finalizador xorshift tanba bit sira ne'e uza husi signifikante primeiru. Eserjis ba leitor: Suporta mantein orijinal ordenadu iha input ho lista hakerek invasive iha strset.Pontu relatifu? Hanesan mensiona, kuatro pontu ida ba…