jhass changed the topic of #crystal-lang to: The Crystal programming language | http://crystal-lang.org | Crystal 0.28.0 | Fund Crystal's development: http://is.gd/X7PRtI | GH: https://github.com/crystal-lang/crystal | Docs: http://crystal-lang.org/docs/ | API: http://crystal-lang.org/api/ | Gitter: https://gitter.im/crystal-lang/crystal
<FromGitter> <Blacksmoke16> havent used em too much
<FromGitter> <mwlang> I'm not easily impressed, but I have to say after reading the guide on concurrency that this is the most intuitive way I have ever seen currency implemented in a language.
<FromGitter> <Blacksmoke16> 💯
<FromGitter> <mwlang> and yet another whole class of Ruby idioms I need to drop like a hot potato to do it the Crystal way.
<FromGitter> <mwlang> one question: The guide states, "A Crystal program executes in a single operating system thread" Does this mean a crystal program won't take advantage of all CPU cores available on a computer? (same as Ruby)
<FromGitter> <Blacksmoke16> crystal doesnt have MT yet
<FromGitter> <Blacksmoke16> its single threaded
<FromGitter> <mwlang> ok, so same thing with Ruby processes.
<FromGitter> <Blacksmoke16> https://github.com/crystal-lang/crystal/blob/master/CHANGELOG.md#concurrency there is some progress towards it
<FromGitter> <Blacksmoke16> its a goal for `1.0.0`
<FromGitter> <mwlang> nothing to complain about at this point since it's already much faster than Ruby.
<FromGitter> <Blacksmoke16> indeed
<FromGitter> <Blacksmoke16> avoid generics, they kinda broken
<FromGitter> <mwlang> what are generics? haven't encountered that in reading, yet.
<FromGitter> <Blacksmoke16> `T`
<FromGitter> <Blacksmoke16> like avoid complex usages using like `MyClass(T)`
rohitpaulk has quit [Ping timeout: 245 seconds]
<FromGitter> <Blacksmoke16> https://play.crystal-lang.org/#/r/6tmj
<FromGitter> <Blacksmoke16> 😠
<FromGitter> <mwlang> oh, I see...yeah, already ran into that issue
<FromGitter> <Blacksmoke16> removing the `M` generic from the base class, or changing the block arg so they are diff fixes it
<FromGitter> <mwlang> I tried to implement extending the Array class but couldn't figure out how to get that generic T working
<FromGitter> <Blacksmoke16> easy
<FromGitter> <Blacksmoke16> https://play.crystal-lang.org/#/r/6tml
<FromGitter> <mwlang> well, that's easy, but what I wanted to do was instantiate an Array with a max size.
<FromGitter> <mwlang> such that when max size is reached and a new element is added, the first element in array is shifted off
<FromGitter> <mwlang> This is what I implemented: https://play.crystal-lang.org/#/r/6tmn
<FromGitter> <mwlang> Proxy design pattern, I believe.
<FromGitter> <Blacksmoke16> sec
<FromGitter> <mwlang> a lot of indicators, like simple moving averages (SMA) or RSI have a lookback window (X number of candles) in their formulas, so a simple class like this can keep exactly the number of data points I want on the array at all times without explicitly managing in the SMA or RSI class.
<FromGitter> <mwlang> btw, I didn't realize Crystal could reopen classes like Ruby can -- simply hadn't gotten that far, yet! Great example showing that.
<FromGitter> <Blacksmoke16> the point being like `def <<(value : T)`
<FromGitter> <Blacksmoke16> so now if you tried to do like `arr << "foo"` would do
<FromGitter> <Blacksmoke16> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5cca3b59a4ef097471331980]
<FromGitter> <Blacksmoke16> because its restricted to `Int32` since you did `BoundArray(Int32).new`
<FromGitter> <Blacksmoke16> also does your `[]` method do the same thing the array version does?
<FromGitter> <mwlang> almost.
<FromGitter> <Blacksmoke16> https://play.crystal-lang.org/#/r/6tn3
<FromGitter> <Blacksmoke16> can also include a `forward_missing_to @array` so that a method you dont define on `self` would attempt to use array
<FromGitter> <Blacksmoke16> i.e. basic can use all array methods on it now
<FromGitter> <mwlang> main diff is that it I almost always want to start counting at right-most (newest) values on the array
<FromGitter> <Blacksmoke16> and they'll be forwarded to `@array`
<FromGitter> <mwlang> so [-1] and [0] would be right-most element
<FromGitter> <mwlang> [-2] and [1] would be next to last.
<FromGitter> <Blacksmoke16> fair enough
<FromGitter> <Blacksmoke16> sorry, another thing you could set the type of `max_size` to `UInt32`, then would get a compile error if you tried to use a negative value, vs a runtime error
<FromGitter> <Blacksmoke16> https://play.crystal-lang.org/#/r/6tna
<FromGitter> <mwlang> that's why there's also a "safe_slice" in the beginning of populating the array, there's not enough elements to fill, say 10 values, so it's not just sum and divide by 10. we'll take mean from 2 elements until it reaches it's cap at 10 (or whatever it is we're doing with X number of elements where I need always X elements...the first element serves to fill up the void.
<FromGitter> <mwlang> good tip.
<FromGitter> <Blacksmoke16> https://crystal-lang.org/api/0.28.0/Deque.html might also get a perf boost from using that vs Array, depending on the size of your thing
laaron- has joined #crystal-lang
laaron has quit [Remote host closed the connection]
<FromGitter> <mwlang> hmmm...almost would work.
<FromGitter> <mwlang> some array sizes are about 4000 data points.
<FromGitter> <Blacksmoke16> could benchmark it
<FromGitter> <Blacksmoke16> https://crystal-lang.org/api/0.28.0/Benchmark.html id be interested in seeing the diff
<FromGitter> <mwlang> but when there's, say 300 data points, can't get a correct computation if (3700 of them are zero).
<FromGitter> <Blacksmoke16> yea for sure
<FromGitter> <mwlang> I need to base computations off exactly 300 data points in that case.
<FromGitter> <Blacksmoke16> wait you do know i just meant do like `@array = Deque(T).new` instead of `@array = Array(T).new`
<FromGitter> <Blacksmoke16> :s
alexherbo29 has joined #crystal-lang
<FromGitter> <mwlang> oh, wait....#new is overloaded...I only read the first definition!
<FromGitter> <mwlang> which indicated a size was set at the outset.
<FromGitter> <mwlang> (still getting used to this)
alexherbo2 has quit [Ping timeout: 258 seconds]
<FromGitter> <mwlang> I'll benchmark and see what I get.
<FromGitter> <Blacksmoke16> 👍
<FromGitter> <Blacksmoke16> prob only makes a big diff with a lot of pushes/large ize
<FromGitter> <mwlang> when I'm used to 9 minutes in Ruby and < 4 seconds for same in Crystal....hard to think, "hey, I can squeeze even more out"
<FromGitter> <Blacksmoke16> :p
<FromGitter> <mwlang> one day, I'll be crying that 4 seconds is too slow. but today, jumping with joy on cloud 9
<FromGitter> <mwlang> by then, parallel processing will be reality.
<FromGitter> <Blacksmoke16> indeed
<FromGitter> <mwlang> looks like no difference in speed with 100,000 pushes.
<FromGitter> <mwlang> both clocked 0.007s
<FromGitter> <Blacksmoke16> sec
<FromGitter> <mwlang> I should probably find a better way to benchmark than using "time" if I am going to get serious about benching crystal apps.
<FromGitter> <Blacksmoke16> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5cca40ed8446a6023eae6c43]
<FromGitter> <Blacksmoke16> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5cca410fb489bb6ed7fd08c4]
<FromGitter> <Blacksmoke16> :s
<FromGitter> <mwlang> nice
<FromGitter> <Blacksmoke16> Not what I was expecting
<FromGitter> <mwlang> I got slightly different results.
<FromGitter> <mwlang> 1) 000661 for Array, 0.000420 for Deque
<FromGitter> <mwlang> just using plain Benchmark.measure
<FromGitter> <mwlang> you flipped the report names and the classes you invoked!
<FromGitter> <Blacksmoke16> Lol
<FromGitter> <Blacksmoke16> That would do it
<FromGitter> <Blacksmoke16> Good call :p
<FromGitter> <Blacksmoke16> Well there you go, the deque one is 9x faster in this test at least
<FromGitter> <mwlang> I'm sold. going with Deque
<FromGitter> <mwlang> premature optimization, but who cares! This is pure gold.
<FromGitter> <mwlang> three days into Crystal and I'm already near enough to replace a giant mess of processes for collecting ticker, order books, and trade data from binance.
<FromGitter> <mwlang> every trick in the book to boost Ruby was played from threading, to using Rake to fork multiple processes to pushing to Redis and later processing to DBMS with yet more processes, dockerizing the whole thing into microservices and so on.
<FromGitter> <mwlang> one simple cyrstal script and we have enough performance to do it all.
<FromGitter> <Blacksmoke16> Indeed
<FromGitter> <Blacksmoke16> Maybe rerun that benchmark to simulate something you'd be doing
<FromGitter> <Blacksmoke16> Like smaller size, less iterations etc
<FromGitter> <mwlang> oh, I definitely will.
<FromGitter> <mwlang> but the Deque class meets the exact needs I'm using it for.
<FromGitter> <mwlang> constantly pushing data onto one end and shifting it off the other end.
<FromGitter> <mwlang> tailor made, if you ask me.
laaron- has quit [Remote host closed the connection]
laaron has joined #crystal-lang
lucasb has quit [Quit: Connection closed for inactivity]
<FromGitter> <Blacksmoke16> I guess so :)
alexherbo29 has quit [Ping timeout: 245 seconds]
laaron has quit [Remote host closed the connection]
laaron has joined #crystal-lang
f1refly has quit [Ping timeout: 250 seconds]
f1refly has joined #crystal-lang
rohitpaulk has joined #crystal-lang
rohitpaulk has quit [Ping timeout: 250 seconds]
laaron has quit [Quit: ZNC 1.7.1 - https://znc.in]
laaron has joined #crystal-lang
laaron has quit [Remote host closed the connection]
laaron has joined #crystal-lang
rohitpaulk has joined #crystal-lang
rohitpaulk has quit [Remote host closed the connection]
<jokke> hey
<jokke> afair crystal already kinda caches compile results somewhere to speed up subsequent compilations. Where is this cache located?
<FromGitter> <Val> @jokke: See `CRYSTAL_CACHE_DIR` environment variable, default is `$HOME/.crystal` as far as I know
<jokke> ah nice thanks
<FromGitter> <Val> `man crystal`
ashirase has quit [Ping timeout: 244 seconds]
laaron has quit [Remote host closed the connection]
laaron has joined #crystal-lang
DTZUZO has quit [Ping timeout: 255 seconds]
ashirase has joined #crystal-lang
RyanMcCoskrie has joined #crystal-lang
<FromGitter> <mavu> Morning, I want to automatically include/read version information when the project is compiled.
<FromGitter> <mavu> does anyone have a quick link or hint for some inspiration of how to do that? (i.e. steal code) :P
<FromGitter> <mavu> for example, read the debian changelog file and extract the topmost entry, or start a command and capture its output at compile time
RyanMcCoskrie has quit [Remote host closed the connection]
dom96 has quit [Ping timeout: 255 seconds]
dom96 has joined #crystal-lang
<FromGitter> <bew> You can do that from macros, using simple shell commands, or if you need to do more, use the `run` macro method
<FromGitter> <bew> https://crystal-lang.org/api/0.28.0/Crystal/Macros.html#run(filename,*args):MacroId-instance-method
alexherbo2 has joined #crystal-lang
<FromGitter> <j8r> mps how goes the Crystal 0.28.0 upgrade on Alpine?
<mps> j8r: good, yesterday everything is finished and tested
<mps> I hope that I will push it to aports this night or tomorrow
<FromGitter> <j8r> great, good job 🚀
<mps> it takes time to build and 'make specs' so I don't want to choke builders when most dev's work on fixing other bugs
<mps> but, i din't manage to overcome dependency and build crystal-bootstrap apk
<mps> still use prebuilt static version tar balls
<FromGitter> <mavu> thanks @bew . do you happen to know how I can purge the compile cache? ⏎ ⏎ `````` [https://gitter.im/crystal-lang/crystal?at=5ccad74b375bac747040f1da]
<FromGitter> <r00ster91> you need to put 3 ` at the end too
<FromGitter> <mavu> thanks, reading is a skill I still need to master :)
<FromGitter> <gdotdesign> @mavu I managed to clear the cache with `rm -rf ~/.cache/crystal` (Ubuntu)
<FromGitter> <gdotdesign> > for example, read the debian changelog file and extract the topmost entry, or start a command and capture its output at compile time? ⏎ ⏎ You can execute commands in a macro, in Mint it reads the version from the yaml file: https://github.com/mint-lang/mint/blob/master/src/commands/version.cr#L10
<FromGitter> <gdotdesign> or the `read_file` macro https://crystal-lang.org/api/0.28.0/Crystal/Macros.html#read_file(filename):StringLiteral-instance-method
<jokke> can i create a named pipe/fifo with crystal?
<jokke> i need to pass a file descriptor to a c lib but don't want to write the data to a file
DTZUZO has joined #crystal-lang
<FromGitter> <bew> jokke: there is `LibC.mkfifo`, but no wrapper
<mps> j8r: speaking aobut crystal apk, I had to disable one 'spec' check, 'it "detects stack overflow on the main stack" do' in spec/std/kernel_spec.cr
<mps> what do you think, is it safe or it needs fix in crystal
<mps> also, straight-shoota what do you think about it
<jokke> yup found it!
<jokke> thanks bew
<FromGitter> <mwlang> great write up on crystal performance with insight relative to same issues in Ruby. This was a great way for me to start to unlearn a few Ruby hacks garnered over the years for various micro-optimizations: https://github.com/konung/fast-crystal
<FromGitter> <j8r> @mwlang FYI we are working on a merge of https://github.com/konung/fast-crystal and https://github.com/icyleaf/fast-crystal with @konung and @icyleaf https://github.com/language-benchmarks/fast-crystal
lucasb has joined #crystal-lang
<FromGitter> <mwlang> sounds like a great idea to merge those.
<FromGitter> <mwlang> one thing that surprises me...Crystal is in the middle of the pack here: https://www.techempower.com/benchmarks/#section=data-r17&hw=ph&test=update&l=zdjqpr-1
<FromGitter> <mwlang> comparing Go, Ruby, JS, Python and Crystal. That doesn't seem right to me given what I've seen already in, oh, four days now.
<FromGitter> <kinxer> I hope they compiled with `--release`. :P But it could be because Crystal isn't multithreaded yet.
<FromGitter> <straight-shoota> mps, yes it's totally fine to ignore this spec
<z64> you could check; the techempower configs are in a repo somewhere. IIRC they might already be doing something like `SO_REUSEPORT` with multiple processes to compensate that mt hasn't landed yet
<FromGitter> <straight-shoota> This is already tracked in #7482
<DeBot> https://github.com/crystal-lang/crystal/issues/7482 (Stack overflow detection failure)
<FromGitter> <mwlang> I checked. They're compiling with nodebug and release flags.
<FromGitter> <ArtLinkov> Hi all, ⏎ I'm looking for a library that can parse a PNG file and returns an object that includes all the params and extension (i.e png.timestamp >> date+time_
<FromGitter> <ArtLinkov> I found this lib but it doesn't have it afaik ⏎ https://github.com/stumpycr/stumpy_png
greengriminal has joined #crystal-lang
<FromGitter> <Blacksmoke16> time to make a PR ;)
laaron has quit [Remote host closed the connection]
<FromGitter> <ArtLinkov> @Blacksmoke16 😭 ⏎ I guess I got no other choice huh?
laaron has joined #crystal-lang
<FromGitter> <alehander42> hey guys
<FromGitter> <alehander42> what do the crystal frameworks use usually as a server?
<FromGitter> <alehander42> do you have your own servers written in crystal, do you reuse existing ones, does anybody do its own thing
jeremycw has joined #crystal-lang
<FromGitter> <fridgerator> @ArtLinkov do any of these do what you need? https://crystalshards.xyz/?filter=image
<FromGitter> <fridgerator> There is also a library that wraps the image magick command line : https://crystalshards.xyz/?filter=imagemagick
<FromGitter> <Blacksmoke16> server for what? like Rails or REST api or?
<FromGitter> <fridgerator> @alehander42 You can use the standard library http server, or there are many frameworks / servers already written : https://github.com/veelenga/awesome-crystal#web-frameworks
<jokke> what's the quickest way to turn a bunch of items with an id method into a hash with id as keys and the corresponding item as value?
<FromGitter> <alehander42> yeah @fridgerator thanks
<FromGitter> <alehander42> so do lucky/amber e.g. define their own server impls or do they wrap/work usually with existing ones
<FromGitter> <alehander42> i am not sure i could find definite info on a quick glance
<FromGitter> <fridgerator> they all wrap the standard libraray http server
<FromGitter> <alehander42> i see
<FromGitter> <alehander42> i wondered which approach should i use if i decide to write a nim framework
<FromGitter> <alehander42> so the standard http server is pretty optimized/supports most important protocols correctly?
<FromGitter> <alehander42> nice
moei has joined #crystal-lang
<FromGitter> <ArtLinkov> Oh nice! Thanks @fridgerator I think that's exactly what I was looking for! 😁
<FromGitter> <kinxer> @jokke Does this work? https://carc.in/#/r/6tst
<jokke> hm
<mps> straight-shoota: thanks for explanation and help
<jokke> not sure if that's faster than just using `Hash(...).new(list.size).tap { |hash| list.each { |item| hash[item.id] = item } }`
<FromGitter> <Blacksmoke16> https://play.crystal-lang.org/#/r/6tt2 ?
<FromGitter> <Blacksmoke16> yea pretty much what i had
<FromGitter> <kinxer> @jokke Yeah, I have no idea about its speed. I think it's probably the most readable way (and the shortest), though.
<jokke> mhm
<FromGitter> <Blacksmoke16> `Hash.zip(arr.map(&.id), arr.map(&.itself))`
<FromGitter> <Blacksmoke16> er yea, dont really need the 2nd map as @kinxer showed if its already in an array
<FromGitter> <kinxer> A quick benchmark (code here (https://carc.in/#/r/6tt7)) shows that `#tap` is a bit faster: ⏎ ⏎ ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5ccb0b81e416b845191a8682]
<FromGitter> <kinxer> I'd bet a lot of that is the `pair_array.map(&.id)`.
<FromGitter> <kinxer> I found a couple other ways to do it: https://carc.in/#/r/6ttd
<FromGitter> <kinxer> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5ccb10276a84d76ed832824c]
ua_ has joined #crystal-lang
ua has quit [Ping timeout: 255 seconds]
laaron has quit [Remote host closed the connection]
laaron has joined #crystal-lang
Raimondi has joined #crystal-lang
<FromGitter> <shreeve> ```sockets = SOCKETS.keys.select {|key| key.is_a?(String)}.sort```
<FromGitter> <shreeve> keys of SOCKETS variable are (HTTP::WebSocket | String)...
<FromGitter> <Blacksmoke16> got a playground link?
<FromGitter> <asterite> You can do `SOCKETS.keys.select(String).sort` if you are on 0.28.0
<FromGitter> <Blacksmoke16> neat
<FromGitter> <shreeve> I'm selecting just the stings out from the keys and then trying to sort, but getting an error that it cannot sort websockets (but the array will only have strings, so it should be ok)
<FromGitter> <shreeve> Aw! Great... trying now!
<FromGitter> <shreeve> beautiful! I *am* on 0.28.0, so that worked great!
<FromGitter> <shreeve> Thanks @asterite!
<FromGitter> <asterite> The "problem" with the original code is that the compiler can't figure out that only things of type `String` remain in the array (the `is_a?`thing only works for local variables)
<FromGitter> <asterite> glad to help :-)
<FromGitter> <Blacksmoke16> *interesting*
<FromGitter> <shreeve> That worked perfectly... :-)
<FromGitter> <shreeve> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5ccb33838446a6023eb51abf]
rohitpaulk has joined #crystal-lang
<FromGitter> <shreeve> the sort (first line) works great with 0.28.0 (clean!), the second line still has the "problem", since I can't tell the compiler that the only SOCKETS[connid] values will actually be HTTP::WebSocket objects... any way for me to say, "it's ok... I'm only passing values that are websockets?"
<FromGitter> <Blacksmoke16> would a `.as(HTTP::WebSocket)` solve that?
<FromGitter> <shreeve> where would I add that @Blacksmoke16 ?
<FromGitter> <Blacksmoke16> `SOCKETS[connid].as(HTTP::WebSocket).closed?`?
<FromGitter> <shreeve> ok, will try now
<FromGitter> <shreeve> hot diggity! that worked too... :-)
<FromGitter> <Blacksmoke16> nice
jeremycw has quit [Ping timeout: 258 seconds]
laaron has quit [Quit: ZNC 1.7.1 - https://znc.in]
laaron has joined #crystal-lang
rohitpaulk has quit [Ping timeout: 258 seconds]
<FromGitter> <Blacksmoke16> @mwlang Remembered you can prob squeeze another 1x perf out of your boundArray by doing like `@array = Deque(T).new @max_size`
<FromGitter> <Blacksmoke16> basically telling the internal array the size it should allocate vs growing as you add things
jeremycw has joined #crystal-lang
PixeLInc has joined #crystal-lang
PixeLInc has left #crystal-lang ["WeeChat 2.1"]
jeremycw has quit [Ping timeout: 245 seconds]
rohitpaulk has joined #crystal-lang
rohitpaulk has quit [Ping timeout: 246 seconds]
greengriminal has quit [Quit: This computer has gone to sleep]
<FromGitter> <mwlang> @Blacksmoke16 you were right
<FromGitter> <mwlang> ~~~
<FromGitter> <Blacksmoke16> could also do the same for your array, prob make that a bit faster as well
<FromGitter> <mwlang> I gotta learn how to do markdown in gitter :-/
<FromGitter> <mwlang> That made the array implementation slightly slower.
<FromGitter> <Blacksmoke16> really?
<FromGitter> <Blacksmoke16> welp
<FromGitter> <mwlang> but doesn't matter. I'm going with Deque in the implementation.
<FromGitter> <mwlang> I'm going to focus for a while on building using revelations from those fast-crystal idioms I shared earlier.
<FromGitter> <Blacksmoke16> sounds like a plan
<FromGitter> <mwlang> can circle back and optimize where performance dictates.
laaron- has joined #crystal-lang
laaron has quit [Ping timeout: 256 seconds]
olbat has quit [Max SendQ exceeded]
<FromGitter> <jaydorsey> @mwlang what was the time diff between crystal & ruby for what your’e working on?
laaron- has quit [Remote host closed the connection]
laaron has joined #crystal-lang
<FromGitter> <mwlang> huge. Let me run the benchmark again now that I know a little more what I'm doing.
<FromGitter> <mwlang> I'll be back in a few minutes and get this measured and posted.
<FromGitter> <bew> "a few minutes later.." *just kiddin'*
<FromGitter> <jaydorsey> Lol
<FromGitter> <bohtho> Never to be seen again. The old bait and switch. Leaving us all paralyzed like deer in headlights. He could be an agent from Nim 🤪😄
<FromGitter> <mwlang> Haha.
<FromGitter> <mwlang> Ruby script still running. I had been improving the Crystal code and optimizing since originally writing it.
<FromGitter> <mwlang> then I needed to adjust Ruby code to match logically.
<FromGitter> <mwlang> The code computes Bollinger bands for 450,000 data points.
<FromGitter> <mwlang> https://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:bollinger_bands
<FromGitter> <mwlang> The Crystal version:
<FromGitter> <mwlang> 1) 190000 0.040000 0.230000 ( 0.232463)
<FromGitter> <mwlang> The Ruby version is about 8 or 9 minutes...so it'll be a few minutes more... ;-)
<FromGitter> <mwlang> The Ruby version:
<FromGitter> <mwlang> 1) 140000 1.620000 482.760000 (483.079697)
<mps> j8r: crystal 0.28.0 is uploaded to Alpine edge for both arch's, x86_64 and aarch64
<FromGitter> <mwlang> I just realized the Crystal numbers were too low and it turns out I had two different lookback windows on the two benchmarks.
<FromGitter> <mwlang> So the corrected Crystal results:
<FromGitter> <mwlang> 1) 220000 0.090000 2.310000 ( 1.918516)
<FromGitter> <mwlang> Still a far cry from Ruby's.
<FromGitter> <bew> Nice results!
<FromGitter> <jaydorsey> wait, those are seceonds right?
<FromGitter> <jaydorsey> 1) 2 seconds vs 8 minutes?