oracle / truffleruby

A high performance implementation of the Ruby programming language, built on GraalVM.
https://www.graalvm.org/ruby/
Other
3k stars 184 forks source link

Correct PATH to truffle Ruby #1393

Closed 98-f355-f1 closed 6 years ago

98-f355-f1 commented 6 years ago

I encountered a bug or warning of some kind in one of my scripts. It concerns the use of the Time module in MRI Ruby, it seems. I get this warning from the Truffle VM

[ruby] WARNING could not find timezone (no file in usr/share/zoneinfo is the same as /etc/location), using UTC instead

I was running a MRI Ruby script with the Time module (Time.Now) to use as my timing benchmarks.

Any remedies?

Thanks

eregon commented 6 years ago

Hello, Thank you for your report.

I see that you removed your first question, did you find a solution for that? FWIW, one could add graalvm/jre/languages/ruby/bin in PATH. But, binaries like ruby, gem, irb, rake rdoc, ri, testrb and gem binaries will all conflict if you have another Ruby installation on PATH. That's why it is recommended to use a Ruby manager which ensures only one Ruby is on PATH and sets the proper GEM_HOME/GEM_PATH environement variables. This is documented at https://github.com/oracle/truffleruby/blob/master/doc/user/ruby-managers.md#configuring-ruby-managers-for-the-full-graalvm-distribution You can of course keep MRI as default and just rvm use truffleruby when you want to switch to TruffleRuby in the current terminal.

For the timezone warning, this means our logic to find the current timezone failed. I assume the warning you saw is:

could not find timezone (no file in /usr/share/zoneinfo is the same as /etc/localtime), using UTC instead

Please copy-paste the exact warning message you saw. Could you provide further details to help debugging this issue?

Finally, it is discouraged to use Time.now for benchmarking. Instead, a monotonic clock like Process.clock_gettime(Process::CLOCK_MONOTONIC) is recommended. This is also used by the benchmark standard library with puts Benchmark.realtime { ... }. There are of course also many benchmarking gems which use a monotonic clock and some of them also consider warmup too.

98-f355-f1 commented 6 years ago

Yes, I found the path to the GraalVM/jre/bin/truffleruby… so I fixed that part. You can of course keep MRI as default and just rvm use truffleruby when you want to switch to TruffleRuby in the current terminal.

As a lazy programmer, that's what I'd like to avoid is each time to run a script to switch the RVM all the time. I have disk space for as many gem libraries as I need đź‘Ť , just need to configure paths as best as possible, so that when I execute... "ruby version" "filename.rb" that it just works. and not have to go remembering, whether I reset the path on RVM. My thoughts at least.

I guess that I could write a parser script that parses the command line ruby filename and a flag then, execute a quick RVM change, then run the correct ruby. It would be cool, good programming practice... If it comes to that.

What is your operating system? I am using Windows 10 with the Debian / Linux WSL subsystem

Further, I have 2 different MRI, one for Linux, and one for Windows... I can use POSIX type functions in the Linux-MRI. MRI RUBY, JRUBY, TRUFFLE and CRYSTAL are in the Linux subsystem... and I primarily use the subsystem for programming, since I can use the entire C windows and C Linux/unix POSIX libraries, as well... similar to the Python, 2 separate versions. My goals are to see how to integrate C or Java into JRuby and Truffle, or C into Ruby and Python... since I have an extensive library of data structures that I build in Java while in grad school. I want to see how to interweave different structures as threads, processes, and coroutines... as well as benchmarking and see what is fastest.... all for good fun, but learning at the same time.

I will integrate the monotonic into my program, thanks. My goal is to test the different Rubies. While JRuby, TruffleRuby, Crystal and MRI all can use Benchmark. I like to use the Benchmark IPS, and its gem is benchmark-ips… it seems that JRuby and MRI have no issues with it, and Crystal has it integrated already in the source, while Truffle doesn't recognize it yet as a method. And this is what leads to my next question as far as gems along the Truffle path. I think that is the sole reason that I can't use the benchmark-ips gem in Truffle... it can't find the global path to my gems. I will look at the link.

