jhass changed the topic of #crystal-lang to: The Crystal programming language | https://crystal-lang.org | Crystal 0.35.1 | Fund Crystal's development: https://crystal-lang.org/sponsors | GH: https://github.com/crystal-lang/crystal | Docs: https://crystal-lang.org/docs | Gitter: https://gitter.im/crystal-lang/crystal
<FromGitter> <Daniel-Worrall> The problem is that crystal is not ruby
<FromGitter> <Blacksmoke16> indeed
deavmi has quit [Read error: Connection reset by peer]
deavmi has joined #crystal-lang
f1refly has quit [Ping timeout: 246 seconds]
f1reflyylmao has joined #crystal-lang
<FromGitter> <wyhaines> @pciuch9, Crystal has a lot of the same ergonomics of Ruby, and it generally looks and feels like Ruby, but it isn't Ruby. ⏎ ⏎ When porting Ruby code, sometimes you need to make changes. ⏎ ⏎ IMHO, writing ... [https://gitter.im/crystal-lang/crystal?at=5f77e060b7db72780a1d1f70]
<FromGitter> <Blacksmoke16> `c; k; dd unless superhiper` 😉
<FromGitter> <Blacksmoke16> oh boy ` Module validation failed: Call parameter type does not match function signature!`
<FromGitter> <wyhaines> Yeah. I have a mixed relationship with unless. :) Sometimes I feel like `if !` is easier to follow.
<FromGitter> <Blacksmoke16> depends on how simple it is for me
<FromGitter> <Blacksmoke16> if any `&&` or `||` are involved thats a good point to switch to `if`
<FromGitter> <HertzDevil> ``````
<FromGitter> <HertzDevil> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5f77ecb28f2e9b6ac210b2b0]
<FromGitter> <HertzDevil> is there a reason `f` works but `g` doesn't?
<FromGitter> <HertzDevil> since crystal doesn't support covariant/contravariant types i'd expect `f` to also fail
<FromGitter> <HertzDevil> as `Array(Array(Int32)) < Enumerable(Enumerable(Int32))` is `false`
<FromGitter> <HertzDevil> well, `f` works even without an array expression, so that's probably not it
<FromGitter> <HertzDevil> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5f77f3fe65cb032060679ce9]
zorp has joined #crystal-lang
Liothen has quit [Ping timeout: 240 seconds]
Liothen has joined #crystal-lang
<FromGitter> <HertzDevil> someone said >3 years ago that everything is covariant when considering method overloads, and it seems the situation hasn't changed ever since
<FromGitter> <HertzDevil> kinda wish https://github.com/crystal-lang/crystal/issues/934#issuecomment-504766096 gets continued, guess it won't happen before 1.0.0 though
zorp has quit [Read error: Connection reset by peer]
r0bacarp has quit [Ping timeout: 258 seconds]
<FromGitter> <mattrberry> Its the left side of the graph here likely gc?
<FromGitter> <mattrberry> This is compiling with just shards build. Is there a better way to get better debugging information?
r0bacarp has joined #crystal-lang
<oprypin> mattrberry, did u run it exactly like this? https://forum.crystal-lang.org/t/profiling/2443/2
f1reflyylmao has quit [Quit: bye fags]
f1refly has joined #crystal-lang
<FromGitter> <j8r> oprypin: that's very useful commands! Definitely wort adding to crystal-book (if not already there)
_whitelogger has joined #crystal-lang
Human_G33k has quit [Remote host closed the connection]
Human_G33k has joined #crystal-lang
sagax has quit [Read error: Connection reset by peer]
<FromGitter> <j8r> I try to use the doc generator inside a project, that's a hell
<FromGitter> <j8r> inside the crystal compiler, there are circle dependencies everywhere :(
<FromGitter> <j8r> and/or files does no require what they need to
<FromGitter> <j8r> I'm ending up using `require "compiler/crystal/**"`
<FromGitter> <j8r> that's why I strongly think this syntax is a bad idea
<FromGitter> <j8r> I need LLVM to generate API docs... that's not good
<FromGitter> <Blacksmoke16> why do you need to require the compiler to generate docs?
<FromGitter> <Blacksmoke16> doing something custom or?
<FromGitter> <j8r> yep
<FromGitter> <Blacksmoke16> compiler wouldnt include anything the code you actually use doesn't so its not *terrible*
<FromGitter> <j8r> I would like to make my web router to have a special route, which serves the application's API docs
<FromGitter> <Blacksmoke16> wouldn't that just be a matter of displaying the swagger page?
<FromGitter> <Blacksmoke16> or really does a redirect to `./docs` :p
<FromGitter> <j8r> Swagger docs is more for the users, here it will be Crystal API docs of the classes/methods etc
<FromGitter> <j8r> Not really, because ideally not having to install crystal will be better
<FromGitter> <j8r> I could use a hack like `{{ `crystal docs` }}`, and embed the docs somehow in the app
<FromGitter> <Blacksmoke16> hm yea
<FromGitter> <Blacksmoke16> any reason the user should be generating them in the first place? They're static so can just host it on GH pages no?
<oprypin> j8r, you definitely shouldnt generate docs on the fly
<FromGitter> <j8r> That's simpler. One can have `/swagger` and `/api` out of the box
<FromGitter> <Blacksmoke16> have a `postinstall: crystal docs`
<FromGitter> <j8r> of `/api-docs` - you get the idea
<FromGitter> <Blacksmoke16> but imo id kinda not want that route auto added, like you would need a way to disable it in prod etc
<FromGitter> <j8r> Not automatically sure
<FromGitter> <j8r> Can be behind a flag, or anything
<FromGitter> <j8r> or environment variable, like for swagger docs - not everyone does Open Source ;)
<FromGitter> <Blacksmoke16> fair enough
<FromGitter> <j8r> If docs are generated separately, we have to make an archive to bundle the docs with the app somehow, and put them in a proper location server by the http server/application
<FromGitter> <Blacksmoke16> im still not sold on the need to include your framework docs with a user's application
<FromGitter> <j8r> that's done with Swagger docs, quite frequent to do so
<FromGitter> <Blacksmoke16> yea but swagger docs would be describing their application's endpoint, anyone who isnt devving on the app itself doesnt need to know about the framework
<FromGitter> <j8r> it will be Crystal API docs of the app, not the framework itself.
<FromGitter> <Blacksmoke16> ahh ok, that was the missing piece of info
<FromGitter> <Blacksmoke16> id just let them worry about it if they want
<FromGitter> <j8r> probably
<oprypin> what a weird thing to write. `File.open(file, &.read_line)`
<oprypin> wait, how do i make a temporary directory?
<FromGitter> <j8r> Use `Dir.mkdir File.tempname`
<FromGitter> <j8r> not a fan though
deavmi has quit [Quit: Eish! Load shedding.]
deavmi has joined #crystal-lang
<FromGitter> <mattrberry> @oprypin I just recorded it with the default perf settings that hotspot uses. I also didn’t build with —debug. I’ll give that a shot and see if it look’s any different when I get out of bed
<oprypin> well yea that's exactly what puts debug info
deavmi has quit [Read error: Connection reset by peer]
deavmi has joined #crystal-lang
_whitelogger has joined #crystal-lang
<FromGitter> <mattrberry> @oprypin Doesn't `crystal build` build for debug by default? I know it sets the `debug` compile-time flag..
<FromGitter> <mattrberry> Either way, the perf data is identical to what I sent earlier
<oprypin> mattrberry, i dont think so,no
<oprypin> --debug is definitely not just "lack of --release"
<FromGitter> <mattrberry> Then why does it set the `debug` flag?
<oprypin> dont know lol, maybe the debug flag *is* just lack of --release
<oprypin> mattrberry, tbh maybe you need to build libgc with --debug
<oprypin> or if youre on debianmaybe theres a dbg package for it
<oprypin> "build libgc with --debug" is a misnomer, of course --debug flag is specific to crystal and that one probably has some different way to specify that it's debug mode :)
<FromGitter> <mattrberry> Hmm I'll dig around
<FromGitter> <mattrberry> Also, I must be fundamentally missing something lol ⏎ ⏎ ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5f78cadfb949c45310bc4c77]
<FromGitter> <Blacksmoke16> i always thought debug was enabled by default
<FromGitter> <Blacksmoke16> i.e. try with `--no-debug`
<FromGitter> <Blacksmoke16> and would say either other or release
<FromGitter> <mattrberry> `--no-debug` says "other"
<FromGitter> <Blacksmoke16> 👍 makes sense
<FromGitter> <mattrberry> Why does `--release` still say "debug" though? :thinking:
<FromGitter> <Blacksmoke16> because you can still have a release binary with debug info no?
<FromGitter> <Blacksmoke16> `--release --no-debug` would say `release`
<FromGitter> <mattrberry> Oh hmm interesting
<FromGitter> <mattrberry> Would you assume the stuff on the left of this perf graph is gc? https://media.discordapp.net/attachments/465586361731121162/761872981558820884/unknown.png
<FromGitter> <Blacksmoke16> 😬 i have no idea
<oprypin> @mattrberry: what kind of setup do you have with libgc
<FromGitter> <Blacksmoke16> maybe? or maybe the event loop? :shrug:
<FromGitter> <mattrberry> Is there a way to run crystal with no gc just to test?
<FromGitter> <Blacksmoke16> `--gc-none`
<oprypin> oh good idea
<FromGitter> <mattrberry> > *<oprypin>* @mattrberry: what kind of setup do you have with libgc ⏎ ⏎ I have no clue. How do I tell?
<FromGitter> <mattrberry> > `--gc-none` ⏎ ⏎ ```Error: Invalid option: --gc-none``` [https://gitter.im/crystal-lang/crystal?at=5f78cbe81adcf94d3ffb92c8]
<FromGitter> <Blacksmoke16> mm sec
<oprypin> @mattrberry: `ldd the_binary` will show the path to libgc and I'm just asking what provides that library - probably your distro, then what distro is it?
<FromGitter> <mattrberry> This is Ubuntu 18.04 ⏎ ⏎ ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5f78cc5d17377c6b5dd763b5]
<FromGitter> <Blacksmoke16> `-Dgc_none`
<FromGitter> <Blacksmoke16> its a flag, not actually built into the cli
<oprypin> @mattrberry: woops you showed libgcc 😅 but whatever
<FromGitter> <mattrberry> Oh hmm well ldd doesn't show anythign for libgc 😬
<oprypin> oh uhhh what, does Crystal a libgc of its own statically
<oprypin> well then that just shows that it's a bit difficult to substitute for your own libgc
<oprypin> the easier path is indeed to disable gc and see
<FromGitter> <mattrberry> Hmm still seems to show up even when building with `shards build -Dgc_none`
<FromGitter> <mattrberry> I'm not sure what that would be though since it's showing up outside of the `__crystal_main`
<FromGitter> <Blacksmoke16> its deff that
<FromGitter> <Blacksmoke16> fwiw
<FromGitter> <mattrberry> I remember when I was working on my gameboy emulator and accidentally used classes instead of structs in one place, this is what it looked like because the gc was busy clearing everything
<FromGitter> <mattrberry> But this program should only have like 5 objects instantiated that remain over the lifetime of the program..
<FromGitter> <mattrberry> Everything else should be a value
<FromGitter> <Daniel-Worrall> So I know I can write ⏎ `method { |argument| argument.some_method }` ⏎ as ⏎ `method &.some_method` ⏎ but can I 1 line ... [https://gitter.im/crystal-lang/crystal?at=5f78d66edfe47e4d57467c5e]
<FromGitter> <Blacksmoke16> idt, there is `&->` but idt it'll help in this context
<FromGitter> <Daniel-Worrall> basically passing the yield to a different method instead of chaining methods to the yield
<FromGitter> <j8r> @Daniel-Worrall see https://github.com/crystal-lang/crystal/pull/9218
<FromGitter> <Daniel-Worrall> Oh yeah, I remember seeing that one
<FromGitter> <Blacksmoke16> heres prob a silly question, is there a method to know if a given index exists in an array?
<oprypin> Blacksmoke16, best is `0 <= x < array.size`
<FromGitter> <Blacksmoke16> i feeling adding a common API to `Indexable` could be helpful, as i think both array and hash include that
<FromGitter> <Blacksmoke16> but 👍 thanks
<oprypin> it's controversial because, ... does index -1 exist in the array?
<FromGitter> <Blacksmoke16> no
<FromGitter> <Blacksmoke16> imo `-1` isnt a valid index, its just a QoL thing that exists
<oprypin> fwiw i think any new programming language shouldnt support negative indices
<oprypin> Nim has `array[^1]` as syntax sugar for `array[array.size - 1]`
<FromGitter> <mattrberry> I'm totally lost on how to continue debugging this lol
<FromGitter> <mattrberry> But if I can't figure that out, gba on crystal is gonna be a pita
<FromGitter> <asterite> what's the problem?
<FromGitter> <asterite> I usually use instruments on Mac, it tells you which method takes the most time
<FromGitter> <asterite> it looks like include? takes most of the time?
<FromGitter> <asterite> also, if you can share a snippet or benchmark, I can run it on my machine and see if I can figure it out
<FromGitter> <asterite> it's strange that you can't see the class names... using instruments on Mac I see the full name of the function, which includes the class name
<oprypin> asterite, it's likely not a "snippet" but a whole complicated program (emulator). possibly even running a ROM
<FromGitter> <asterite> Ah, I see. I can try that too
<FromGitter> <mattrberry> @asterite Yeah I have a lot of optimization to do in the emulator itself still. I can get the includes? down to basically 0 with a little uglier code. My main concern at the moment is the 35% spent outside of the main program code. Any idea what might be contributing to that? I assumed it might be gc, but it's still there when compiling with `-Dgc_none`
<FromGitter> <mattrberry> Plus I don't believe I'm ever creating objects that need to be gc'd
<oprypin> mattrberry, so can you send someone everything needed to run this?
<FromGitter> <mattrberry> Yeah here's the repo right now. It's still pretty basic. If you don't have libsdl2 installed, I can tell you which lines to comment out. It should still have the same issue. I haven't created a minimal example yet though https://github.com/mattrberry/crab
<oprypin> mattrberry, how to run it
<oprypin> does it need input files or just run
<FromGitter> <mattrberry> Without libsdl2, you'll need to comment out: ⏎ ⏎ ```src/crab.cr:2 ⏎ src/crab/gba.cr:21 ⏎ src/crab/gba.cr:22 ⏎ src/crab/gba.cr:23``` ⏎ ⏎ and the contents of both methods in Display.cr [https://gitter.im/crystal-lang/crystal?at=5f78f282dfe47e4d5746c0be]
<FromGitter> <mattrberry> Oh yeah, let me send you a rom
<FromGitter> <mattrberry> So just run with `bin/crab path/to/m3_demo.gba`
<oprypin> Unimplemented instruction: 0x9300
<FromGitter> <mattrberry> oop, sorry lol. One sec, let me push my local changes
<FromGitter> <mattrberry> Okay go ahead and pull again :p
<oprypin> ok i see what you're seeing
<FromGitter> <asterite> can't resolve bitfield (running shards)
<oprypin> asterite, delete from shard.yml `- version: 0.1.0`
postmodern has joined #crystal-lang
<FromGitter> <mattrberry> Oh interesting, I must have had it installed before I added the version line. My b
<FromGitter> <mattrberry> Hmm as a side note, the shards install works fine for me even after deleting lib/. I wonder why that's not resolving for you guys..
<FromGitter> <asterite> I see this: https://imgur.com/undefined
<FromGitter> <asterite> well, not that...
<FromGitter> <asterite> https://imgur.com/a/PGnw9RJ
<FromGitter> <mattrberry> I'm trying to understand what yours is saying. Why does yours show multiple GBA#run ?
<FromGitter> <mattrberry> Hmm, according to this, much of the stuff grouped under the ?? is my methods as well. I wonder why it's grouping it outside of the main_user_code there?
<FromGitter> <mattrberry> I guess I could just work on the easy optimizations that I'm already aware of and see if that brings this other chunk back down..
<FromGitter> <asterite> good catch, I don't know why it appears multiple times
<oprypin> mattrberry, do u use threads??
<FromGitter> <mattrberry> I don't use threads
<FromGitter> <mattrberry> Unless you count the ones that SDL uses internally, but there aren't any outside of those
<FromGitter> <asterite> Well, I suggested using instruments but I can't figure out what's slow from that... sorry
<FromGitter> <mattrberry> Hey no worries! I appreciate both of you taking a look. I have to run, but I'll be back in a few hours to work on some other optimizations to see if that helps this issue..
<FromGitter> <asterite> I found something
<FromGitter> <asterite> In Bus#[] there's a to_u8
<FromGitter> <asterite> the reason is that some of the `when` return an Int32 (the last two)
<FromGitter> <asterite> If you change those 0xFF to 0xFF_u8 then you don't need that `to_u8` at the end
<FromGitter> <asterite> I guess that method is called a lot, and the current way is creating a union, then doing a dispatch... when it's not necessary
<FromGitter> <asterite> When I changed that the profile graph changes quite a bit
<FromGitter> <asterite> Can you try it?
<FromGitter> <asterite> In general, avoiding numeric unions whenever possible is best
<FromGitter> <mattrberry> Oh wow, good to know. I do that in a couple of places in CryBoy
<FromGitter> <mattrberry> I made the change on my end. Didn't seem to make a huge change in my perf graph, but it still bought me ~3 fps. I went from getting ~37-39 on this demo to now getting ~40-42
<FromGitter> <mattrberry> Looks even more fun in release :p
<FromGitter> <mattrberry> I have to run now unfortunately :/ I'll be back on in a few hours if you're still here :) Thanks again!!
<FromGitter> <asterite> I'll be able to take a look at it again on Monday
<FromGitter> <asterite> oh, crystal once is accessing a constant
<FromGitter> <asterite> so probably those ??? come from that
<FromGitter> <asterite> my bet is that inlining those range constants will improve things
<FromGitter> <asterite> that said, there's no reason why those ranges need to use that crystal_once... but constants like that are not well optimized
<FromGitter> <asterite> I wish we could optimize such constants... but I don't know how to detect these cases... maybe some other core team members, like waj and brian, can think of a solution
<FromGitter> <asterite> When I inlined the constants, I see that Range#includes? is the bottleneck
<FromGitter> <asterite> Also, where can I see the FPS?
<FromGitter> <asterite> I think doing `n <= index <= y` instead of using a constant range is your best bet... until the compiler gets smarter. Range is a nice convenience but right now not very good in hot paths
<FromGitter> <asterite> However, I just benchmarks doing `n <= index <= y` vs. `case index; n..y` and I'm seeing the same performance, so maybe using range is okay
<FromGitter> <asterite> Then there's an optimization we can do in the stdlib: array and deque#clear will clear out the memory so the GC can collect references... but that's not needed if the array or deque just holds numbers