<hightower4>
Blacksmoke16 that event magic you did is just brilliant (almost done with incorporating/documenting the event model)
<hightower4>
(I didn't have success with AnyEvent though (didn't manage to convert to module as it still didn't want to play with struct, nor convert to classes since then I got into issue of missing initialize()s which struct automatically provides), but that's of lesser importance for now)
<FromGitter>
<Blacksmoke16> Just add the initializers
<FromGitter>
<Blacksmoke16> The record macro defines one, not struct itself
<hightower4>
ah cool, yeah, still I don't have a clear picture in mind how I'd do it.. (I wanted to generate initializes, rather than write them by hand for each class)
<FromGitter>
<Blacksmoke16> Generate how?
<FromGitter>
<Blacksmoke16> Could copy the record macro and make it define a class instead, but probably not worth it
<hightower4>
I thought I could somehow find all the custom properties on the class, and generate from that
<hightower4>
but yeah, that's not a bad idea, the elegance of how record is defined is great
<FromGitter>
<Blacksmoke16> Ivars are only available within a method
HumanG33k has quit [Ping timeout: 265 seconds]
alexherbo2 has quit [Quit: Ping timeout (120 seconds)]
alexherbo2 has joined #crystal-lang
HumanG33k has joined #crystal-lang
Human_G33k has joined #crystal-lang
HumanG33k has quit [Read error: Connection reset by peer]
<FromGitter>
<ImAHopelessDev_gitlab> right now, only got 1 rune word added and working on server. which is a good first step :)
hightower4 has quit [Read error: Connection reset by peer]
<FromGitter>
<ImAHopelessDev_gitlab> with that said, `each_char` and `each` have been a godsend for socket / rune checking. sockets are stored in mysql as "000000" 0 is filler, 1 is socket, 2 is a linked socket (skill gem could be inserted in this as well), 3 is a rune word, and 4 is a gem. when inserted, the item's socket_data field gets updated. example: "0:25,1:26". socket position 0 and 1 are runes. sockets value is now
<FromGitter>
... "330000". ⏎ then, if a rune word needs to be checked, i can utilize `socket_data` and match it with the `sockets` to see what's inside. then, i can utilize the power of `.select` to obtain the possible rune words for that item type, and then call another `.select` after i extract the rune word string to validate if it's an actu ... [https://gitter.im/crystal-lang/crystal?at=5db25a939c398215097d4b3d]
f1reflyylmao has joined #crystal-lang
f1refly has quit [Ping timeout: 246 seconds]
teardown has joined #crystal-lang
<FromGitter>
<christopherzimmerman> I'm running into a bottleneck in my code that I can't seem to fix. When I benchmark the `times` function, it runs quite fast for large numbers: ⏎ ⏎ ```times 100_000 increment 2 64.56k ( 15.49µs) (± 0.62%) 0.0B/op fastest``` ⏎ ⏎ Is the compiler unrolling the first loop but not the second? There has to be some major optimization going on that I am missing.
alexherbo2 has quit [Quit: Ping timeout (120 seconds)]
alexherbo2 has joined #crystal-lang
<FromGitter>
<absolutejam_twitter> @hightower4 there's a data classes shard which does similar thinb as the record macro for classes
ht_ has joined #crystal-lang
<FromGitter>
<Daniel-Worrall> I imagine the compiler can optimise single step loops a lot better than it can 2 step
<FromGitter>
<Daniel-Worrall> The bytecode would come out a lot simpler
rohitpaulk has joined #crystal-lang
rohitpaulk has quit [Remote host closed the connection]
absolutejam2 has joined #crystal-lang
ht_ has quit [Quit: ht_]
absolutejam2 has quit [Ping timeout: 252 seconds]
absolutejam2 has joined #crystal-lang
dwdv has joined #crystal-lang
absolutejam2 has quit [Ping timeout: 268 seconds]
absolutejam2 has joined #crystal-lang
hightower4 has joined #crystal-lang
alexherbo21 has joined #crystal-lang
alexherbo2 has quit [Ping timeout: 240 seconds]
alexherbo216 has joined #crystal-lang
alexherbo21 has quit [Ping timeout: 240 seconds]
alexherbo216 has quit [Ping timeout: 265 seconds]
alexherbo2162 has joined #crystal-lang
<FromGitter>
<vlazar> @christopherzimmerman I don't see the difference you shown. Do you mind posting you benchmark? I've tried benchmarking `i += 1` and `i += 2` cases and got the second one 2 times faster.
alexherbo21628 has joined #crystal-lang
alexherbo2162 has quit [Read error: Connection reset by peer]
<FromGitter>
<christopherzimmerman> I tried the step approach and it works fine when I pass literals, but I need to be able to use the instance variables. If it makes a difference, the instance variables will never change once the class is instantiated so maybe there is something I can do there.
<FromGitter>
<christopherzimmerman> I understand why using variables would be slower than literals, but it baffles me that its 17000 times slower.
duane has quit [Ping timeout: 265 seconds]
<FromGitter>
<tenebrousedge> @christopherzimmerman is this a pretty consequential bottleneck for you?
Yxhuvud has quit [Quit: No Ping reply in 180 seconds.]
<FromGitter>
<christopherzimmerman> Yea it's pretty massive. I need to be able to support strided containers and I can't have them be thousands of times slower to access
<FromGitter>
<tenebrousedge> @kinxer using play is not going to get an accurate benchmark
<FromGitter>
<kinxer> I'm just using it to share the code.
<FromGitter>
<kinxer> I compiled it on my machine, using `--release` (after getting an even worse comparison of ~20,000x from the code he had).
<FromGitter>
<kinxer> Also, I've never even been able to make play run a benchmark.
<FromGitter>
<tenebrousedge> oh, it does it, but it has to be a pretty simple benchmark
<FromGitter>
<asterite> Yeah, for me all of the timings are similar. Did you compile/run with `--release`? The instance variable is read once so it shouldn't make a difference
<FromGitter>
<christopherzimmerman> @asterite are you talking about my original timings or the ones just posted?
<FromGitter>
<asterite> I'm talking about the benchmarks and the timings I get
<FromGitter>
<Blacksmoke16> also what OS @christopherzimmerman ?
<FromGitter>
<asterite> Oh, with `i` it's very different
<FromGitter>
<asterite> but all these benchmarks are flawed because you don't do anything with the result
<FromGitter>
<asterite> so the compiler (in this case LLVM) is free to discard the results
<FromGitter>
<asterite> more so with `i` than `i*2`
<FromGitter>
<absolutejam_gitlab> woah, I didn't know Lucky used Crystal to render the HTML
<FromGitter>
<tenebrousedge> personally I have a hard time distinguishing microseconds from nanoseconds under the best of circumstances
<FromGitter>
<absolutejam_gitlab> That was badly worded
<FromGitter>
<absolutejam_gitlab> I really want to use Crystal for my web app but there's not a solid GraphQL implementation
<FromGitter>
<asterite> Another thing
<FromGitter>
<asterite> when you pass literals the compiler is able to compute the result right way (again, this is done by LLVM)
<FromGitter>
<asterite> with a local variable that doesn't change LLVM should be able to do the same
<FromGitter>
<asterite> However, each block given to benchmark will form a closure over local variables at the top-level, and so this means the variables will be allocated on the heap and read from there
<FromGitter>
<asterite> that's why the literal works so much faster
<FromGitter>
<asterite> I'll try to move the var inside the block and see what happens
<FromGitter>
<asterite> but I can't imagine `step` being a bottleneck in a program
<FromGitter>
<kinxer> Yeah, using an outside variable is an even closer comparison (again, using play just to share code): https://play.crystal-lang.org/#/r/7vyh
<FromGitter>
<asterite> same goes with `f`, which is closured so it will affect the benchmark, more so with these things that usually take nanoseconds to complete, so accessing the heap memory might be slower than that
<FromGitter>
<asterite> Here there are no closured variables, and I also used `struct` for `Foo` since I assume it's immutable. All different approaches result in the same performance
<FromGitter>
<tenebrousedge> nice
<FromGitter>
<kinxer> And you used `&+=` as a much faster (non-overflowing?) operation?
<FromGitter>
<asterite> I used it because otherwise it will overflow and stop the benchmark from running
<FromGitter>
<christopherzimmerman> So if I'm understanding, my code wasn't necessary running slower, the benchmark was just bad?
<FromGitter>
<kinxer> Right, but my other point was that it was faster than the `*=` I used above.
<FromGitter>
<asterite> I think the `benchmark` module is in a way a bit flawed because results might change depending on closured variables, but if that's affecting the benchmark it means the benchmarked thing is probably super fast (like in this case, 1.2ns)
<FromGitter>
<asterite> @christopherzimmerman kind of. Some blocks in the benchmark closured some variables and that happens to be slower than incrementing numbers
<FromGitter>
<tenebrousedge> real-world performance measures are also usually more useful than artificial benchmarks
duane has joined #crystal-lang
<FromGitter>
<christopherzimmerman> Really appreciate the help, thanks all!
<FromGitter>
<wontruefree> Are there any docs on crystals arithmetic order of operations?
alexherbo2377 has quit [Ping timeout: 268 seconds]
alexherbo2377 has joined #crystal-lang
alexherbo2377 has quit [Ping timeout: 240 seconds]
<FromGitter>
<greenbigfrog> @Blacksmoke16 It's simply a array of JSONable objects ⏎ (worked around it for now by simply storing it seperately in redis, but I'd actually like it to expire like a kemal session)
<FromGitter>
<christopherzimmerman> Unfortunately I can't have my class as a struct since I need to be able to pass it by reference, but it seems that is where all the performance gain is.
<FromGitter>
<jwoertink> If I make a file that does `raise "test"`, run it, then do `echo $?` I'll get 1 as a status code
<FromGitter>
<jwoertink> assuming that file is `test.cr`, I have this code
<FromGitter>
<j8r> even `Process.run("exit 1", shell: true)` return `256`
<FromGitter>
<j8r> I got an exit status of `512` lol
<FromGitter>
<j8r> `Process.run("ls", {"-P"})`
<FromGitter>
<jwoertink> lol
<FromGitter>
<ilanpillemer> Yup. I searched for Queue!
<FromGitter>
<j8r> there is an issue here
<FromGitter>
<jwoertink> I don't really understand what the issue is. I would think if errors only go to 255, then we should never see 256 returned, right?
<FromGitter>
<j8r> yes
<FromGitter>
<j8r> The implementation uses `Int32`, because others OS other than POSIX may support higher exit status
<FromGitter>
<Blacksmoke16> which seems like is what i want? it helps on the memory front but not as low as i thought it would be when its done
<FromGitter>
<tenebrousedge> cursor sounds like your boy there
<FromGitter>
<tenebrousedge> if you want to do it low-level
<FromGitter>
<tenebrousedge> the way `query_each` is done, it seems like it fetches the whole result, and then yields each element
<FromGitter>
<tenebrousedge> so you minimize db roundtrips at the expense of memory
<FromGitter>
<Blacksmoke16> i think i could add something to granite that wraps that
<FromGitter>
<tenebrousedge> if you really want to minimize memory, you probably need to use cursors
<FromGitter>
<kaukas_gitlab> Hi! Upgrading Crystal one of my specs broke. Turns out in the latest version `[false, true, true, true].first(3)` results in `[false, false, false]`. Why?...
<FromGitter>
<Blacksmoke16> like either way the data is going to have to be selected from the db yea?
<FromGitter>
<tenebrousedge> you can do it piecemeal, but you're going to pay some kind of performance penalty either way
<FromGitter>
<Blacksmoke16> so ideal flow would be like `select data from db, for each RS new up a model obj and yield it, gc that object, repeat until no data left`
<FromGitter>
<Blacksmoke16> then you're only loading the one class obj into memory at a time?
<FromGitter>
<Blacksmoke16> which would be like 50% reduction in memory yea?
<FromGitter>
<tenebrousedge> I think so
<FromGitter>
<tenebrousedge> I mean, no idea about the memory reduction
<FromGitter>
<Blacksmoke16> ill have to test it :P
<FromGitter>
<Blacksmoke16> @tenebrousedge anyway, true; having one orm obj at a time would be ideal, have access to all the extra methods/functionality
<FromGitter>
<ilanpillemer> amazing that something that looks so simple explodes so much
<FromGitter>
<Blacksmoke16> i.e. in my use case having 1 full obj in memory at a time would be better than 12,000 :P
<FromGitter>
<tenebrousedge> for sure
<FromGitter>
<ilanpillemer> streaming can save your day
<FromGitter>
<Blacksmoke16> oh?
<FromGitter>
<ilanpillemer> thats why.. sed
<FromGitter>
<Blacksmoke16> hm?
<FromGitter>
<ilanpillemer> also map-reduce
<FromGitter>
<tenebrousedge> D: sed
<FromGitter>
<ilanpillemer> yes. thats why it exists
<FromGitter>
<ilanpillemer> [s]treaming [ed]itor
<FromGitter>
<tenebrousedge> I just got on the vim train T__T dun make me sed. awk is also sadness
<FromGitter>
<Blacksmoke16> oh sorry i thought you were referring to my db issue :P
<FromGitter>
<ilanpillemer> its the same old issue
<FromGitter>
<ilanpillemer> as old as computer and memory
<FromGitter>
<ilanpillemer> and more stuff than memory
<FromGitter>
<ilanpillemer> and you need to process it
<FromGitter>
<ilanpillemer> if the data base can do cursors you can use those
<FromGitter>
<ilanpillemer> cursors == iterators
<FromGitter>
<ilanpillemer> some dbs offer ‘offset’ and ‘limit'
<FromGitter>
<ilanpillemer> thats what I am using for something db related I process
<FromGitter>
<ilanpillemer> I use limit for the number of records I get at a time
<FromGitter>
<Blacksmoke16> im assuming there isnt anything for that in the db driver shards :/
<FromGitter>
<ilanpillemer> I then increase the offset
<FromGitter>
<Blacksmoke16> but yea that sounds like it would be super helpful
<FromGitter>
<ilanpillemer> until I get no more records
<FromGitter>
<tenebrousedge> `offset` and `limit` will probably work, but I would hesitate to rely on that
<FromGitter>
<ilanpillemer> in my case, I have no other choice
<FromGitter>
<tenebrousedge> as far as I'm aware, either you're going to lock the table or you're going to have issues with writes
<FromGitter>
<ilanpillemer> in general or with Crystal?
<FromGitter>
<tenebrousedge> in general
<FromGitter>
<ilanpillemer> Why?
<FromGitter>
<tenebrousedge> because tables aren't immutable?
<FromGitter>
<ilanpillemer> you mean because someone could update the table during the process?
<FromGitter>
<ilanpillemer> So what I do.. is I actually stream it twice into a temporary place. And then compare and check the results are the same.
<FromGitter>
<ilanpillemer> sadness
<FromGitter>
<ilanpillemer> as I said.. no other choice
<FromGitter>
<Blacksmoke16> doing `.all` used `52mb` doing query_each directly did `29`
<FromGitter>
<ilanpillemer> my query is in gigabytes
<FromGitter>
<tenebrousedge> `each` looks like it wants to be `each_with_object`
<FromGitter>
<ilanpillemer> Yes!
<FromGitter>
<ilanpillemer> though I wonder if this thing will ever finish
<FromGitter>
<ilanpillemer> I may need to find ways to prune the solution space
<FromGitter>
<kinxer> Oh, "breadth-first search". This is the one you're doing for an AoC puzzle?
<FromGitter>
<tenebrousedge> *nods*
<FromGitter>
<ilanpillemer> day 11
<FromGitter>
<ilanpillemer> so far the hardest day in the set for 2016
<FromGitter>
<ilanpillemer> and it looks so simple
<FromGitter>
<ilanpillemer> you can see the recursive piece too with the `e.parent = n`
<FromGitter>
<ilanpillemer> its probably a hanoi look alike
<FromGitter>
<kinxer> If you're looking for the minimum number of steps, would that solution space be limited to only those solutions who have fewer steps than whatever your current minimum is?
<FromGitter>
<ilanpillemer> bfs always finds mininum steps as the frontier opens up one level at a time
<FromGitter>
<ilanpillemer> but just spotted an error in my solved so restarting
<FromGitter>
<ilanpillemer> I wonder if it even works
<FromGitter>
<ilanpillemer> can you a hash as a key in a hash?
duane has quit [Ping timeout: 265 seconds]
<FromGitter>
<ilanpillemer> or do I need to work out some serialisation to use as key?
<FromGitter>
<tenebrousedge> it works
<FromGitter>
<ilanpillemer> even if the insertion order was different?
hightower4 has quit [Read error: Connection reset by peer]
<FromGitter>
<tenebrousedge> > Two objects refer to the same hash key when their hash value (Object#hash) is identical and both objects are equal to each other (Object#==)
<FromGitter>
<tenebrousedge> I suspect that the hash hashes will differ
<FromGitter>
<ilanpillemer> day 23 (not 22) I had to go to reddit in the end for help
<FromGitter>
<ilanpillemer> Day 23 part 2 was the only one I could not solve without hints
<FromGitter>
<ilanpillemer> 2018
<FromGitter>
<ilanpillemer> But I got very close.. using a stochastic random walk
<FromGitter>
<ilanpillemer> I should have realised that the random walk should have snapped to a valid radius.. then I think my original algorithm might have worked.
<Yxhuvud>
Yeah I also had major issues with that one.
<FromGitter>
<ilanpillemer> topaz posted that day 23 part 2 he considered the most difficult puzzle of 2018
<FromGitter>
<ilanpillemer> so that made me feel a bit better about it
<Yxhuvud>
Yes, though getting all the details right in the elf grand melee was a nice runner up
<FromGitter>
<ilanpillemer> that was just very painful
<FromGitter>
<ilanpillemer> mhy final bug was a resurrecting elf
<FromGitter>
<ilanpillemer> if someone moved into a dead spot, the original elf in that spot resurected
<Yxhuvud>
funniest was day9. my 14 lines of code happily accepted the bigger problem while still being ridiculously fast.
<FromGitter>
<ilanpillemer> I actually found the magic missile thingie from 2015 harder because I stupid and didnt do it immutable