I watched some older videos that show how the GraalVM can integrate Java, JS, Python, C, Ruby and call each other and compile and process... are there any special setups for that? I am a little lost on that part.

For example, how do I put calls to my Java library into a Truffle Ruby or Python program? Are there paths that I need to configure besides putting "require" and "import" statements? My Java programs were created using Eclipse, so sit there in those packages... do I need to make them into jars?

Yes, that is EXACTLY the warning message.

Can you show the output of ls -l /etc/localtime ? I am in Arizona, if that tells you anything -rw-r--r-- 2 root root 126 Jul 20 07:17 /etc/localtime

Can you show the output of ls -l /usr/share/zoneinfo ? total 172 drwxr-xr-x 1 root root 4096 Jul 14 17:40 Africa drwxr-xr-x 1 root root 4096 Jul 14 17:40 America drwxr-xr-x 1 root root 4096 Jul 14 17:40 Antarctica drwxr-xr-x 1 root root 4096 Jul 14 17:40 Arctic drwxr-xr-x 1 root root 4096 Jul 14 17:40 Asia drwxr-xr-x 1 root root 4096 Jul 14 17:40 Atlantic drwxr-xr-x 1 root root 4096 Jul 14 17:40 Australia drwxr-xr-x 1 root root 4096 Jul 14 17:40 Brazil drwxr-xr-x 1 root root 4096 Jul 14 17:40 Canada -rw-r--r-- 1 root root 2102 May 4 11:22 CET drwxr-xr-x 1 root root 4096 Jul 14 17:40 Chile -rw-r--r-- 1 root root 2294 May 4 11:22 CST6CDT -rw-r--r-- 1 root root 2437 May 4 11:22 Cuba -rw-r--r-- 1 root root 1876 May 4 11:22 EET -rw-r--r-- 1 root root 1972 May 4 11:22 Egypt -rw-r--r-- 1 root root 3531 May 4 11:22 Eire -rw-r--r-- 1 root root 127 May 4 11:22 EST -rw-r--r-- 1 root root 2294 May 4 11:22 EST5EDT drwxr-xr-x 1 root root 4096 Jul 14 17:40 Etc drwxr-xr-x 1 root root 4096 Jul 14 17:40 Europe -rw-r--r-- 1 root root 129 May 4 11:22 Factory -rw-r--r-- 1 root root 3687 May 4 11:22 GB lrwxrwxrwx 1 root root 2 May 4 11:22 GB-Eire -> GB -rw-r--r-- 1 root root 127 May 4 11:22 GMT lrwxrwxrwx 1 root root 3 May 4 11:22 GMT0 -> GMT lrwxrwxrwx 1 root root 3 May 4 11:22 GMT-0 -> GMT lrwxrwxrwx 1 root root 3 May 4 11:22 GMT+0 -> GMT lrwxrwxrwx 1 root root 3 May 4 11:22 Greenwich -> GMT -rw-r--r-- 1 root root 1189 May 4 11:22 Hongkong -rw-r--r-- 1 root root 128 May 4 11:22 HST -rw-r--r-- 1 root root 1188 May 4 11:22 Iceland drwxr-xr-x 1 root root 4096 Jul 14 17:40 Indian -rw-r--r-- 1 root root 1704 May 4 11:22 Iran -rw-r--r-- 1 root root 4445 Feb 28 2017 iso3166.tab -rw-r--r-- 1 root root 2265 May 4 11:22 Israel -rw-r--r-- 1 root root 507 May 4 11:22 Jamaica -rw-r--r-- 1 root root 318 May 4 11:22 Japan -rw-r--r-- 1 root root 245 May 4 11:22 Kwajalein -rw-r--r-- 1 root root 10666 Jan 15 2018 leap-seconds.list -rw-r--r-- 1 root root 655 May 4 11:22 Libya lrwxrwxrwx 1 root root 14 May 4 11:22 localtime -> /etc/localtime -rw-r--r-- 1 root root 2102 May 4 11:22 MET drwxr-xr-x 1 root root 4096 Jul 14 17:40 Mexico drwxr-xr-x 1 root root 4096 Jul 14 17:34 Msft -rw-r--r-- 1 root root 127 May 4 11:22 MST -rw-r--r-- 1 root root 2294 May 4 11:22 MST7MDT -rw-r--r-- 1 root root 2453 May 4 11:22 Navajo -rw-r--r-- 1 root root 2460 May 4 11:22 NZ -rw-r--r-- 1 root root 2073 May 4 11:22 NZ-CHAT drwxr-xr-x 1 root root 4096 Jul 14 17:40 Pacific -rw-r--r-- 1 root root 2705 May 4 11:22 Poland -rw-r--r-- 1 root root 3469 May 4 11:22 Portugal drwxr-xr-x 1 root root 4096 Jul 14 17:40 posix -rw-r--r-- 1 root root 3545 May 4 11:22 posixrules -rw-r--r-- 1 root root 414 May 4 11:22 PRC -rw-r--r-- 1 root root 2294 May 4 11:22 PST8PDT drwxr-xr-x 1 root root 4096 Jul 14 17:40 right -rw-r--r-- 1 root root 790 May 4 11:22 ROC -rw-r--r-- 1 root root 531 May 4 11:22 ROK -rw-r--r-- 1 root root 410 May 4 11:22 Singapore drwxr-xr-x 1 root root 4096 Jul 14 17:40 SystemV -rw-r--r-- 1 root root 2152 May 4 11:22 Turkey -rw-r--r-- 1 root root 127 May 4 11:22 UCT lrwxrwxrwx 1 root root 3 May 4 11:22 Universal -> UTC drwxr-xr-x 1 root root 4096 Jul 14 17:40 US -rw-r--r-- 1 root root 127 May 4 11:22 UTC -rw-r--r-- 1 root root 1873 May 4 11:22 WET -rw-r--r-- 1 root root 1544 May 4 11:22 W-SU -rw-r--r-- 1 root root 17781 Feb 16 14:59 zone1970.tab -rw-r--r-- 1 root root 19165 Feb 16 10:21 zone.tab lrwxrwxrwx 1 root root 3 May 4 11:22 Zulu -> UTC

