[{"data":1,"prerenderedAt":345},["ShallowReactive",2],{"project-39750077":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":29,"sentiment":30,"stance_mix":31,"scored_comments":36,"aspects":37,"strip":44,"post_text":45,"what":46,"said":70,"maker_in_thread":156,"shape":167,"grid":170,"attempts":307,"same_week":308,"maker_shows":39,"maker_hidden":337,"reader_version":338,"card":339},"39750077","sweep.dev","File-based cache for slow Python functions","title","Show HN: File-based cache for slow Python functions","https:\u002F\u002Fdocs.sweep.dev\u002Fblogs\u002Ffile-cache","docs.sweep.dev","williamzeng0",1710796331,2024,73,57,1041,3515,30,"notable","dev_tools","caching decorator","library",[24,25,26,27,28],"python cache","function memoization","file cache","python decorator","disk cache","curious",-0.148,{"positive":32,"neutral":33,"mixed":34,"critical":35},1,10,0,5,16,{"execution":38,"performance":40,"idea":42,"design":43},{"positive":32,"critical":39},2,{"positive":34,"critical":41},3,{"positive":34,"critical":34},{"positive":34,"critical":34},[41,34,34,34,41,41,34,34,34,34,34,34,34,34,41,34,34,34,34,34,34,34,34,41,41,32,32,34,41,34,34,35,32,34,34,32,34,41,34,34],null,{"problem":47,"audience":62,"pricing":45,"motivation":45,"time_to_build":45,"stack":68,"openness":69,"stage":69,"team_size":69},{"value":48,"source":49,"evidence":50},"Avoids re-running slow Python functions during development, such as LLM calls","maker",[51,54,58],{"id":52,"by":11,"text":53},"39750491","I think the marginal gain would be a lot less for Jupyter notebooks, but I've definitely rerun individual cells and wasted time there before. I think it could help if you forget…",{"id":55,"by":56,"text":57},"39756344","canadiantim","I'm sure this is a stupid question, but why is it much better to be caching LLM functions during development?",{"id":59,"by":60,"text":61},"39755160","wildermuthn","If you aren’t caching LLM functions during development, then you’re an even greater glutton for punishment than the normal engineer. My local file cache Python decorator also…",{"value":63,"source":49,"evidence":64},"Python developers, especially those running LLM workflows in single-process scripts",[65],{"id":66,"by":11,"text":67},"39757699","Thread safety is a big issue with ours, we'll run into issues when two different processes attempt to write to the same location, or we'll get a bad read. This is a better…",[],"unknown",{"praise":71,"objections":80,"requests":102,"questions":117,"alternatives":133},[72],{"value":73,"source":74,"evidence":75},"Simple and clean implementation","commenter",[76],{"id":77,"by":78,"text":79},"39750458","skp1995","This is a pretty good implementation. I like the simplicity of it, reminds me of SQLite backed storage decorators we used to have, where the data was persisted to a DB instead of…",[81,91,98],{"value":82,"source":74,"evidence":83},"Cache key ignores dependency changes, so stale results can be returned",[84,88],{"id":85,"by":86,"text":87},"39756201","epr","``` def hash_code(code): return hashlib.md5(code.encode()).hexdigest() ``` Be warned. The above function is used as part of the hash. The ostensible purpose is to prevent using…",{"id":89,"by":86,"text":90},"39758650","> How do you suggest one might fix that issue? Also pin the cache to a hash of all dependency versions? Pretty much. Recursively collect dependencies by analyzing the AST of the…",{"value":92,"source":74,"evidence":93},"md5 hashing is slow and a poor choice",[94],{"id":95,"by":96,"text":97},"39758341","chlorion","Using md5 for this seems like an odd choice. Sha1 is a better choice even for non-cryptographic use cases, it's quite a bit faster than md5. Even better would be something like…",{"value":99,"source":49,"evidence":100},"Not thread or process safe for concurrent writes",[101],{"id":66,"by":11,"text":67},[103,110],{"value":104,"source":74,"evidence":105},"Make kwargs order-independent in cache keys",[106],{"id":107,"by":108,"text":109},"39755629","mpeg","I recently wrote a version of this that I use in my projects, some things I do differently that you may or may not care about: - from your code it seems you're not sorting…",{"value":111,"source":74,"evidence":112},"Add a version parameter to the decorator for deliberate invalidation",[113],{"id":114,"by":115,"text":116},"39757602","Karellen","I feel like adding an argument to the decorator that labels the \"version\" of the function would make deliberate cache invalidation more straightforward for cache users.",[118,129],{"value":119,"source":74,"evidence":120},"How it differs from diskcache and joblib Memory",[121,125],{"id":122,"by":123,"text":124},"39754972","rmholt","I have extensively used https:\u002F\u002Fpypi.org\u002Fproject\u002Fdiskcache\u002F. Is there a reason you decided to make an in house solution?",{"id":126,"by":127,"text":128},"39759088","rassibassi","What's the difference to using joblibs Memory class similar to this implementation: https:\u002F\u002Fgithub.com\u002Fstanfordnlp\u002Fdspy\u002Fblob\u002Fmain\u002Fdsp\u002Fmodules\u002Fcache_utils.py",{"value":130,"source":74,"evidence":131},"Whether it handles thundering herd problem",[132],{"id":77,"by":78,"text":79},[134,142,149],{"value":135,"source":74,"evidence":136},"diskcache",[137,138],{"id":122,"by":123,"text":124},{"id":139,"by":140,"text":141},"39755185","akx","You'll be happy to know that Diskcache is backed by SQLite (and\u002For spill files for large enough (size configurable) blobs).",{"value":143,"source":74,"evidence":144},"joblib Memory",[145,146],{"id":126,"by":127,"text":128},{"id":147,"by":127,"text":148},"39760152","The diskcache docs state: \"\"\" Caching Libraries ``` joblib.Memory provides caching functions and works by explicitly saving the inputs and outputs to files. It is designed to…",{"value":150,"source":74,"evidence":151},"Hishel",[152],{"id":153,"by":154,"text":155},"39794956","quickslowdown","I write some toy Python scripts\u002Fapps for a couple APIs (the Pokeapi, Spacetraders, etc). I use the HTTPX library as a request client, and wasn't aware of the Hishel library for…",{"comments":157,"answered":158,"key":159},15,4,[160,163,166],{"id":161,"text":162},"39757613","Making the __dict__ opt-in makes it a lot more user-friendly at the expense of a little verbosity. That makes sense. These tips make sense, we often use named args in our…",{"id":164,"text":165},"39758324","This is great, thanks for the suggestion! We've just updated our docs and code with this change: https:\u002F\u002Fgithub.com\u002Fsweepai\u002Fsweep\u002Fpull\u002F3332",{"id":66,"text":67},{"commenters":18,"max_depth":35,"maker_replies":157,"first_comment_mins":168,"lifespan_hours":169},22,213,[171,173,177,180,183,185,188,190,192,195,198,199,201,204,205,209,212,215,216,219,222,226,228,230,232,235,237,239,241,243,244,246,248,250,252,254,256,260,263,266,267,270,271,273,277,280,283,286,289,291,292,293,296,298,302,303,305],[107,34,41,172,108,34],"project\u002Fneutral\u002Fexecution",[174,34,34,175,176,34],"39755870","commenter\u002Fneutral\u002Fnone","AlecSchueler",[178,34,34,175,179,34],"39755900","oulipo",[181,34,34,175,182,34],"39755908","by_the_bay",[161,34,34,184,11,32],"maker\u002Fneutral\u002Fexecution",[186,34,41,187,108,34],"39757898","project\u002Fneutral\u002Fperformance",[164,34,34,189,11,32],"maker\u002Fpositive\u002Fexecution",[122,32,41,191,123,34],"project\u002Fneutral\u002Fidea",[193,32,34,194,154,34],"39754986","other\u002Fneutral\u002Fnone",[196,32,34,194,197,34],"39755052","dotancohen",[139,32,34,175,140,34],[200,32,34,194,123,34],"39756171",[202,32,34,194,203,34],"39756816","p10_user",[153,32,34,194,154,34],[206,32,34,207,208,34],"39755164","other\u002Fneutral\u002Fperformance","varispeed",[210,32,34,207,211,34],"39755190","BiteCode_dev",[213,32,34,207,214,34],"39755263","Twirrim",[66,32,34,187,11,32],[217,32,34,194,218,34],"39755712","anentropic",[220,32,41,191,221,34],"39756463","CGamesPlay",[223,32,34,224,225,34],"39756680","other\u002Fneutral\u002Fidea","nicwolff",[227,32,34,194,11,32],"39757432",[229,32,34,191,11,32],"39757412",[231,32,34,194,123,34],"39757870",[233,32,34,234,11,32],"39758367","maker\u002Fpositive\u002Fnone",[59,39,34,236,60,34],"commenter\u002Fneutral\u002Fidea",[238,39,34,175,108,34],"39755747",[240,39,34,175,176,34],"39755881",[242,39,34,175,108,34],"39756055",[55,39,34,194,56,34],[245,39,34,194,203,34],"39756849",[247,39,34,187,11,32],"39757455",[114,39,41,249,115,34],"project\u002Fneutral\u002Fdesign",[251,39,34,249,11,32],"39757844",[253,39,41,249,115,34],"39758635",[255,39,34,234,11,32],"39758775",[257,41,32,258,259,34],"39759800","project\u002Fcritical\u002Fperformance","rthnbgrredf",[261,41,32,258,262,34],"39761968","kevinlu1248",[264,158,34,236,265,34],"39842452","andrewgazelka",[126,35,41,191,127,34],[268,35,41,191,269,34],"39759836","khaledh",[147,35,34,194,127,34],[272,35,34,194,11,32],"39760777",[274,275,34,236,276,34],"39762880",6,"emilehere",[77,278,35,279,78,34],7,"project\u002Fpositive\u002Fexecution",[281,278,34,282,11,32],"39750550","maker\u002Fneutral\u002Fperformance",[85,284,32,285,86,34],8,"project\u002Fcritical\u002Fexecution",[287,284,34,175,288,34],"39756492","martinky24",[290,284,34,172,11,32],"39757668",[89,284,32,285,86,34],[95,284,32,258,96,34],[294,284,34,295,11,32],"39758777","maker\u002Fneutral\u002Fnone",[297,284,41,187,96,34],"39759151",[299,300,41,191,301,34],"39750329",9,"kapilsinha",[52,300,34,191,11,32],[304,300,34,194,203,34],"39756877",[306,300,34,194,11,32],"39757682",[],[309,314,318,323,328,332],{"id":310,"name":311,"points":312,"category":313},"39706004","Skyvern",422,"ai",{"id":315,"name":316,"points":317,"category":20},"39759325","jnv",373,{"id":319,"name":320,"points":321,"category":322},"39756325","Godspeed",328,"productivity",{"id":324,"name":325,"points":326,"category":327},"39714053","algebraic-nnhw",310,"hardware",{"id":329,"name":330,"points":331,"category":20},"39770908","GritQL",280,{"id":333,"name":334,"points":335,"category":336},"39755858","Causal 2.0",261,"web_saas",false,"v2",{"id":340,"name":5,"line":6,"ai":337,"cat":20,"year":13,"points":14,"comments":15,"rec":29,"s":341,"top":18,"kw":342,"maker":11,"domain":10,"tier":19,"attempts":34,"strip":343,"url":9,"mix":344,"praise":73,"objection":82,"sub":21},39750077,-0.15,[24,25,26,27,28],"3000330000000030000000033110300510010300",[32,33,34,35],1794036651419]