08:25 < ws-client> **** yea all servers hexagoupled ram usage over night just the gperf server did not increase by a single bit 08:26 < ws-client> **** i wonder if my old friend `2025-12-07 00:19:40 I mysql: can't free last result (free_result:stmt:5025): Statement has no result set` is related 08:26 < ws-client> **** @blaiszephyr u figured it out? xd 08:26 < ws-client> **** is there a chance than asan+gdb causes memleaks on its own? 08:27 < ws-client> **** ah wait never mind i even had a test server running without asan gdb or gperf and it leaked too 08:35 < bridge> <0xdeen> Sounds like you don't have a memory leak, but some data structure that keeps growing but isn't supposed to 08:35 < ws-client> **** yea i think so too i keep calling it a leak tho :D 08:36 < ws-client> **** or do you have a sexy term to replace it? 08:36 < bridge> <0xdeen> So the memory is still reachable, you could use something like massif and keep it running for a while to check where the memory is used 08:36 < ws-client> **** memory hog? xd 08:36 < ws-client> **** i was hoping gperf would do that 08:37 < ws-client> **** but since its not collecting memory with it i might actually try massif next 08:37 < bridge> <0xdeen> > gperf is a perfect hash function generator 08:37 < bridge> <0xdeen> ? 08:37 < ws-client> **** ah wait 08:37 < ws-client> **** the link robsi sent its some google tool sec 08:37 < ws-client> **** https://gperftools.github.io/gperftools/heapprofile.html 08:38 < ws-client> **** looks similar to massif its also just some kind of profiler 08:38 < ws-client> **** its just every time i am watching the memory stays low :D 08:38 < ws-client> **** but im not giving up yet! 08:38 < bridge> <0xdeen> Yeah, tcmalloc can do that, jemalloc too. Maybe a race condition 08:38 < ws-client> **** i even dumped the ram once :D 08:39 < ws-client> **** turns out i had 321489 occurences of the string `1(i0` in my ram. not sure what that means xd 10:42 < bridge> hmm what process even safes new strings 10:44 < bridge> thats the wrong approach probably 11:09 < ws-client> **** its raw ram so it might not be a string just something that happens to be representable as string 11:09 < ws-client> **** pushing into an vector of std::strings does that 11:35 < bridge> no D: 11:35 < bridge> i gave up after spending close to 10 hours on finding the cure 12:14 < bridge> @sedonya: new big ass pr 12:14 < bridge> 1k commits again just 3 days later lol 12:20 < ws-client> **** yea looks like massif is also not collecting ram -. 12:32 < bridge> Wdym not collecting ram? 12:32 < bridge> Its usage doesn’t grow when observed 12:33 < bridge> Ah a heisenbug, yeah have fun 😄 12:35 < bridge> Map changes maybe? 12:41 < bridge> I’d just try the tcmalloc heap profiler I guess, massif has massive overhead. Just let it run with tcmalloc until it does one day leak, then get a profile with a signal 12:42 < bridge> massif has... *massif* overhead ba dum tsss 12:42 < bridge> massif has... *massif* overhead. ba dum tsss 12:54 < bridge> Thank you, the last PR will be especially useful, check wire 12:55 < ws-client> **** massif and tcmalloc both fix the leak tho 12:56 < ws-client> **** i run both right now 12:56 < bridge> Are you sure they “fix” it? Is it immediately obvious that the memory usage gets higher without them? 12:56 < ws-client> **** yes 12:57 < ws-client> **** other servers rise to 11% memory usage in a day 12:57 < ws-client> **** this one is flat at 0.8% since yesterday 12:57 < ws-client> **** but ye maybe im impatient 12:57 < bridge> And people played on the server? 12:57 < ws-client> **** ima wait a few more days 12:58 < ws-client> **** servers i thought were empty also collected but i dont have proper statistics 12:58 < ws-client> **** im a bit scared at some point my vps dies with full disk because of all this logging xd 12:59 < bridge> I mean either of those things “fixing” something like this is a tad on the insane side. Some weird race condition, or maybe a bug inside glibc somehow. You can I guess also dump out the heap from a server that has grown in memory usage and just stare at it real hard 13:00 < ws-client> **** i dumped the heap 13:00 < ws-client> **** but not sure what im looking at xd 13:01 < ws-client> **** i looked at strings xd https://github.com/ddnet-insta/ddnet-insta/issues/267#issuecomment-3620627728 13:01 < bridge> Yeah it would be quite hard to figure out what where is just by looking at it, you are sort of hoping for obvious stuff like strings around e.g. 13:02 < ws-client> **** thats where heinrichs gdb command comes into play 13:02 < ws-client> **** if he can patch maps with gdb while a tournament is running he can also tell me which code allocated all the ram 13:03 < bridge> He can’t, that information is not tracked 13:03 < ws-client> **** sadge 13:03 < ws-client> **** if only there was still magnuses memory manager 13:03 < bridge> That’s what the profilers do, they instrument free/malloc/new then keep track of what allocated what 13:03 < ws-client> **** in the good old days there was no `std::` or `new` and `delete` 13:04 < bridge> That’s what the profilers do, they instrument free/malloc/new/delete then keep track of what allocated what 13:04 < ws-client> **** there was the teeworlds engine memory allocator 13:04 < bridge> We used to avoid heap memory like the plague 😄 13:04 < ws-client> **** should go back to that 13:05 < ws-client> **** okay i will slap profiler on my most played on server now 13:05 < ws-client> **** tcmalloc or massif? 13:05 < ws-client> **** or memcheck? 13:06 < ws-client> **** massif it is 13:07 < bridge> Your dump memory script you used seems to dump way more than just the heap btw 13:07 < ws-client> **** oke xd 13:07 < ws-client> **** ye it took forver to dump 13:07 < ws-client> **** and contained all sorts of nudes 13:07 < bridge> Maybe just dump the heap and you might find patterns easier, we are pretty much sure it’s not something else that is leaking 13:08 < ws-client> **** wat about stack leak? 13:08 < bridge> Stack can’t really “leak” 13:08 < ws-client> **** also idk how to only dump heap i copied this from stackoverflow 13:08 < ws-client> **** @learath2 tell that to my assembly code xd 13:09 < bridge> In /proc//maps there is a memory region marked [heap] 13:09 < bridge> Maybe you can just add a `grep heap` to the script you used right before the sed 😄 13:10 < ws-client> **** lel lemme try 13:11 < bridge> Also another question, does it keep growing as you keep the server on? 13:11 < ws-client> **** yes 13:11 < ws-client> **** until OOM 13:12 < bridge> Ok, just wanted to make sure, because it just could have been the max size and for whatever reason glibc malloc just wasn’t feeling like returning the memory to the OS 13:13 < bridge> just restart the server every 10 finishes 13:13 < bridge> Ok these are all the easy-ish ideas I can think of rn, so try all these and if you still can’t find it we can talk about patching glibc to hack in a profiler 😛 13:13 < ws-client> **** i wonder how feasible it is to just look at the code xd 13:14 < bridge> I really can’t imagine it not happening under massif though, the way it hooks stuff it shouldn’t ever change behaviour unless a race is involved 13:14 < ws-client> **** yea lets give it another day to grow 13:14 < bridge> If you can find a version where it doesn’t happen, you can bisect for it 13:15 < ws-client> **** bisecting will be uselessly slow tho 13:15 < ws-client> **** i cant detect it on launch 13:15 < bridge> I mean if it’s like 30 commits it will only take you 5 days 😄 13:16 < ws-client> **** i cant really run non forward compatible breaking db changes 13:16 < ws-client> **** oh there is only one heap segment 13:16 < ws-client> **** much faster 13:16 < bridge> Also you can stare at the changes between the 2 commits if you do find one good commit 13:16 < ws-client> **** also it doesnt seem to need root idk why once i got permission errors 13:17 < bridge> Probably because you tried to dump the vdso 13:17 < ws-client> **** yea i think diff isnt the way i noticed the first mem leak in feb 13:19 < ws-client> **** https://paste.zillyhuhn.com/e5 13:19 < ws-client> **** cant make any sense out of it 13:22 < bridge> I doubt just looking at strings would work in this case, you’ll need to get in there with a hex editor, maybe some statistical analysis to look for repeating patterns of bytes 13:22 < bridge> Gtg, need to craft food 13:26 < bridge> Please check out https://twmap.patiga.eu/info and https://twmap.patiga.eu/fix, two twmap tools to get some infos about a map and to fix maps which are not loadable by tmwap. The web pages are again static, so your maps aren't uploaded to anywhere :) 13:36 < bridge> can someone with good cpu run my today's aoc code, it takes too much time on my laptop xdd 13:37 < ws-client> **** send 13:38 < ws-client> **** or push i guess https://github.com/MilkeeyCat/aoc 13:39 < ws-client> **** i need input too 13:39 < bridge> Here's `input` file 13:39 < bridge> https://cdn.discordapp.com/attachments/293493549758939136/1447205926300942457/message.txt?ex=6936c70c&is=6935758c&hm=1027c597b1e988a9863853a6ee815601a91c4869ec48e7df371a5c7636c277d4& 13:39 < ws-client> **** both parts? 13:40 < bridge> part 2 xd 13:41 < ws-client> **** it uses 1 core bruv 13:41 < ws-client> **** thats why i focussed on single core speed when selecting a cpu xd 13:43 < ws-client> **** where loading bar xd 13:43 < bridge> hm? 13:44 < ws-client> **** i see no progress xd 13:44 < bridge> me neither 13:44 < bridge> it's been 20 mins and it's still running 13:44 < bridge> i hope it doesn't have a bug xd 13:48 < ws-client> **** idk if this is going anywhere 13:48 < ws-client> **** i tried to add dbg prints to build progress bar but recursion is too complicated xd 13:51 < ws-client> **** i tried to print the depth and it only seems to be growing xd 13:51 < ws-client> **** u sure this works? 13:51 < bridge> it works on a simple input 13:51 < bridge> ``` 13:52 < bridge> .......S....... 13:52 < bridge> ............... 13:52 < bridge> .......^....... 13:52 < bridge> ............... 13:52 < bridge> ......^.^...... 13:52 < bridge> ............... 13:52 < bridge> .....^.^.^..... 13:52 < bridge> ............... 13:52 < bridge> ....^.^...^.... 13:52 < bridge> ............... 13:52 < bridge> ...^.^...^.^... 13:52 < bridge> ............... 13:52 < bridge> ..^...^.....^.. 13:52 < bridge> ............... 13:52 < bridge> .^.^.^.^.^...^. 13:52 < bridge> ............... 13:52 < bridge> ``` 13:54 < ws-client> **** wait 13:54 < ws-client> **** i got progress bar 13:56 < ws-client> **** okay i restarted run 13:56 < ws-client> **** its already declining the depth 13:56 < ws-client> **** so only 18446744073702000000 left to go 13:57 < bridge> :justatest: t 13:57 < bridge> :justatest: 13:57 < ws-client> **** number looks big tho 13:57 < ws-client> **** 18446744073666000000 13:57 < ws-client> **** 18446744073660000000 13:57 < ws-client> **** 18446744073653000000 13:58 < ws-client> **** 18446744073644000000 13:58 < bridge> <01000111g> is aoc fun? 13:58 < ws-client> **** im not that strong in maffs stuff 13:59 < ws-client> **** but i have the feeling that this wont finish fast enuff 13:59 < bridge> These numbers are suspiciously close to max size_t value -.- 13:59 < ws-client> **** oh yea i used uint64_t for the counter xd 14:01 < ws-client> **** oke i stopped now 14:02 < ws-client> **** even perfect multi thread with 32x speed would not finish during my lifetime i guess 14:03 < bridge> Thanks for trying to run it :) 14:17 < bridge> fwiw aoc rarely ever has computationally intensive questions from what I remember 14:18 < bridge> i wanted to get the answer using my stupid code, but it won't work with such a big input :\ 14:18 < bridge> your algorithm must be suboptimal, this looks like || it should be solved with dfs and memoization|| 14:20 < bridge> actually || dynamic programming is a better keyword here I guess|| 14:22 < bridge> okay, I added an `std::unoredered_map` which stores previously computed values and it doesn't take ages(the answer is wrong tho xd) 14:22 < bridge> something like || go down as far as you can, recurse at `^`s, remember stuff || 😄 14:22 < bridge> something like || go down as far as you can, recurse left and right at `^`s, remember stuff || 😄 14:24 < bridge> ah, it doesn't work like that :p 14:29 < bridge> ```cpp 14:29 < bridge> size_t magic(std::vector &Diagram, std::unordered_map, size_t> &memo, size_t i, size_t j) { 14:29 < bridge> if(auto s = memo.find(std::make_pair(i,j)); s != memo.end()) 14:29 < bridge> return s.second; 14:30 < bridge> 14:30 < bridge> while(Diagram[i][j] == '.') { 14:30 < bridge> i++; 14:30 < bridge> if(i == Diagram.size()) { 14:30 < bridge> memo[std::make_pair(i, j)] = 1; 14:30 < bridge> return 1; 14:30 < bridge> } 14:30 < bridge> } 14:30 < bridge> return magic(i, j - 1) + magic(i, j + 1); 14:30 < bridge> } 14:30 < bridge> ``` 14:30 < bridge> 14:30 < bridge> I think this sounds about right to me 14:30 < bridge> ```cpp 14:30 < bridge> size_t magic(std::vector &Diagram, std::unordered_map, size_t> &memo, size_t i, size_t j) { 14:30 < bridge> if(auto s = memo.find(std::make_pair(i,j)); s != memo.end()) 14:30 < bridge> return s.second; 14:30 < bridge> 14:30 < bridge> while(Diagram[i][j] == '.') { 14:30 < bridge> i++; 14:30 < bridge> if(i == Diagram.size()) { 14:30 < bridge> memo[std::make_pair(i, j)] = 1; 14:30 < bridge> return 1; 14:30 < bridge> } 14:30 < bridge> } 14:30 < bridge> return magic(i, j - 1) + magic(i, j + 1); 14:30 < bridge> } 14:30 < bridge> ``` 14:30 < bridge> I think this sounds about right to me 14:30 < bridge> ```cpp 14:30 < bridge> size_t magic(std::vector &Diagram, std::unordered_map, size_t> &memo, size_t i, size_t j) { 14:31 < bridge> if(auto s = memo.find(std::make_pair(i,j)); s != memo.end()) 14:31 < bridge> return s.second; 14:31 < bridge> 14:31 < bridge> while(Diagram[i][j] == '.') { 14:31 < bridge> i++; 14:31 < bridge> if(i == Diagram.size()) { 14:31 < bridge> memo[std::make_pair(i, j)] = 1; 14:31 < bridge> return 1; 14:31 < bridge> } 14:31 < bridge> } 14:31 < bridge> 14:31 < bridge> size_t res = magic(i, j - 1) + magic(i, j + 1); 14:31 < bridge> memo[std::make_pair(i, j)] = res; 14:31 < bridge> return res; 14:31 < bridge> } 14:31 < bridge> ``` 14:31 < bridge> I think this sounds about right to me 14:31 < bridge> Making a std unordered_map actually work with a std pair is left as an exercise to the reader 😛 14:31 < bridge> ```cpp 14:31 < bridge> size_t magic(std::vector &Diagram, std::unordered_map, size_t> &memo, size_t i, size_t j) { 14:31 < bridge> if(auto s = memo.find(std::make_pair(i,j)); s != memo.end()) 14:31 < bridge> return s.second; 14:31 < bridge> 14:31 < bridge> while(Diagram[i][j] == '.') { 14:31 < bridge> if(++i == Diagram.size()) { 14:31 < bridge> memo[std::make_pair(i, j)] = 1; 14:31 < bridge> return 1; 14:31 < bridge> } 14:32 < bridge> } 14:32 < bridge> 14:32 < bridge> size_t res = magic(i, j - 1) + magic(i, j + 1); 14:32 < bridge> memo[std::make_pair(i, j)] = res; 14:32 < bridge> return res; 14:32 < bridge> } 14:32 < bridge> ``` 14:32 < bridge> I think this sounds about right to me 14:32 < bridge> Making a std unordered_map actually work with a std pair key is left as an exercise to the reader 😛 14:33 < bridge> ||```cpp 14:33 < bridge> size_t magic(std::vector &Diagram, std::unordered_map, size_t> &memo, size_t i, size_t j) { 14:33 < bridge> if(auto s = memo.find(std::make_pair(i,j)); s != memo.end()) 14:33 < bridge> return s.second; 14:33 < bridge> 14:33 < bridge> while(Diagram[i][j] == '.') { 14:33 < bridge> if(++i == Diagram.size()) { 14:33 < bridge> memo[std::make_pair(i, j)] = 1; 14:33 < bridge> return 1; 14:33 < bridge> } 14:33 < bridge> } 14:33 < bridge> 14:33 < bridge> size_t res = magic(i, j - 1) + magic(i, j + 1); 14:33 < bridge> memo[std::make_pair(i, j)] = res; 14:33 < bridge> return res; 14:33 < bridge> } 14:33 < bridge> ```|| 14:33 < bridge> I think this sounds about right to me 14:35 < bridge> ||```cpp 14:35 < bridge> size_t magic(std::vector &Diagram, std::unordered_map, size_t> &memo, size_t i, size_t j) { 14:35 < bridge> if(auto s = memo.find(std::make_pair(i,j)); s != memo.end()) 14:35 < bridge> return s.second; 14:35 < bridge> 14:35 < bridge> while(Diagram[i][j] == '.') { 14:35 < bridge> if(++i == Diagram.size()) { 14:35 < bridge> memo[std::make_pair(i, j)] = 1; 14:35 < bridge> return 1; 14:35 < bridge> } 14:35 < bridge> } 14:35 < bridge> 14:35 < bridge> size_t res = magic(Diagram, memo, i, j - 1) + magic(Diagram, memo, i, j + 1); 14:35 < bridge> memo[std::make_pair(i, j)] = res; 14:36 < bridge> return res; 14:36 < bridge> } 14:36 < bridge> ```|| 14:36 < bridge> I think this sounds about right to me 14:55 < bridge> https://github.com/MilkeeyCat/aoc/blob/2d1a9b833771e13bf3809fd9b5ff602e72a49bdb/2025/day7/part2.cpp#L10-L63 my solution is not that pretty but it works xd 14:56 < bridge> One `unordered_map` saved sooo much time 14:56 < bridge> I solved today's problem in excel so yeah 14:57 < bridge> you can just |||| 14:58 < bridge> you don't even need to ||memoize anything||, you can just ||assign a 1 to each of the bottom | characters and then go up from bottom to top, and sum the left and right "child" of each ^|| 15:03 < bridge> Yeah you can definitely do it || bottom up|| too 😄 16:31 < bridge> @kebscs I think we should make a video for the release for the scoreboard 18:21 < bridge> Weblate is awesome 18:21 < bridge> https://cdn.discordapp.com/attachments/293493549758939136/1447276892703949012/image.png?ex=69370924&is=6935b7a4&hm=34af1f8c87ebc5c95cb3d699d19a46e88b09ca60bcb36df17511d15eb07986c8& 20:07 < bridge> there is 1 already 20:07 < bridge> what else from the one posted in #announcements 20:29 < bridge> https://github.com/ddnet/ddnet/blob/050dbe925fc9046f69d2b3b7ad291328666ce650/src/game/client/components/menus_settings.cpp#L2768 20:29 < bridge> https://hosted.weblate.org/search/ddnet/ddnet/?q=show+background 23:07 < bridge> spec is also now there, just more obscure, but 🤷‍♂️