98-f355-f1 commented 6 years ago

Personally, my views are that the GraalVM, if and when dialed in, could be a significant tour-de-force for programming and language integration. How exciting it could be to make a program that uses the fastest parts in each language and compile with one device. WOW, mind blown!

eregon commented 6 years ago

while Truffle doesn't recognize it yet as a method.

What does TruffleRuby not recognize yet? The Benchmark.ips method? Yet the require "benchmark-ips" works? benchmark-ips is supported and should work.

Can you post the full output of the error from the terminal, including the command being run?

And this is what leads to my next question as far as gems along the Truffle path. I think that is the sole reason that I can't use the benchmark-ips gem in Truffle... it can't find the global path to my gems.

Right, that's likely because the environment variables GEM_HOME and GEM_PATH are set to values for MRI, which doesn't make sense for TruffleRuby. If you integrated TruffleRuby with RVM, and rvm use truffleruby, then MRI would have the same issue. There is documentation to workaround this issue: https://github.com/oracle/truffleruby/blob/master/doc/user/ruby-managers.md#using-truffleruby-without-a-ruby-manager In short, either unset GEM_HOME GEM_PATH GEM_ROOT in the terminal when using TruffleRuby or export TRUFFLERUBY_RESILIENT_GEM_HOME=true then TruffleRuby will never look in any gem home but its own (which can be problematic in some situations, e.g., when using Bundler).

I would highly recommend instead to integrate (not install) GraalVM TruffleRuby with a Ruby manager (I think you use RVM), as it will make everything easier, and it's as simple as rvm mount path/to/graalvm/jre/languages/ruby -n truffleruby. You can still keep MRI as default (rvm use --default ruby if it wasn't the case already) and just rvm use truffleruby when you want to switch to TruffleRuby in the current terminal.


I am using Windows 10 with the Debian / Linux WSL subsystem

Could you tell me which version of Debian is it so I can try to reproduce in Docker? I think cat /etc/debian_version should show it.

