01:14 < PerfeCtion_> Hey 01:14 <+PerfeCtion_> Can someone help me changing small things in the teeworlds source? I already compiled it I just need some help please 01:17 <@heinrich5991> hello also from over here ;) ask your question and you might get an answer within a day or so ;) 01:23 <@heinrich5991> good night 03:03 <+PerfeCtion_> Okayy so in which cpp file can I do unlimited ammo? 03:14 <+PerfeCtion_> i found it out myself 03:14 <+PerfeCtion_> but how can i make the gun autoshoot? 03:28 <+PerfeCtion_> Heheee i got ittttt 03:38 <+PerfeCtion_> Oh mann Wie kann ich die shotgun mehr spread machen? 03:46 <+PerfeCtion_> i need the shotgun to spread more but it is acting weird i dont get it :/ 05:43 <+bridge> [ddnet] i guess you didn't add new direction for your bullets 05:43 <+bridge> [ddnet] i guess you didn't add new directions for your bullets 06:00 <+bridge> [ddnet] ChillerDragon: can we also get a script to remove paths automatically xd 06:39 <+bridge> [ddnet] bruh 06:39 <+bridge> [ddnet] https://cdn.discordapp.com/attachments/293493549758939136/810747146755899432/unknown.png 06:40 <+bridge> [ddnet] intel driver 06:42 <+bridge> [ddnet] using nvidia tho lol 06:42 <+bridge> [ddnet] it is probably the site that is broken 08:49 <+bridge> [ddnet] man these botters that ask for source code help are increasing exponentially lately 09:48 <+fokkonaut> Hey fstd 10:03 <+fstd> hi fokkonaut 10:09 <+fokkonaut> heinrich told me you have a 512 player server? Could you show me how you did the collision between tees? My server sometimes need up to 100% of the CPU, I did some local tests and think it is related to the collision code, e.g. CCharacterCore::Move() 10:19 <+fstd> oh well he's probably referring to http://penenen.de/twparticle.png 10:20 <+fstd> in no way shape or form i run such a server, that screenshot is at least 6-8 years old 10:20 <+bridge> [ddnet] oh true, i remember this 10:20 <+bridge> [ddnet] ohhh 10:20 <+fstd> and i didn't do anything special collision wise, it performed horribly at 512 10:20 <+fstd> in fact the lesson learned was 10:20 <+bridge> [ddnet] exactly 10:20 <+fstd> many tees needs ac ollision overhaul 10:21 <+fstd> quadtree maybe 10:21 <+bridge> [ddnet] well, i probably dont know how :D 10:22 <+fstd> the general idea is to group tees together that are physically close 10:23 <+fstd> that way you only have to check collisions against your group rather than everything 10:23 <+fstd> of course maintaining the groups has some overhead on its own 10:24 <+bridge> [ddnet] uhm.. 10:24 <+bridge> [ddnet] why is it even that expensive? 10:26 <+fstd> what collisions? 10:26 <+fokkonaut> yea 10:27 <+fstd> well because the vanilla approach checks every tee vs every other tee 10:27 <+fstd> so N tees -> N^2 checks 10:27 <+fstd> that gets costly as N grows 10:28 <+bridge> [ddnet] hm 10:30 <+fstd> (technically it only takes half the amount of checks as after checking X vs Y you don't have to check Y vs X 10:30 <+fstd> so there's a /2 in there somewhere 10:30 <+fstd> but that becomes insignificant as N grows as well 10:30 <+bridge> [ddnet] but for 128 players it should be possible to improve it, right? 10:31 <+fstd> IIRC 128 was right at the edge of becoming noticably nasty but still kinda playable (i only tested with dummies though, not with 128 real clients) 10:32 <+fstd> but yes for 128 players the naive approach really gets to its limits 10:33 <+bridge> [ddnet] well for my server i can say it usually works, i even had 128 clients connected 2-3 times, but in the past few days im facing problems more and more, where CPU usage goes up to 100% 10:33 <+bridge> [ddnet] i dont really know why it suddenly started to do that so often 10:33 <+bridge> [ddnet] the easiest you could do without changing source too much is replacing distance checks with squared distance 10:33 <+bridge> [ddnet] isnt distance already checked by squared distance? 10:34 <+bridge> [ddnet] oh in 0.7? i dunno ^^ 10:34 <+bridge> [ddnet] let me check it 10:34 <+fstd> fokkonaut: it's a little involved but a profiler would tell you what part is eating the CPU 10:35 <+bridge> [ddnet] @Jupstar ✪ sqrtf(a.x*a.x + a.y*a.y) 10:35 <+bridge> [ddnet] thats not squared 10:35 <+bridge> [ddnet] @Jupstar ✪ `sqrtf(a.x*a.x + a.y*a.y)` 10:35 <+bridge> [ddnet] its rooted 10:35 <+bridge> [ddnet] root function is expensive 10:35 <+bridge> [ddnet] ah lol 10:36 <+fstd> see this is the kind of thing you'd probably want to profile before changing 10:36 <+bridge> [ddnet] ChillerDragon tried to do that, but couldnt get it to work 10:36 <+bridge> [ddnet] i did some local tests with visual studio, and it looked like the distance function in CCharacterCore::Move (inside of the player <-> player loop) is very expensive 10:36 <+bridge> [ddnet] you could also compile with Ofast, then it optimizes floating calculations 10:37 <+fstd> okay 10:38 <+bridge> [ddnet] fstd: Jupstar: do you think you can help? 10:39 <+bridge> [ddnet] sqrt(9) == 3 10:39 <+bridge> [ddnet] becomes 10:39 <+bridge> [ddnet] 9 = 3*3 10:39 <+bridge> [ddnet] 10:39 <+bridge> [ddnet] so basically remove sqrt and instead increase the checks by ^ 2 10:40 <+bridge> [ddnet] but this is really only about optmizing the math a bit, fstd's approach of grouped physics will still be faster 10:44 <+bridge> [ddnet] last time i checked with Ofast vs O2 was about 10% performance increase, tho i didnt dig much deeper into what exactly is better 10:44 <+bridge> [ddnet] probs the static sized loops like MAX_CLIENTS 10:44 <+bridge> [ddnet] and maybe the floating point arithmetics 10:44 <+bridge> [ddnet] :D 10:44 <+bridge> [ddnet] creating a mod gets more complicated every time 11:20 <+bridge> [ddnet] I would really appreciate any help 11:20 <+bridge> [ddnet] with this specific lag problem 11:22 <+bridge> [ddnet] @Jupstar ✪ i will try the squared way< 11:33 <+bridge> [ddnet] @Jupstar ✪ `sqrtf(a.x*a.x + a.y*a.y)` 11:33 <+bridge> [ddnet] What do you I have to replace this with? 11:33 <+bridge> [ddnet] What do I have to replace this with? 11:57 <+bridge> [ddnet] We can all suggest optimizations but doubt anyone will know what to do without a profile 11:58 <+bridge> [ddnet] Locally with some server dummies I can see that its the distance function 11:58 <+bridge> [ddnet] What jupstar meant was to compare distances without sqrt which would work because sqrt is monotone increasing 11:58 <+bridge> [ddnet] I understood what he means, but not how to do it 11:58 <+bridge> [ddnet] (As long as we don't have negative coordinates, that will crash and burn) 11:59 <+bridge> [ddnet] oh wait, thats very important 11:59 <+bridge> [ddnet] I want to try it anyways 12:00 <+bridge> [ddnet] I don't think it would help significantly, check perf see how much of the time is spent on the sqrt 12:02 <+bridge> [ddnet] fstd was considering a quadtree which would help with much larger N but it's not trivial to implement. 12:05 <+bridge> [ddnet] I considered a precalculated BSP or spatial hashing (chunking) both are much easier to implement 12:08 <+bridge> [ddnet] I guess most engines now use a Bounding Volume Hierarchy though so that's also an option you can look into 12:09 <+bridge> [ddnet] Actually this will work just fine, sorry, just woke up 12:11 <+bridge> [ddnet] :D 12:11 <+bridge> [ddnet] Could you help me implement any of those ideas 12:13 <+bridge> [ddnet] If I had time to code anything I'd finish my own PRs 12:24 <+bridge> [ddnet] @fokkonaut You can try the trivial optimization of checking squared distance but I have a feeling gcc/clang already figures this out on it's own 12:26 <+bridge> [ddnet] hmm 12:27 <+bridge> [ddnet] I doubt that will do much though. I'd go straight to spatial hashing. You basically split the map into chunks and a hash function tells you which chunk you are in. When checking for collision you only check against other tees in your chunk 12:29 <+bridge> [ddnet] makes sense, but i doubt i can implement such thing 12:29 <+bridge> [ddnet] make a 2nd function called distance_squared 12:29 <+bridge> [ddnet] and change all affected calculations to the squared versions 12:30 <+bridge> [ddnet] i still dont know what i should calculate in there 12:31 <+bridge> [ddnet] e.g. 12:31 <+bridge> [ddnet] 12:31 <+bridge> [ddnet] ``` 12:31 <+bridge> [ddnet] float D = distance(Pos, pCharCore->m_Pos); 12:31 <+bridge> [ddnet] if(D < 28.0f && D >= 0.0f) 12:31 <+bridge> [ddnet] { 12:31 <+bridge> [ddnet] if(a > 0.0f) 12:31 <+bridge> [ddnet] m_Pos = LastPos; 12:31 <+bridge> [ddnet] else if(distance(NewPos, pCharCore->m_Pos) > D) 12:31 <+bridge> [ddnet] m_Pos = NewPos; 12:31 <+bridge> [ddnet] return; 12:31 <+bridge> [ddnet] } 12:31 <+bridge> [ddnet] ``` 12:31 <+bridge> [ddnet] gets 12:31 <+bridge> [ddnet] 12:31 <+bridge> [ddnet] ``` 12:31 <+bridge> [ddnet] float D = distance_squared(Pos, pCharCore->m_Pos); 12:31 <+bridge> [ddnet] if(D < 28.0f * 28.0f && D >= 0.0f) 12:31 <+bridge> [ddnet] { 12:31 <+bridge> [ddnet] if(a > 0.0f) 12:31 <+bridge> [ddnet] m_Pos = LastPos; 12:31 <+bridge> [ddnet] else if(distance_squared(NewPos, pCharCore->m_Pos) > D) 12:31 <+bridge> [ddnet] m_Pos = NewPos; 12:31 <+bridge> [ddnet] return; 12:31 <+bridge> [ddnet] } 12:31 <+bridge> [ddnet] ``` 12:31 <+bridge> [ddnet] i mean inside of that function... 12:31 <+bridge> [ddnet] remove sqrt 12:31 <+bridge> [ddnet] Well doesn't the name tell you what it is? 😄 12:31 <+bridge> [ddnet] but better create a 2nd function 12:32 <+bridge> [ddnet] Definitely create a 2nd function, changing it everywhere at once won't be fun 12:32 <+bridge> [ddnet] just retuirn `a.x*a.x + a.y*a.y` 12:32 <+bridge> [ddnet] lol 12:32 <+bridge> [ddnet] and that works without problems? 12:32 <+bridge> [ddnet] up to a certain point 12:32 <+bridge> [ddnet] Shouldn't be too hard btw, in CCharacterCore::Move instead of going thru all the tees, you only go thru tees in your and neighbouring chunks 12:35 <+bridge> [ddnet] how would i define where a chunk is and ends? 12:36 <+bridge> [ddnet] what are the boundaries? 12:36 <+bridge> [ddnet] When the squares get way too large 12:37 <+bridge> [ddnet] At some point floats will become too inaccurate 12:37 <+bridge> [ddnet] u shouldnt care too much i think, in theory u could also use doubles, bcs x87 uses 80bit precision internally 12:38 <+bridge> [ddnet] Also I think there is a conversion to an integer there so floor(D) + 1 can't be larger than INT_MAX 12:38 <+bridge> [ddnet] So that's another limit 12:38 <+bridge> [ddnet] Ooooh now that I think about it you shouldn't replace that first distance with a distance squared e.g. 12:39 <+bridge> [ddnet] It will square the amount of iterations you do along the line 😄 12:39 <+bridge> [ddnet] yea 12:39 <+bridge> [ddnet] yeah only inside the MAX_CLIENTS loop 12:40 <+bridge> [ddnet] I think you can skip thru tees aswell 12:40 <+bridge> [ddnet] didn't know this 12:44 <+bridge> [ddnet] it performs better i think, but not yet perfect of course 12:44 <+bridge> [ddnet] is ur server on linux? 12:46 <+bridge> [ddnet] for the release build u could deffs try out Ofast and lto 12:46 <+bridge> [ddnet] the good thing here is, if they dont work as expected, you can just remove them again without changing any code 12:52 <+bridge> [ddnet] ChillerDragon: 12:52 <+bridge> [ddnet] you here for this? :D 12:52 <+bridge> [ddnet] @Jupstar ✪ https://github.com/fokkonaut/F-DDrace/commit/c2017bcd2e4016c4171bbd2deb1a2016d9753b6e 12:54 <+bridge> [ddnet] i think the reference looks wrong 12:54 <+bridge> [ddnet] why? 12:54 <+bridge> [ddnet] &v => v 12:54 <+bridge> [ddnet] bcs u take a reference of a tmp object 12:54 <+bridge> [ddnet] just as the length function would do 12:54 <+bridge> [ddnet] no, it accepts a const reference 12:55 <+bridge> [ddnet] i never understoof this xD 12:55 <+bridge> [ddnet] just remove the reference 12:55 <+bridge> [ddnet] the compiler is smart enough to not produce slower code 12:55 <+bridge> [ddnet] i dont even know what that is 12:55 <+bridge> [ddnet] its like a pointer just that it cant be null xd 12:55 <+bridge> [ddnet] what is it used for 12:55 <+bridge> [ddnet] like 12:55 <+bridge> [ddnet] idk 12:56 <+bridge> [ddnet] e.g. if you have an object of class CPlayer 12:56 <+bridge> [ddnet] and u take it by reference, you modify the object itself 12:56 <+bridge> [ddnet] not a copy of it 12:57 <+bridge> [ddnet] but isnt that the same with a pointer? 12:57 <+bridge> [ddnet] https://github.com/fokkonaut/F-DDrace/commit/1ac880a085ecd7376d3570fd60da52c1444ed72f 12:57 <+bridge> [ddnet] yes 12:57 <+bridge> [ddnet] references are basically pointers 12:58 <+bridge> [ddnet] its not directly true, but they are implemented like that 12:58 <+bridge> [ddnet] the rest looks fine to me 12:58 <+bridge> [ddnet] okay, thanks 12:58 <+bridge> [ddnet] if its broken you'd notice anyway, bcs the collision wont work 😄 12:58 <+bridge> [ddnet] it all works fine, as it seems 12:59 <+bridge> [ddnet] I wonder if my mod has more of these "bugs" 13:00 <+bridge> [ddnet] performance issues 13:00 <+bridge> [ddnet] I think I should replace the distance by distance_squared in gameworld too, right? 13:00 <+bridge> [ddnet] all these FindEntities etc 13:00 <+bridge> [ddnet] ClosestCharacter 13:04 <+bridge> [ddnet] u can replace it basically everywhere, where the distance is not used directly, but only compared against others 13:04 <+bridge> [ddnet] but it wont improve it everywhere as much 13:04 <+bridge> [ddnet] makes sense 13:05 <+bridge> [ddnet] why? 13:05 <+bridge> [ddnet] i guess a single call is not that bad? :d 13:05 <+bridge> [ddnet] :D* 13:06 <+bridge> [ddnet] well the FPU might not even profit from a signle core, if it waits on another call anyway 13:06 <+bridge> [ddnet] its really hard to predict what happens inside the CPU 13:06 <+bridge> [ddnet] ask an intel or amd dev xd 13:06 <+bridge> [ddnet] xd 13:06 <+bridge> [ddnet] so basically you lol 13:06 <+bridge> [ddnet] well the FPU might not even profit from a signle call, if it waits on another call anyway 13:06 <+bridge> [ddnet] what you've done to ddnet is immaculate xD 13:07 <+bridge> [ddnet] but i havent done anything FPU related xD 13:07 <+bridge> [ddnet] i also dont know how GPU drivers are implemented in detail, its more guessing 13:07 <+bridge> [ddnet] also dont know what that is tbh 13:07 <+bridge> [ddnet] floating point unit 13:07 <+bridge> [ddnet] xD thats why its experimental? 13:07 <+bridge> [ddnet] its like a CPU just for floating points 13:07 <+bridge> [ddnet] lol 13:07 <+bridge> [ddnet] ah no, opengl is well defined 13:08 <+bridge> [ddnet] its experimental, bcs we had quite a few bugs on Mac and older hardware on windows 13:08 <+bridge> [ddnet] we even have an unknown bug in 6+7th gen intel 13:08 <+bridge> [ddnet] tho it also affects older GL versions 13:09 <+bridge> [ddnet] but i'd say GL 3.3 is stable, i didnt really encounter an issue lately 13:13 <+bridge> [ddnet] anyway fokko, if u have the motivation to change every distance check do it. it wont hurt^^ 13:20 <+bridge> [ddnet] :D 13:26 <+bridge> [ddnet] something something premature optimization something something 13:27 <+bridge> [ddnet] Profile your code before making small insignificant optimizations a modern CPU has so many tricks up it's sleeve, small changes usually mean nothing 13:31 <+bridge> [ddnet] i ran my fng server with 256 slots, 255 dbg dummies which randomly moved and jumped etc. and it worked fine without code modications, but maybe i just used a stronger CPU 13:32 <+bridge> [ddnet] I had trouble with cpu usage so I'd guess that's what helps 13:33 <+bridge> [ddnet] Maybe just throw money at the problem @fokkonaut 13:33 <+bridge> [ddnet] ChillerDragon said that we have the best CPU already 13:33 <+bridge> [ddnet] i wondered too 13:33 <+bridge> [ddnet] he said anything better costs > 100€ 13:34 <+bridge> [ddnet] p/m 13:41 <+bridge> [ddnet] https://github.com/fokkonaut/F-DDrace/runs/1903237972 13:41 <+bridge> [ddnet] doesnt work 13:43 <+bridge> [ddnet] ah 13:43 <+bridge> [ddnet] i think i know how this works 13:43 <+bridge> [ddnet] yea i fucked it up lol 13:48 <+bridge> [ddnet] still doesnt work 14:00 <+bridge> [ddnet] https://cdn.discordapp.com/attachments/293493549758939136/810858123291131944/unknown.png 14:02 <+bridge> [ddnet] cant u use smth like push "-Wno-..." 14:03 <+bridge> [ddnet] ah nvm that looks right indeed 14:03 <+bridge> [ddnet] maybe outdated compiler? 14:04 <+bridge> [ddnet] not sure, its github actions test 14:04 <+bridge> [ddnet] the first error just occured out of nowhere 14:05 <+bridge> [ddnet] and the fix doesnt work 14:06 <+bridge> [ddnet] its also missing a pop isnt it? 14:06 <+bridge> [ddnet] but probs not causing this issue 14:07 <+bridge> [ddnet] but ubuntu latest doest fail? 14:07 <+bridge> [ddnet] then its probs the compiler version, i'd say 14:07 <+bridge> [ddnet] gcc 5.5 is pretty old xd 14:08 <+bridge> [ddnet] added the pop later on 14:08 <+bridge> [ddnet] how do i update it? 14:08 <+bridge> [ddnet] i think you can just check the gcc version somehow 14:09 <+bridge> [ddnet] i am not familiar with all of this xD 14:09 <+bridge> [ddnet] at all 14:09 <+bridge> [ddnet] #if defined(__GNUC__) && .... 14:09 <+bridge> [ddnet] `#if defined(__GNUC__) && ....` 14:10 <+bridge> [ddnet] ``` 14:10 <+bridge> [ddnet] /* Test for GCC > 3.2.0 */ 14:10 <+bridge> [ddnet] #if __GNUC__ > 3 || \ 14:10 <+bridge> [ddnet] (__GNUC__ == 3 && (__GNUC_MINOR__ > 2 || \ 14:10 <+bridge> [ddnet] (__GNUC_MINOR__ == 2 && \ 14:10 <+bridge> [ddnet] __GNUC_PATCHLEVEL__ > 0)) 14:10 <+bridge> [ddnet] ``` 14:10 <+bridge> [ddnet] https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html 14:10 <+bridge> [ddnet] so a `&& __GNUC__ > 7` might do the job 14:10 <+bridge> [ddnet] i dunno when they added that pragma support 14:11 <+bridge> [ddnet] well, i do have a fix already in f-ddrace 14:11 <+bridge> [ddnet] for other false positives 14:11 <+bridge> [ddnet] maybe it just fails bcs the actual warning is unsupported 14:11 <+bridge> [ddnet] no idea, but how can it suddenly pop up? 14:11 <+bridge> [ddnet] like the whole warning why i want to add this ignore thing 14:12 <+bridge> [ddnet] yes, but like this: 14:12 <+bridge> [ddnet] warning was added in gcc 8 14:12 <+bridge> [ddnet] warning causes werror in gcc 8 14:12 <+bridge> [ddnet] 14:12 <+bridge> [ddnet] so u only want to remove it for gcc 8 14:12 <+bridge> [ddnet] i mean 14:13 <+bridge> [ddnet] https://cdn.discordapp.com/attachments/293493549758939136/810861277910925312/unknown.png 14:13 <+bridge> [ddnet] from one day to another 14:13 <+bridge> [ddnet] this error appeared 14:13 <+bridge> [ddnet] https://cdn.discordapp.com/attachments/293493549758939136/810861345544994837/unknown.png 14:13 <+bridge> [ddnet] yes, maybe ubuntu latest was updated 14:13 <+bridge> [ddnet] oh 14:13 <+bridge> [ddnet] true 14:15 <+bridge> [ddnet] that warning is considered not very useful anyway, i already read it in the gcc mailing lists, and they were devided, if its useful or not, in the end, not warning might cause more issues 😄 14:15 <+ChillerDragon> @fokkonaut haha we do not have the best single core cpu on the market but i think the best we can afford at the current hoster 14:15 <+bridge> [ddnet] meh 14:15 <+ChillerDragon> anything i missed i did not read all? 14:15 <+bridge> [ddnet] yes 14:16 <+bridge> [ddnet] Can you add a script to remove the paths for svgs? XD 14:16 <+ChillerDragon> sure 14:16 <+bridge> [ddnet] nice thanks 14:16 <+ChillerDragon> make an issue please 14:16 <+ChillerDragon> wait i can make one :D 14:16 <+bridge> [ddnet] ok 14:16 <+ChillerDragon> oh no then i do not get a mail 14:16 <+ChillerDragon> can you do it ? :D 14:16 <+bridge> [ddnet] ok xD 14:16 <+ChillerDragon> nice thanks 14:20 <+ChillerDragon> ofast and lto is just to boost performance right? not to solve the actual issue but more compating the sympthoms? 14:22 <+bridge> [ddnet] yes, but it heavily relies on defined behavior 14:22 <+bridge> [ddnet] so better write good code with it xD, there are edge cases you never heard of, before you googled them xD 14:39 <+ChillerDragon> i wrote "compating" sometimes i wonder how people understand me 14:40 <+bridge> [ddnet] i just ignore words i dont understand xd 14:49 <+bridge> [ddnet] https://9to5linux.com/linux-kernel-5-11-officially-released-this-is-whats-new 14:49 <+bridge> [ddnet] :poggers: 15:39 <+bridge> [ddnet] @Learath2 splitting the map into different chunks doesnt make mush sense if all players are in the same chunk, or in chunks close to it 15:39 <+bridge> [ddnet] You make the chunks rather small 15:40 <+bridge> [ddnet] There is a version of this scheme that makes the density of the grid variable at a given point (quadtrees), quite a bit harder to implement though 16:29 <+bridge> [ddnet] https://www.drdobbs.com/jvm/an-algorithm-for-compressing-space-and-t/184406478 16:29 <+bridge> [ddnet] 👀 16:34 <+bridge> [ddnet] https://cdn.discordapp.com/attachments/293493549758939136/810896764474621972/unknown.png 16:34 <+bridge> [ddnet] u have to scroll all the way down 16:34 <+bridge> [ddnet] to reject all their shit 16:34 <+bridge> [ddnet] but allow all is up there 16:34 <+bridge> [ddnet] https://cdn.discordapp.com/attachments/293493549758939136/810896845773209600/unknown.png 16:35 <+bridge> [ddnet] i wonder if u can law suit them 16:35 <+bridge> [ddnet] doesnt it have to be clear? 16:36 <+bridge> [ddnet] gdrp should make this a opt in feature, where it is disabled by default, and the user has to explicitly go and activate it by his own will 18:34 <+bridge> [ddnet] @Jupstar ✪ @fstd: it probably is not even related to that part of the code, i did some tests with real clients, and it seems the DoSnapshot function is just taking so much 18:35 <+bridge> [ddnet] and all the entities in general 18:36 <+bridge> [ddnet] i did some intense debugging with chillerdragon but idk, i cant really find anything, but i also never had anything like this before, sucks really hard 18:38 <+bridge> [ddnet] I dont know why it ran so good for months now, I dont want to remove 128p support again 18:52 <+bridge> [ddnet] Can i for example thread some specific stuff? 18:52 <+bridge> [ddnet] for example the snapshotting which will go up to 60% iirc, or some other stuff? 19:04 <+bridge> [ddnet] Eh the gun is broken xD 19:05 <+bridge> [ddnet] You can see if you shoot with grenade or smth 19:05 <+bridge> [ddnet] You cant see if you shoot with grenade or smth 19:07 <+bridge> [ddnet] @Marius you made a bad update. I think the version you got is already removed 19:07 <+bridge> [ddnet] Check out if you can download the latest version 19:09 <+bridge> [ddnet] So its not the problem from the srv? 19:10 <+bridge> [ddnet] Ah I see 19:10 <+bridge> [ddnet] @fokkonaut would it kill you to learn how to profile the code? Speculating about where the issue might be and randomly moving things to threads won’t help 19:11 <+bridge> [ddnet] I profiled it 19:11 <+bridge> [ddnet] DoSnapshot is using 50-60% of the CPU on my local server 19:12 <+bridge> [ddnet] CGameWorld::Tick and Snap takes a lot too 19:12 <+bridge> [ddnet] iterating over all entities 19:12 <+bridge> [ddnet] CSnapshotBuilder::Finish is also very expensive due to the tl_swap 19:12 <+bridge> [ddnet] and all the loops in CCharacterCore::Move and ::Tick 19:13 <+bridge> [ddnet] Snap on what? 19:14 <+bridge> [ddnet] CDragger takes 10%, character just about 2-5 19:14 <+bridge> [ddnet] but creating the snapshots takes a lot 19:16 <+bridge> [ddnet] There is a tl_swap in ::Finish? 19:16 <+bridge> [ddnet] 3 19:16 <+bridge> [ddnet] well not in finish i think 19:16 <+bridge> [ddnet] let me see 19:17 <+bridge> [ddnet] yes 19:17 <+bridge> [ddnet] 3 times per index 19:17 <+bridge> [ddnet] in the loop 19:17 <+bridge> [ddnet] Also is this profile from a live server? People moving around and chatting might change the profile drastically due to the way collision is handled 19:18 <+bridge> [ddnet] i tested it with clients locally because chillerdragon said its not possible to get a profiler on the live server 19:18 <+bridge> [ddnet] There is no loop in CSnapshotBuilder::Finish? 19:18 <+bridge> [ddnet] i am on 0.7 19:18 <+bridge> [ddnet] my mod 19:18 <+bridge> [ddnet] ChillerDragon learn to use perf nobo 19:19 <+bridge> [ddnet] his argument was that the one he used didnt give any information 19:19 <+bridge> [ddnet] Oh 0.7 now sorts the snapshots? 19:19 <+bridge> [ddnet] and valgrind or some others are way to expensive 19:19 <+bridge> [ddnet] i have no idea 19:19 <+bridge> [ddnet] maybe? it seems like 19:19 <+bridge> [ddnet] why tho? 19:20 <+bridge> [ddnet] Well bubble sort has awful performance characteristics as n grows. Maybe try replacing that with std::sort? 19:20 <+bridge> [ddnet] I see, I should have based on 0.6 xD 19:20 <+bridge> [ddnet] how would that work? 19:21 <+bridge> [ddnet] `std::sort(pSnap->SortedKeys()[0], pSnap->SortedKeys()[NumItems]);`? 19:22 <+bridge> [ddnet] ah no 19:22 <+bridge> [ddnet] You need a custom swap function to swap the offsets too 19:22 <+bridge> [ddnet] why is that even needed 19:24 <+bridge> [ddnet] Because of the way split 1 item into 3, (data, size, offset) all go into separate arrays 19:25 <+bridge> [ddnet] So when sorting the data by key, you also need to swap around the size and the offset so they stay correct 19:25 <+bridge> [ddnet] Oh, yea of course! i mean why does 0.7 sort them? 19:25 <+bridge> [ddnet] Oh, so they can do binary search on the client 19:26 <+bridge> [ddnet] Avoids the costly linear search 0.6 does 19:26 <+bridge> [ddnet] ohh 19:27 <+bridge> [ddnet] But I don’t like the idea honestly. The client sorting it would distribute the cost. The server pays a huge cost per client all on it’s own like this 19:27 <+bridge> [ddnet] And why dont you need to do that for 0.6? 19:28 <+bridge> [ddnet] i mean for the bridge servers 19:28 <+bridge> [ddnet] I think I did, didn’t I? 19:28 <+bridge> [ddnet] not sure 19:28 <+bridge> [ddnet] Hm I actually don’t remember 19:28 <+bridge> [ddnet] you sounded surprised 19:29 <+bridge> [ddnet] I did but then I do remember discussing this before 19:29 <+bridge> [ddnet] Well let me check 19:29 <+bridge> [ddnet] i dont think you sort them, tbh 19:30 <+bridge> [ddnet] Hm, okay than idk what the bubble sort on the server is for. Maybe to reduce the cost for the client? 19:30 <+fstd> fokkonaut: if nothing about your build changed then i guess something changed on the host (duh) 19:30 <+fstd> this would be a good time to have been running munin for a few months :) 19:30 <+bridge> [ddnet] Well I push changes every day almost 19:30 <+bridge> [ddnet] and Mr. Anderson says nothing has changed on his side 19:31 <+fstd> so you can revert to a commit that has okay performance? 19:31 <+fstd> in that case use git bisect 19:31 <+bridge> [ddnet] https://github.com/teeworlds/teeworlds/commit/0c4b3ab62bb3ef798c77f8d591f921bffe6b30b0 19:31 <+bridge> [ddnet] thats the point, i dont know when it started 19:31 <+bridge> [ddnet] This is indeed why they bubble sort, I wonder how our bridge even works at all now 😄 19:32 <+fstd> finding out at what point it started is the whole point of using git bisect 19:32 <+bridge> [ddnet] x 19:32 <+bridge> [ddnet] D 19:32 <+fstd> ? 19:32 <+bridge> [ddnet] how does it work? 19:32 <+fstd> you tell it a good and a bad commit 19:32 <+bridge> [ddnet] i reacted to learaths message fstd 19:32 <+fstd> and it does a binary search 19:33 <+bridge> [ddnet] no idea what any of those means 19:33 <+bridge> [ddnet] binary search is rly simple 19:33 <+bridge> [ddnet] just look it up 19:33 <+fstd> it makes find teh bug fast 19:33 <+fstd> is what it means 19:33 <+bridge> [ddnet] But I would like to understand xD 19:33 <+fstd> or let's say the commit that introduced the bug 19:34 <+fstd> well 19:34 <+bridge> [ddnet] binary search discards half 19:34 <+bridge> [ddnet] every iteration 19:34 <+bridge> [ddnet] https://blog.penjee.com/wp-content/uploads/2015/04/binary-and-linear-search-animations.gif 19:34 <+fstd> there's this magical network of information 19:34 <+fstd> i'd explain it to you but only if you genuinely can't figure out out by yourself using google or wikipedia etc 19:35 <+bridge> [ddnet] yeah 19:35 <+bridge> [ddnet] literally wikipedia can tell u all this 19:35 <+bridge> [ddnet] u just a lazy bones 19:36 <+bridge> [ddnet] so how do i use git bisect 19:36 <+bridge> [ddnet] google it 19:36 <+bridge> [ddnet] or run "git bisect" 19:37 <+bridge> [ddnet] git bisect --help 19:37 <+bridge> [ddnet] wtf 19:37 <+bridge> [ddnet] it runs git-bisect.hmtk 19:37 <+bridge> [ddnet] it runs git-bisect.hmtl 19:37 <+bridge> [ddnet] on linux it opens a man page 19:38 <+bridge> [ddnet] Ah the client when unpacking the delta also uses the snapshotbuilder so it sorts too 19:38 <+fstd> even the .html file will do. i think you can download .html viewers somewhere 19:39 <+bridge> [ddnet] okay, but git bisect wont help me much i think. since i need about 60-80 players for it to trigger 19:39 <+bridge> [ddnet] @fokkonaut you can probably abuse that to distribute the cost of sorting. Just send unsorted snaps 19:39 <+fstd> you obviously need some way to tell whether a given version is good or bad 19:39 <+bridge> [ddnet] i dont really have that 19:40 <+bridge> [ddnet] because it just starts to lag very hard, there is no value that pops over :D 19:40 <+bridge> [ddnet] so removing the bubble sort should work? 19:40 <+fstd> well but you notice whether it lags very hard or not...? 19:40 <+fstd> so you can tell when it's bad 19:41 <+fstd> now with the same test load if it doesn't lag very hard, it's good, no? 19:41 <+bridge> [ddnet] yea, true 19:41 <+bridge> [ddnet] but its not always happening 19:41 <+fstd> okay that sucks 19:41 <+bridge> [ddnet] its not just, oh okay 70 players i will start to lag now 19:41 <+bridge> [ddnet] yea 19:41 <+bridge> [ddnet] it sucks so bad 19:42 <+fstd> well bring 70 players then every time? 19:42 <+bridge> [ddnet] its at 72 right now and doesnt lag 19:42 <+fstd> sigh 19:42 <+bridge> [ddnet] There is actually a way to handle this. perf is perfectly capable of saving to a ring buffer and you can send a SIGUSR2 to it to get it to dump the buffer to a file 19:42 <+bridge> [ddnet] its pure randomness so the only thing i can do is improving everything 19:43 <+bridge> [ddnet] So to profile transient issues like this keep perf running and send it a SIGUSR2 when it gets laggy 19:43 <+fstd> Learath2: nice idea 19:43 <+bridge> [ddnet] ChillerDragon 19:43 <+bridge> [ddnet] u there :/ 19:43 <+fstd> Learath2: what's perf tho? not gprof? 19:44 <+bridge> [ddnet] @Learath2 ? 19:44 <+bridge> [ddnet] @fokkonaut I think so, try it it should break very obviously if my hypothesis is wrong 19:44 <+bridge> [ddnet] okay, thanks 19:44 <+bridge> [ddnet] fstd: perf is part of the kernel 19:45 <+bridge> [ddnet] it can do the kind of sampling profiling gprof does 19:46 <+bridge> [ddnet] works @Learath2 19:49 <+bridge> [ddnet] Again not sure how much it'll help but it's one less bubble sort per player per snap less 19:51 <+bridge> [ddnet] O(nk^2) where k is the number of snapitems which I guess is fair to assume is of the same order as n so an O(n^3) process gone 19:52 <+bridge> [ddnet] (atleast I think, I'm usually not very good with the theory part of CS) 19:57 <+bridge> [ddnet] well, just locally already it is a huge improvement 20:04 <+bridge> [ddnet] fstd: perf works without instrumenting the code so a little less information but it's still very useful imho, you should add it to your toolkit for profiling stuff 20:05 <+bridge> [ddnet] ulan ziyaaa 20:25 <+bridge> [ddnet] rider is better than vs but running trying to run 32 bits on it sucks 20:25 <+bridge> [ddnet] you gotta download alot of shit 20:25 <+bridge> [ddnet] sad 20:26 <+bridge> [ddnet] you gotta download some of shit 20:50 <+bridge> [ddnet] @Learath2 why is the CDragger::Snap so expensive? 20:50 <+bridge> [ddnet] because it moves all the time? 20:55 <+bridge> [ddnet] Because of their very complex behaviour with respect to teams and solo 20:56 <+bridge> [ddnet] The way we fake entities being separate in different teams is actually quite costly. That’s what I’d suspect to be the culprit 20:56 <+bridge> [ddnet] ```for (int i = 0; i < MAX_CLIENTS; i++) 20:56 <+bridge> [ddnet] { 20:56 <+bridge> [ddnet] if (m_SoloIDs[i] == -1) 20:56 <+bridge> [ddnet] break; 20:56 <+bridge> [ddnet] 20:56 <+bridge> [ddnet] Server()->SnapFreeID(m_SoloIDs[i]); 20:56 <+bridge> [ddnet] m_SoloIDs[i] = -1; 20:56 <+bridge> [ddnet] }``` 20:56 <+bridge> [ddnet] stuff like this belongs to the Tick function, no? 20:56 <+bridge> [ddnet] that would save us quite a bit already 20:56 <+bridge> [ddnet] on fuller servers 20:57 <+bridge> [ddnet] I honestly don’t remember the logic there at all, it’s been that way for a long time 20:57 <+bridge> [ddnet] All I know is that snap function is called once per player and it has a large costly loop that is run once per player. That’s O(n^2) and O(n^2) bad 20:58 <+bridge> [ddnet] yea 20:58 <+bridge> [ddnet] snaps every 2nd tick for all active players 20:59 <+bridge> [ddnet] I have no idea why for snapping for a single player it needs to go thru alll players. You’ll have to read the code to figure it out 20:59 <+bridge> [ddnet] i believe for spectators 20:59 <+bridge> [ddnet] idk 20:59 <+bridge> [ddnet] nah probbaly not xD 21:00 <+bridge> [ddnet] that looks like it checks if people are in solo 21:00 <+bridge> [ddnet] yeah thats just a small snippet 21:00 <+bridge> [ddnet] well, we have a SnappingClient already, I also dotn understand why we would need a loop inside of the Snap function 21:01 <+bridge> [ddnet] the Snap function basically IS A loop 21:01 <+bridge> [ddnet] oh, yeah, that's really strange 21:01 <+bridge> [ddnet] But it really is expensive 21:02 <+bridge> [ddnet] Well maybe check the commit messages? At the end of the day to optimize something you need to understand it first 21:04 <+bridge> [ddnet] the handling of m_SoloIDs is also very, very strang 21:04 <+bridge> [ddnet] the handling of m_SoloIDs is also very, very strange 21:04 <+bridge> [ddnet] My theory is that it’s snapping multiple times because it can be attached to multiple people in different teams 21:04 <+bridge> [ddnet] thats what i thought too 21:05 <+bridge> [ddnet] So a way to optimize could be to keep track if connections instead of going thru every tee to see if we are connected 21:05 <+bridge> [ddnet] But again, I’m only speculating 21:05 <+bridge> [ddnet] fact tho: i need to change it 21:05 <+bridge> [ddnet] the more players are online on my server the more it eats 21:05 <+bridge> [ddnet] locally, it went up to 17% 21:06 <+bridge> [ddnet] just the dragger snap 21:06 <+bridge> [ddnet] Sounds like a great place to optimize 21:06 <+bridge> [ddnet] i already improved another thing to not loop over all players, works fine 21:07 <+bridge> [ddnet] also the snap sorting was quite expensive 21:07 <+bridge> [ddnet] if i understood the profiler correctly 21:24 <+bridge> [ddnet] I did some tests now 21:24 <+bridge> [ddnet] 1. You will only see draggers from your team 21:24 <+bridge> [ddnet] 2. using /showothers you can see the draggers of another person from the same team who is in solo 21:26 <+bridge> [ddnet] i dont really think its needed to see other draggers than the one that can affect you 21:27 <+bridge> [ddnet] thats what the loop is for, as you suspected, showing multiple draggers 21:30 <+bridge> [ddnet] Are there some resources on the Maths behind Tw physics, best i could find is some old Forum post https://www.teeworlds.com/forum/viewtopic.php?id=10603 21:45 <+bridge> [ddnet] wow it even creates 1 CDragger for every team 21:46 <+bridge> [ddnet] Before I embarrass myself on the rust books issue tracker: This section from the book explaining lifetimes doesn't make sense, right? 21:46 <+bridge> [ddnet] > ``` 21:46 <+bridge> [ddnet] > fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { 21:47 <+bridge> [ddnet] > if x.len() > y.len() { 21:47 <+bridge> [ddnet] > x 21:47 <+bridge> [ddnet] > } else { 21:47 <+bridge> [ddnet] > y 21:47 <+bridge> [ddnet] > } 21:47 <+bridge> [ddnet] > } 21:47 <+bridge> [ddnet] > ``` 21:47 <+bridge> [ddnet] > The function signature now tells Rust that for some lifetime 'a, the function takes two parameters, both of which are string slices that live at least as long as lifetime 'a. The function signature also tells Rust that the string slice returned from the function will live at least as long as lifetime 'a. 21:47 <+bridge> [ddnet] 21:47 <+bridge> [ddnet] Rather it should be: 21:48 <+bridge> [ddnet] Before I embarrass myself on the rust books issue tracker: This section from the book explaining lifetimes doesn't make sense, right? 21:48 <+bridge> [ddnet] > ``` 21:48 <+bridge> [ddnet] > fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { 21:48 <+bridge> [ddnet] > if x.len() > y.len() { 21:48 <+bridge> [ddnet] > x 21:48 <+bridge> [ddnet] > } else { 21:48 <+bridge> [ddnet] > y 21:48 <+bridge> [ddnet] > } 21:48 <+bridge> [ddnet] > } 21:48 <+bridge> [ddnet] > ``` 21:48 <+bridge> [ddnet] > The function signature now tells Rust that for some lifetime 'a, the function takes two parameters, both of which are string slices that live at least as long as lifetime 'a. The function signature also tells Rust that the string slice returned from the function will live at least as long as lifetime 'a. 21:48 <+bridge> [ddnet] 21:48 <+bridge> [ddnet] Rather it should be: 21:48 <+bridge> [ddnet] 21:48 <+bridge> [ddnet] > The function signature now tells Rust that for some lifetime 'a, the function takes two parameters, both of which are string slices that live at least as long as lifetime 'a. The function signature also tells Rust that lifetime 'a will live at least as long as the string slice returned from the function. 21:48 <+bridge> [ddnet] Where are you rust crew? :D 21:49 <+bridge> [ddnet] Before I embarrass myself on the rust books issue tracker: This section from the book explaining lifetimes doesn't make sense, right? 21:49 <+bridge> [ddnet] > ``` 21:49 <+bridge> [ddnet] > fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { 21:49 <+bridge> [ddnet] > if x.len() > y.len() { 21:50 <+bridge> [ddnet] > x 21:50 <+bridge> [ddnet] > } else { 21:50 <+bridge> [ddnet] > y 21:50 <+bridge> [ddnet] > } 21:50 <+bridge> [ddnet] > } 21:50 <+bridge> [ddnet] > ``` 21:50 <+bridge> [ddnet] > The function signature now tells Rust that for some lifetime 'a, the function takes two parameters, both of which are string slices that live at least as long as lifetime 'a. The function signature also tells Rust that the string slice returned from the function will live at least as long as lifetime 'a. 21:50 <+bridge> [ddnet] 21:50 <+bridge> [ddnet] Rather it should be: 21:50 <+bridge> [ddnet] 21:50 <+bridge> [ddnet] > The function signature now tells Rust that for some lifetime 'a, the function takes two parameters, both of which are string slices that live at least as long as lifetime 'a. The function signature also tells Rust that **lifetime 'a will live at least as long as the string slice returned from the function**. 21:50 <+bridge> [ddnet] Before I embarrass myself on the rust books issue tracker: This section from the book explaining lifetimes doesn't make sense, right? 21:50 <+bridge> [ddnet] > ``` 21:50 <+bridge> [ddnet] > fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { 21:50 <+bridge> [ddnet] > if x.len() > y.len() { 21:50 <+bridge> [ddnet] > x 21:50 <+bridge> [ddnet] > } else { 21:50 <+bridge> [ddnet] > y 21:50 <+bridge> [ddnet] > } 21:50 <+bridge> [ddnet] > } 21:50 <+bridge> [ddnet] > ``` 21:50 <+bridge> [ddnet] > The function signature now tells Rust that for some lifetime 'a, the function takes two parameters, both of which are string slices that live at least as long as lifetime 'a. The function signature also tells Rust that **the string slice returned from the function will live at least as long as lifetime 'a**. 21:50 <+bridge> [ddnet] 21:50 <+bridge> [ddnet] Rather it should be: 21:50 <+bridge> [ddnet] 21:50 <+bridge> [ddnet] > The function signature now tells Rust that for some lifetime 'a, the function takes two parameters, both of which are string slices that live at least as long as lifetime 'a. The function signature also tells Rust that **lifetime 'a will live at least as long as the string slice returned from the function**. 21:50 <+bridge> [ddnet] Isn’t that an iff? 21:50 <+bridge> [ddnet] The two sound equivalent 21:51 <+bridge> [ddnet] no!? 21:51 <+bridge> [ddnet] (Disclaimer I’m not much of a rust person, just thinking) 21:57 <+bridge> [ddnet] As an argument that it's not equivalent (ik it's super shallow but idk how to talk about lifetimes idk if I understand them good enough): The sentence is "x lives at least as long as y", so x >= y. You can't change x and y here. 21:57 <+bridge> [ddnet] No? 21:58 <+bridge> [ddnet] Ah I see, hm 21:58 <+bridge> [ddnet] I guess you could say that the lifetime of 'a should really be the same as the lifetime of the string slice returned from the function 21:59 <+bridge> [ddnet] That would make sense in my understanding of lifetimes 21:59 <+bridge> [ddnet] So your argument is that it's the lifetime 'a that is constrained by the lifetime of the string slice? 21:59 <+bridge> [ddnet] Exactly that 22:00 <+bridge> [ddnet] but from what I understand (even more shallow than your knowledge) lifetimes exist separate from the objects that they constrain 22:01 <+bridge> [ddnet] @Learath2 omg 22:01 <+bridge> [ddnet] This is important context from later in the paragraph: 22:01 <+bridge> [ddnet] > [...] only that some scope can be substituted for 'a that will satisfy this signature. 22:01 <+bridge> [ddnet] So it will compile only if there is any scope 'a that works 22:01 <+bridge> [ddnet] @Learath2 if i dont create the draggers, it doesnt lag that heavily, because one dragger creates MAX_CLIENTS draggers, 1 for each team, so in my case 128 draggers which alle have to be snapped 22:02 <+bridge> [ddnet] it only snaps draggers to the same team tho 22:02 <+bridge> [ddnet] Yeah the proper solution is to get rid of this silly idea of entities having multiple personality disorder 22:02 <+bridge> [ddnet] but just alone the calls to CDragger::Snap, 128 calls to 128 draggers, so 128*128 takes already 5% alone 22:02 <+bridge> [ddnet] GameWorld per team is the future 22:02 <+bridge> [ddnet] thats so insane 22:03 <+bridge> [ddnet] sadly, i dont know what a good fix for this would be. 22:03 <+bridge> [ddnet] @timakro doesn't that signature basically say that the lifetime of the returned string slice is the same as the lifetime of the inputs? 22:04 <+bridge> [ddnet] i think i will rework the dragger for my purposes xD 22:04 <+bridge> [ddnet] Yeah you could say it like that and I guess it would be unambiguous what you mean. 22:05 <+bridge> [ddnet] But that wouldn't be precisely right because the lifetime of the inputs can be longer than that of the output, right? 22:05 <+bridge> [ddnet] I see your confusion though. I think the original sounds more correct to my understanding of rust lifetimes but the only one that understands the concept well enough to comment on a technical matter like this is probably @heinrich5991 22:06 <+bridge> [ddnet] Heck, I don't even know if the lifetime includes when the variable comes into scope or only means the time when it goes out of scope 22:06 <+bridge> [ddnet] From the ascii art stuff they draw in their code it seems like they mean both, where lifetime A is "longer" than lifetime B if A comes into scope before B and goes out of scope after B 22:09 <+bridge> [ddnet] For a moment think of a' as the lifetime which starts right before the function is called and ends right after the function returns. That would work with the original sentence, right? 22:54 <+bridge> [ddnet] > The function signature also tells Rust that the string slice returned from the function will live at least as long as lifetime 'a. 22:54 <+bridge> [ddnet] both have to live as long as 'a 22:54 <+bridge> [ddnet] note that rust only knows stuff at compile time 22:54 <+bridge> [ddnet] there is no runtime 22:54 <+bridge> [ddnet] so it needs this 22:55 <+bridge> [ddnet] also len() on a str is the length in bytes 22:55 <+bridge> [ddnet] use .chars().count() if u want the count in chars 22:56 <+bridge> [ddnet] u dont know if it will return x or y at runtime 22:57 <+bridge> [ddnet] ur best bet is to return a owned str 22:57 <+bridge> [ddnet] aka a String 22:58 <+bridge> [ddnet] altho i find it hard to find this function practical 22:58 <+bridge> [ddnet] or just do it this way and deal with the lifetimes 22:59 <+bridge> [ddnet] Both parameters? Yes, both parameters need to live at least as long as 'a. But the returned value? I'm arguing 'a has to live at least as long as the returned value. Not the other way around. 22:59 <+bridge> [ddnet] the returned value has to live as long as 'a too 22:59 <+bridge> [ddnet] This example is not my code, it's from the book 23:00 <+bridge> [ddnet] cuz its a reference still 23:01 <+bridge> [ddnet] Why would you want it to live *longer* than anything? It could be dropped immediately after the function is called, no? 23:01 <+bridge> [ddnet] Why would you want it to live *longer* than anything? It could be dropped immediately after the function returns, no? 23:01 <+bridge> [ddnet] it has to live as long as the parameter 23:01 <+bridge> [ddnet] cuz what u return is the parameter 23:02 <+bridge> [ddnet] they are references to the same thing 23:04 <+bridge> [ddnet] No, the returned reference can live at most as long as the thing it's referencing, not any longer 23:04 <+bridge> [ddnet] yea 23:04 <+bridge> [ddnet] it has to live as long as 'a 23:04 <+bridge> [ddnet] Or shorter 23:06 <+bridge> [ddnet] no, it has to be 'a 23:07 <+bridge> [ddnet] https://cdn.discordapp.com/attachments/293493549758939136/810995618910437396/unknown.png 23:07 <+bridge> [ddnet] https://cdn.discordapp.com/attachments/293493549758939136/810995802260242512/unknown.png 23:08 <+bridge> [ddnet] the lifetime of both parameters has to be equal or longer than 'a 23:08 <+bridge> [ddnet] Right 23:08 <+bridge> [ddnet] :monkalaugh: 23:08 <+bridge> [ddnet] lifetimes reminds me of learning pointers 23:08 <+bridge> [ddnet] in c++ 23:08 <+bridge> [ddnet] all confusion 23:09 <+bridge> [ddnet] And to be more specific, the lifetime of the thing the parameters are pointing to has to be equal or longer than 'a 23:09 <+bridge> [ddnet] but u once u get it its fine i guess 23:09 <+bridge> [ddnet] And to be more specific, the lifetime of the things the parameters are pointing to has to be equal or longer than 'a 23:09 <+bridge> [ddnet] ye 23:09 <+bridge> [ddnet] I get it but the explanation in the book is still wrong xD 23:09 <+bridge> [ddnet] I think 23:10 <+bridge> [ddnet] And the lifetime of the reference that is returned has to be equal or shorter than 'a 23:10 <+bridge> [ddnet] > The function signature now tells Rust that for some lifetime 'a, the function takes two parameters, both of which are string slices that live at least as long as lifetime 'a. The function signature also tells Rust that the string slice returned from the function will live at least as long as lifetime 'a. 23:10 <+bridge> [ddnet] its not wrong 23:10 <+bridge> [ddnet] check my image again 23:10 <+bridge> [ddnet] u can see the value returned will live as long as lifetime 'a 23:10 <+bridge> [ddnet] check how i marked 'a 23:10 <+bridge> [ddnet] and where it gets dropped 23:13 <+bridge> [ddnet] btw, i think i get what u think, if a was a reference to b in that context, it will only get dropped once all its lifetimes drop 23:13 <+bridge> [ddnet] thats how i would say it 23:14 <+bridge> [ddnet] i dont think the compiler drops x directly as u would think, it drops x in that scope and b in that scope 23:14 <+bridge> [ddnet] In the image you sent 'b would be the argument and 'a would be the string slice that's returned from the function. And now I can't go on because we have two different `'a`s ^^ 23:15 <+bridge> [ddnet] ?? 23:15 <+bridge> [ddnet] no 23:15 <+bridge> [ddnet] 'a is the argument 23:15 <+bridge> [ddnet] and the returned 23:16 <+bridge> [ddnet] Yeah ok whatever, this is just hypothetical hypothetical ... 23:17 <+bridge> [ddnet] ```rust 23:17 <+bridge> [ddnet] let b = "a"; 23:17 <+bridge> [ddnet] { 23:17 <+bridge> [ddnet] let x = "c"; 23:17 <+bridge> [ddnet] let a = longest(b, x); 23:17 <+bridge> [ddnet] drop(x) // a is implicitly dropped by this 23:17 <+bridge> [ddnet] } 23:17 <+bridge> [ddnet] drop(b) 23:17 <+bridge> [ddnet] ``` 23:17 <+bridge> [ddnet] u could say a is just a alias 23:17 <+bridge> [ddnet] idk 23:17 <+bridge> [ddnet] im a bad teacher 23:17 <+bridge> [ddnet] i guess i couldnt explain it to u 23:18 <+bridge> [ddnet] :pepeH: 23:18 <+bridge> [ddnet] A is dropped after the 4th line because it's never used xD 23:19 <+bridge> [ddnet] a is dropped after the 4th line because it's never used xD 23:19 <+bridge> [ddnet] no 23:19 <+bridge> [ddnet] a is not dropped directly 23:19 <+bridge> [ddnet] cuz its just another references 23:19 <+bridge> [ddnet] i imagine it as the compiler only dropping the original references 23:19 <+bridge> [ddnet] idk 23:19 <+bridge> [ddnet] im rly bad explaining it 23:19 <+bridge> [ddnet] stuff is always dropped implicitly after it's last use 23:20 <+bridge> [ddnet] yeah thats not what im trying to say 23:20 <+bridge> [ddnet] if reference or not 23:20 <+bridge> [ddnet] a in this case can be x or b 23:20 <+bridge> [ddnet] a isnt dropped as is 23:20 <+bridge> [ddnet] x or b will be dropped 23:20 <+bridge> [ddnet] when their lifetime ends 23:21 <+bridge> [ddnet] ah ok yeah what i just said was wrong, just noticed they all have the same type 23:22 <+bridge> [ddnet] the brackets are just confusing, they don't change anything, right? 23:22 <+bridge> [ddnet] they define a scope 23:22 <+bridge> [ddnet] but in this case they don't change anything, right? 23:22 <+bridge> [ddnet] no 23:23 <+bridge> [ddnet] xd 23:24 <+bridge> [ddnet] https://cdn.discordapp.com/attachments/293493549758939136/810999900846030888/unknown.png 23:24 <+bridge> [ddnet] https://cdn.discordapp.com/attachments/293493549758939136/810999919015886848/unknown.png 23:25 <+bridge> [ddnet] I think what makes the example dumb is that x and y have static lifetime 23:25 <+bridge> [ddnet] yea 23:25 <+bridge> [ddnet] https://cdn.discordapp.com/attachments/293493549758939136/811000249337249812/unknown.png 23:25 <+bridge> [ddnet] his works 23:25 <+bridge> [ddnet] cuz it has static lifetime 23:25 <+bridge> [ddnet] but 23:25 <+bridge> [ddnet] https://cdn.discordapp.com/attachments/293493549758939136/811000328001552414/unknown.png 23:25 <+bridge> [ddnet] https://cdn.discordapp.com/attachments/293493549758939136/811000349477175376/unknown.png 23:26 <+bridge> [ddnet] if u put the print inside it works 23:27 <+bridge> [ddnet] the compiler knows this thanks to lifetimes 23:27 <+bridge> [ddnet] xd 23:27 <+bridge> [ddnet] btw this `let b = "a";` does something similar to my brain as 23:27 <+bridge> [ddnet] https://cdn.discordapp.com/attachments/293493549758939136/811000725755789322/colors2.png 23:27 <+bridge> [ddnet] yeah sry 23:27 <+bridge> [ddnet] my examples xddd 23:27 <+bridge> [ddnet] 😄 23:28 <+bridge> [ddnet] what r u tryna do btw? 23:28 <+bridge> [ddnet] I was just reading the book and thinking this sentence is wrong xD 23:28 <+bridge> [ddnet] this book is actually reviewed 23:29 <+bridge> [ddnet] there even is a beta version of the book iirc 23:30 <+bridge> [ddnet] the book is released for stable beta and nightly 23:30 <+bridge> [ddnet] i dont think they would miss something that important 23:30 <+bridge> [ddnet] specially in the lifetimes section 23:33 <+bridge> [ddnet] All you're examples have only static livetimes, they can't possibly get to the core of my problem with the second sentence 23:33 <+bridge> [ddnet] All your examples have only static livetimes, they can't possibly get to the core of my problem with the second sentence 23:34 <+bridge> [ddnet] my last 23:34 <+bridge> [ddnet] All your examples have only static lifetimes, they can't possibly get to the core of my problem with the second sentence 23:34 <+bridge> [ddnet] doesnt have 23:34 <+bridge> [ddnet] ah sry 23:35 <+bridge> [ddnet] Okay so my problem with that second sentence will also be a problem with only one argument, so I'll make a function with only one argument 23:35 <+bridge> [ddnet] btw with 1 argument u can omit the lifetime 23:35 <+bridge> [ddnet] but its there 23:35 <+bridge> [ddnet] Yep, I will keep it for now just so we have a name for it 23:38 <+bridge> [ddnet] @timakro btw i think 2021 will be the year a new edition of rust is released 23:39 <+bridge> [ddnet] What's new? 23:39 <+bridge> [ddnet] https://github.com/rust-lang/rfcs/pull/2966 23:39 <+bridge> [ddnet] this is the rfc 23:39 <+bridge> [ddnet] well wait 23:40 <+bridge> [ddnet] https://doc.rust-lang.org/nightly/edition-guide/rust-next/index.html 23:40 <+bridge> [ddnet] this section here keeps track of changes 23:41 <+bridge> [ddnet] https://cdn.discordapp.com/attachments/293493549758939136/811004344559206440/unknown.png 23:41 <+bridge> [ddnet] its there in nightly already 23:41 <+bridge> [ddnet] xd 23:42 <+bridge> [ddnet]