[{"data":1,"prerenderedAt":370},["ShallowReactive",2],{"project-36672957":3},{"id":4,"name":5,"line":6,"line_source":7,"title":8,"url":9,"domain":10,"maker":11,"posted_at":12,"year":13,"points":14,"comments":15,"rank_in_year":16,"shown_in_year":17,"top":18,"tier":19,"category":20,"subcategory":21,"format":22,"keywords":23,"reception":27,"sentiment":28,"stance_mix":29,"scored_comments":34,"aspects":35,"strip":44,"post_text":46,"what":47,"said":67,"maker_in_thread":172,"shape":183,"grid":187,"attempts":332,"same_week":333,"maker_shows":250,"maker_hidden":362,"reader_version":363,"card":364},"36672957","hamt","A hash array-mapped trie implementation in C","title","Show HN: A hash array-mapped trie implementation in C","https:\u002F\u002Fgithub.com\u002Fmkirchner\u002Fhamt","github.com","mkirchner",1689023215,2023,171,56,353,3109,12,"notable","languages","data structure library","library",[5,24,25,26],"persistent data structure","hash array mapped trie","c library","curious",0.126,{"positive":30,"neutral":31,"mixed":32,"critical":33},8,26,0,7,41,{"idea":36,"design":39,"execution":41,"docs":42,"performance":43},{"positive":37,"critical":38},4,1,{"positive":32,"critical":40},3,{"positive":38,"critical":38},{"positive":40,"critical":38},{"positive":32,"critical":38},[45,40,40,40,32,32,32,40,38,38,32,40,38,40,38,40,40,40,45,40,40,40,40,32,40,40,45,40,40,32,45,38,45,38,45,32,45,38,40,45],5,"Long-simmering side project that is finally ready to see the light. HAMTs are a cool persistent data structure and implementing one has been a lot of fun. Beyond the code, there is likely some value in the extensive and largely complete implementation docs; basic benchmarks are linked in the README, too.\n\nKind of aiming to be \"the libavl for HAMTs\". That is obviously a high and aspirational bar but a distinct possibility if it stirs up a little interest and\u002For contribution.\n\nAnyways, it's time for this to go out, collect feedback and maybe even some use outside of toy projects. Let me know how",{"problem":48,"audience":54,"pricing":54,"motivation":55,"time_to_build":54,"stack":59,"openness":64,"stage":65,"team_size":66},{"value":49,"source":50,"evidence":51},"Provides a persistent hash trie with cheap copy-on-update for C programs","maker",[52],{"id":53},"post",null,{"value":56,"source":50,"evidence":57},"Long-simmering side project; the maker enjoyed implementing a HAMT and wants it to be a reference like libavl",[58],{"id":53},[60],{"value":61,"source":50,"evidence":62},"C",[63],{"id":53},"open_source","launched","solo",{"praise":68,"objections":96,"requests":118,"questions":130,"alternatives":142},[69,85],{"value":70,"source":71,"evidence":72},"Clean, readable code and documentation","commenter",[73,77,81],{"id":74,"by":75,"text":76},"36685724","pkkm","I like how readable the code and docs are. Thanks for sharing.",{"id":78,"by":79,"text":80},"36675559","ghotli","Not much to add other than this is cool and the README was very informative. Nice work!",{"id":82,"by":83,"text":84},"36675858","kazinator","Doc fix: Iterators section repeats a code block with these declaration from the previous section: ``` size_t hamt_size(const struct hamt *trie); const void *hamt_get(const struct…",{"value":86,"source":71,"evidence":87},"Good data structure for C; a standard HAMT in C could set a precedent",[88,92],{"id":89,"by":90,"text":91},"36673364","tombert","I discovered HAMTs first when Erlang added support for first-class maps, and it was sort of a \"holy shit!\" moment for me. They felt like the \"holy grail\" of data structures for…",{"id":93,"by":94,"text":95},"36678934","JonChesterfield","Good datastructure, code looks quite clean for C. Your API is missing some of the advantages relative to hash tables though. Because it's a tree, operations like union and…",[97,111],{"value":98,"source":71,"evidence":99},"Allocator API design is debated; commenters prefer a context-carrying or malloc-compatible interface",[100,104,108],{"id":101,"by":102,"text":103},"36673611","thechao","Just a note about your 'exported memory allocation' API: ``` struct hamt_allocator { void *(*malloc)(const size_t size); void *(*realloc)(void *chunk, const size_t size); void…",{"id":105,"by":106,"text":107},"36677078","lelanthran","> But I know a lot of people get confused and\u002For don't like having to pass (& thus keep) so much information to the allocator. That's not why I think it' a bad idea. I prefer the…",{"id":109,"by":83,"text":110},"36675901","I would drop the API directly and concentrate on the algorithm. If users integrating HAMT need a different allocator situation, they can solve that problem by themselves, without…",{"value":112,"source":71,"evidence":113},"Performance could improve with a 64-bit bitmap and iterative lookup",[114],{"id":115,"by":116,"text":117},"36679042","fanf2","I have spotted a couple of ways to improve performance: Increase the size of the bitmap in each node from 32 bits to 64 bits. You are wasting 4 bytes per node, and wider nodes…",[119,123],{"value":120,"source":71,"evidence":121},"Add batch construction from N key\u002Fvalue pairs",[122],{"id":93,"by":94,"text":95},{"value":124,"source":71,"evidence":125},"Add userdata member to the allocator struct",[126],{"id":127,"by":128,"text":129},"36678879","spacechild1","Nice! I think you should really add a userdata member to hamt_allocator. Not every memory allocator is global!",[131,138],{"value":132,"source":71,"evidence":133},"How does it handle memory deallocation without a garbage collector",[134],{"id":135,"by":136,"text":137},"36675582","erichocean","How does this compare to https:\u002F\u002Fgithub.com\u002Farximboldi\u002Fimmer (other than the C\u002FC++ difference)? Also, it's my understanding that, in practice, persistent data structures require…",{"value":139,"source":71,"evidence":140},"How does it compare to immer",[141],{"id":135,"by":136,"text":137},[143,151,158,165],{"value":144,"source":71,"evidence":145},"immer (C++ persistent data structures)",[146,147],{"id":135,"by":136,"text":137},{"id":148,"by":149,"text":150},"36675322","vinkelhake","If you're interested in persistent data structures for C++, then I highly recommend Immer. High quality and easy to work with. https:\u002F\u002Fgithub.com\u002Farximboldi\u002Fimmer",{"value":152,"source":71,"evidence":153},"Crit-bit trees",[154],{"id":155,"by":156,"text":157},"36676218","commandersaki","Are these the same as Crit-bit trees [0]? [0]: https:\u002F\u002Fcr.yp.to\u002Fcritbit.html Edit: I think I understand now from the design section on your page, they are both tries, but the…",{"value":159,"source":71,"evidence":160},"Swiss Tables",[161],{"id":162,"by":163,"text":164},"36675361","nnx","how does HAMTs compare with more recent designs like Swiss Tables? [1] [1] https:\u002F\u002Fabseil.io\u002Fabout\u002Fdesign\u002Fswisstables",{"value":166,"source":71,"evidence":167},"Boehm GC for memory management",[168],{"id":169,"by":170,"text":171},"36676235","magicalhippo","> How does your implementation handle that? This is explained in the readme[1]. You can pass custom allocation functions (mallic, realloc, free), so you can plug in Boehm fex.…",{"comments":45,"answered":38,"key":173},[174,177,180],{"id":175,"text":176},"36687188","Beautiful, thanks!",{"id":178,"text":179},"36686880","Thank you, happy to share. These are excellent pointers. Regarding the batch construction, it's not immediately clear to me how to implement sorting since the order is implicit…",{"id":181,"text":182},"36686950","Thanks! Yes, basically log_64(n) vs. log_32(n) and it would also require to switch to a 64 bit hash function and adjust hash exhaustion and bit fiddling arithmetic accordingly.…",{"commenters":184,"max_depth":33,"maker_replies":45,"first_comment_mins":185,"lifespan_hours":186},36,37,70,[188,190,192,195,197,200,203,206,209,212,214,216,219,223,225,228,231,233,235,237,238,241,243,246,247,249,252,254,256,258,260,264,267,270,272,274,277,279,280,283,286,288,291,294,296,298,301,304,308,310,313,316,319,323,328,330],[89,32,45,189,90,32],"project\u002Fpositive\u002Fidea",[101,38,40,191,102,32],"project\u002Fneutral\u002Fdesign",[193,38,40,191,194,32],"36674119","david2ndaccount",[196,38,40,191,102,32],"36674280",[198,38,40,191,199,32],"36674462","cataphract",[201,38,32,202,102,32],"36675558","other\u002Fneutral\u002Fnone",[204,38,32,202,205,32],"36675647","pixelpoet",[207,38,32,202,208,32],"36678114","jjgreen",[210,38,32,202,211,32],"36675908","inopinatus",[213,38,40,191,199,32],"36681255",[175,38,32,215,11,38],"maker\u002Fpositive\u002Fnone",[217,38,38,218,199,32],"36688825","project\u002Fcritical\u002Fexecution",[220,38,38,221,222,32],"36674390","project\u002Fcritical\u002Fdesign","torstenvl",[224,38,40,191,83,32],"36676044",[226,38,32,227,222,32],"36702039","commenter\u002Fneutral\u002Fnone",[229,38,40,191,230,32],"36677231","dataflow",[232,38,38,221,128,32],"36678583",[234,38,40,191,199,32],"36674428",[236,38,40,191,128,32],"36675884",[109,38,38,221,83,32],[239,38,40,191,240,32],"36676623","hgs3",[242,38,40,191,83,32],"36687866",[244,38,40,191,245,32],"36677406","flohofwoe",[105,38,40,191,106,32],[248,38,40,191,245,32],"36677350",[93,250,45,251,94,32],2,"project\u002Fpositive\u002Fexecution",[178,250,32,253,11,38],"maker\u002Fneutral\u002Fexecution",[255,250,40,253,94,32],"36687157",[135,40,40,257,136,32],"project\u002Fneutral\u002Fnone",[169,40,40,259,170,32],"project\u002Fneutral\u002Fdocs",[261,40,40,262,263,32],"36676531","project\u002Fneutral\u002Fexecution","dumdumchan",[265,40,32,227,266,32],"36676934","aidenn0",[268,40,32,227,269,32],"36678005","vkazanov",[271,40,32,227,266,32],"36682204",[155,37,40,273,156,32],"project\u002Fneutral\u002Fidea",[275,37,40,273,276,32],"36676377","silasdavis",[278,37,45,189,156,32],"36678890",[162,45,40,273,163,32],[281,45,40,273,282,32],"36675523","cbarrick",[284,45,40,259,285,32],"36688246","naasking",[287,45,32,227,282,32],"36714496",[289,45,32,227,290,32],"36678159","masklinn",[78,292,45,293,79,32],6,"project\u002Fpositive\u002Fdocs",[115,33,38,295,116,32],"project\u002Fcritical\u002Fperformance",[181,33,32,297,11,38],"maker\u002Fneutral\u002Fperformance",[299,30,45,189,300,32],"36679961","fsloth",[148,302,38,303,149,32],9,"project\u002Fcritical\u002Fidea",[305,306,45,293,307,32],"36714529",10,"photon_lines",[127,309,40,191,128,32],11,[311,309,32,312,11,38],"36686961","maker\u002Fneutral\u002Fdesign",[314,18,45,189,315,32],"36676557","robbintt",[82,317,38,318,83,32],13,"project\u002Fcritical\u002Fdocs",[320,321,40,262,322,32],"36678113",14,"query2",[324,325,40,326,327,32],"36679199",15,"maker\u002Fneutral\u002Fnone","bionhoward",[329,325,32,326,11,38],"36687072",[74,331,45,293,75,32],16,[],[334,339,343,348,352,357],{"id":335,"name":336,"points":337,"category":338},"36662655","Workout.lol",993,"consumer_social",{"id":340,"name":341,"points":342,"category":338},"36686672","LandCamp",348,{"id":344,"name":345,"points":346,"category":347},"36627112","hackernews-personal-blogs",281,"learning_science",{"id":349,"name":350,"points":351,"category":338},"36613727","Blogs.hn",224,{"id":353,"name":354,"points":355,"category":356},"36676415","Laser",218,"games",{"id":358,"name":359,"points":360,"category":361},"36667374","Danswer",189,"ai",false,"v2",{"id":365,"name":5,"line":6,"ai":362,"cat":20,"year":13,"points":14,"comments":15,"rec":27,"s":366,"top":18,"kw":367,"maker":11,"domain":10,"tier":19,"attempts":32,"strip":368,"url":9,"mix":369,"praise":70,"objection":98,"sub":21},36672957,0.13,[5,24,25,26],"5333000311031313335333303353305151505135",[30,31,32,33],1793991069163]