Could you run:

find /usr/share/zoneinfo -type f | xargs md5sum | grep `md5sum /etc/localtime | cut -f 1 -d " "` 

This should output which files are the same as your timezone and have the information in the zoneinfo files. For instance, for me it shows:

5fda284e681f5245c45084ac8ab67442  /usr/share/zoneinfo/posix/Europe/Vienna
5fda284e681f5245c45084ac8ab67442  /usr/share/zoneinfo/Europe/Vienna
98-f355-f1 commented 6 years ago

Could you tell me which version of Debian is it so I can try to reproduce in Docker? I think cat /etc/debian_version should show it. I'm totally new to this WSL thing on windows since, I just installed it a little over a week ago. Microsoft has great documentation on it, but when installing other stuff, where I find the documentation a little sparse sometimes, and spend a lot of time googling for help. Otherwise, I am very happy with the system/combo. Just the fact, that I can now use fork, and POSIX stuff in the Ruby, Python and C languages is awesome... before you sit there frustrated with messages stating, not functional on Windows. It's great to actually see them run now on my desktop. 9.5

Timezone: 069c656a4f078852eb07eaa77d4eabc1 /usr/share/zoneinfo/Msft/localtime

I put export TRUFFLERUBY_RESILIENT_GEM_HOME=true in my .bashrc file, is that the right place to put it? I think that's what I understood to do.

eregon commented 6 years ago

OK, now I understand why we cannot find the timezone, because it's a "pseudo Microsoft localtime timezone" (/usr/share/zoneinfo/Msft/localtime) and it doesn't point to an actual timezone file, so TruffleRuby has no idea how to find out you are in the America/Phoenix timezone.

I wonder if in such a situation the JVM can find it. Could you try, with GraalVM:

ruby --jvm -e 'p [Time.now, Time.now.zone]'

and post the output? We try to mimic how Java finds the current timezone, but maybe we missed something.


I put export TRUFFLERUBY_RESILIENT_GEM_HOME=true in my .bashrc file, is that the right place to put it? I think that's what I understood to do.

That's one way, yes. I recommend integrating with RVM instead though, it's better supported.

eregon commented 6 years ago

I just read this comment from you in an edit:

As a lazy programmer, that's what I'd like to avoid is each time to run a script to switch the RVM all the time. I have disk space for as many gem libraries as I need +1 , just need to configure paths as best as possible, so that when I execute... "ruby version" "filename.rb" that it just works. and not have to go remembering, whether I reset the path on RVM. My thoughts at least.

If RVM has MRI by default (rvm use --default ruby) then ruby filename.rb executes with MRI. If you want to execute with TruffleRuby, just use rvm truffleruby do ruby filename.rb or first rvm use truffleruby and then just ruby filename.rb. Most people use RVM this way and find it convenient. It ensures binaries and gems are not mixed in very complex and hard-to-debug ways, that few people will ever want to debug. Please look at the RVM documentation, I'm confident there is something for your use case. If you want something simpler that just changes PATH, GEM_HOME and GEM_PATH, you might want to look at chruby or rbenv.

98-f355-f1 commented 6 years ago

BTW, I refactored out the Time.now to the monotonic and the error msgs stopped, programs worked great.

Output: [2018-07-21 01:42:53 +0000, "GMT"]

I did your command, but had to put a truby in the front, since I have the bashrc set up to substitute for truffle ruby. If I just did ruby --jvm -e 'p [Time.now, Time.now.zone]', I would get this error: Traceback (most recent call last): ruby: invalid option --jvm (-h will show valid options) (RuntimeError)

I'm going to have to print out this log, so I can remember to go back over it when I have more time.

eregon commented 6 years ago

If I just did ruby --jvm -e 'p [Time.now, Time.now.zone]', I would get this error:

Because you have MRI earlier in PATH, which is not very well supported (e.g., the gem command will always be MRI's and never TruffleRuby so you'd need something like truffleruby -S gem install ....)


[2018-07-21 01:42:53 +0000, "GMT"]

OK, so the JVM cannot find the timezone on WSL either it seems.

This seems a general bug of WSL in my understanding after a bit of googling.

https://github.com/Microsoft/WSL/issues/1392 https://github.com/Microsoft/WSL/issues/856 https://github.com/HowardHinnant/date/issues/102

It seems from those bug reports a workaround could be (I'd guess those need to be run as root or with sudo but I have no experience with WSL):

dpkg-reconfigure tzdata

And if that doesn't work (if /etc/locatime is still not a symlink), there is always the manual workaround of setting up the symlink yourself:

rm /etc/localtime
ln -s /usr/share/zoneinfo/America/Phoenix /etc/localtime

I don't think we can do much in TruffleRuby, the timezone in WSL is broken for any program that tries to find the timezone ID of the system. The only thing is maybe we should not print the warning and fallback to GMT silently in such a case, like the JVM. But the warning is correct: WSL has a hacky/broken timezone.

98-f355-f1 commented 6 years ago

@eregon Holy Schmoly... I went through those issue links and found that running 'sudo dpkg-reconfigure tzdata' corrects the time zone situation.

I am not going to pretend how that works, but it brought up a screen that allowed me to reset my time to Arizona time... so now when I do 'ls -l /etc/localtime'... it is correct and doesn't give me some bogus time that is off.

I guess according to one of the posters comments, that it works nicely with the JVM.

I also used the monotonic and it had removed those warnings before this solution. But I will test out by making a script with Time.now and run with Truffle Ruby and see if it works or not.

I am still research out the GEM path thing and will post some solutions for others to see.

Thanks so far to your help.

98-f355-f1 commented 6 years ago

Ok, Now I realize what I have done here.

MRI Ruby on windows: installed via windows Installer... no issues there

MRI Ruby on Linux/Debian: installed via RVM

TruffleRuby #1: installed via Ruby-Install

TruffleRuby #2: installed via GraalVM/jre/languages path: GU command

JRuby on Linux/Debian: installed via Ruby-Install This is because Ruby Install maintains the current version of JRuby, where RVM had issues with version and required me to install like Ruby 1.9, and some old version LLVM or something. So uninstalled the RVM JRuby and went with Ruby-Install... this is the reason I chose to mount TruffleRuby on Ruby-Install... then afterwards I figured out how to install the Truffle on the GraalVM path, so that is how I ended up with 2 of them.

I set the windows ENV path to the Graal installation, as well as the Linux PATH to path/to/Graal.... So, when I get Truffle version: truffleruby 1.0.0.rc4, like Ruby 2.4.4, GraalVM CE Native[x86-64 Linux]

so RVM doesn't know about Truffle when I ask for the list: I get just Ruby 2.5.1

ANYWAYS, we can consider this issue as settled...

I was able to hardwire in a shorcut in the bashrc file, all I have to do is put at the $ is trubygem and it loads the gem directly to the TruffleRuby gem folder in the GraalVM. I just tested that it worked and IT WORKED... I now have Benchmark-Ips available for Truffle.

I like how I got my system set up now...

The way I have it is like this, at the command line $: ruby => MRI jruby => JRuby truby => TruffleRuby crystal => Crystal goby => Goby

Love it... now I gotta get to work on C extensions, and configure the Python and Pip paths for the GraalVM.

eregon commented 6 years ago

@98-f355-f1 I see what you want to achieve. Sounds mostly good but I would suggest:

Then you can have the setup you show, but in a sane way as every implementation will naturally use its own Gem setup. Note the gem/irb command, etc should not be used but ruby/jruby/truby/etc -S gem/irb should be used instead.

For TruffleRuby, if you already installed it with GraalVM there is no need to have a second copy with ruby-install, I would remove that one, it's just redundant.

eregon commented 6 years ago

I improved the warning message when running on WSL to indicate the workaround sudo dpkg-reconfigure tzdata command: b6751221c242a3fd6b99a77dfdef567cb25c0810 This will be in the next release, 1.0.0-rc5. I'll close this issue as the main timezone issue on WSL now has a (hopefully clear) workaround.