How to compile Ruby?

后端 未结 7 1924
青春惊慌失措
青春惊慌失措 2020-12-13 14:22

Is there a tool that can allow me to compile Ruby code so that it runs somewhat faster?

For example, I have heard that there is a tool for Python called \"pyc\" tha

相关标签:
7条回答
  • 2020-12-13 14:27

    Check the Unholy git repo

    0 讨论(0)
  • 2020-12-13 14:31

    In the beginning of 2013 there is not a way to translate Ruby into C/C++ source and then compile it.

    However, I heard Matz (Yukihiro Matsumoto) say that a researcher is creating this tool in Japan. The project should be founded by the Japanese government.

    Otherwise you could use JRuby and compile it in Java byte-code or you could use Rubinius. Rubinius compiles automatically in byte-code (JIT compiler) for the Rubinius VM. It is possible to convert Rubinius in byte-code into LLVM IR and LLVM can generate machine code.

    0 讨论(0)
  • 2020-12-13 14:33

    Try ruby-packer which creates executables from Ruby and Ruby on Rails applications

    0 讨论(0)
  • 2020-12-13 14:35

    The following "selfcontained" ruby test-case is based on the examples from this very thread, from the comment/answer of the user named illusionist.

    #!/usr/bin/env ruby
    #==========================================================================
    # This file is in public domain.
    # The code of this file is based on the code fragments at the
    # 2018_12_09 version of the:
    #
    #     https://stackoverflow.com/questions/5902334/how-to-compile-ruby
    #
    # This file has been tested with the ruby version
    #
    #     ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-linux]
    #
    #-----start--of--the--boilerplate------------------------------------------
    
    s_fp_home=ENV["HOME"].to_s
    s_fp_tmp=s_fp_home+"/tmp" # using /tmp can be a security risk
    s_fp_demofolder=s_fp_tmp+"/ruby_bytecode_usage_demo_01"
    
    def create_folder_if_needed(s_fp_in)
       if !Dir.exists? s_fp_in
          Dir.mkdir(s_fp_in)
          if !Dir.exists? s_fp_in
             raise(Exception.new("\n\n Folder creation failed.\n"+
             "GUID=='d6e409cb-e072-4441-9421-22630190c2e7'\n"))
          end # if
       end # if
    end # create_folder_if_needed
    create_folder_if_needed(s_fp_tmp)
    create_folder_if_needed(s_fp_demofolder)
    
    s_rand=""
    7.times{s_rand<<("_"+rand(100).to_s)}
    
    s_fp_bytecode=s_fp_demofolder+"/awesome_bytecode"+s_rand
    s_fp_src=s_fp_demofolder+"/x"+s_rand+".rb"
    
    if File.exists? s_fp_src
       raise(Exception.new("\n\n This file should not exist yet.\n"+
       " s_fp_src=="+s_fp_src+"\n"+
       "GUID=='43ab3d45-1324-47af-9441-22630190c2e7'\n"))
    end # if
    IO.write(s_fp_src,"puts('');puts('Greetings from bytecode!');puts('')")
    if !File.exists? s_fp_src
       raise(Exception.new("\n\n The file \n"+s_fp_src+"\n is missing.\n"+
       "GUID=='4aeb5e54-efe0-4111-a851-22630190c2e7'\n"))
    end # if
    
    
    #-----start--of--the--core--of--the--demo----------------------------------
    
    bytecode_out = RubyVM::InstructionSequence.compile_file(s_fp_src)
    IO.binwrite(s_fp_bytecode, bytecode_out.to_binary)
    
    bytecode_in = IO.binread(s_fp_bytecode)
    instruction_from_byte_code = RubyVM::InstructionSequence.load_from_binary(bytecode_in)
    instruction_from_byte_code.eval
    
    #==========================================================================
    
    0 讨论(0)
  • 2020-12-13 14:43

    The simple answer is that you can't, at least with MRI 1.8 (the standard). This is because 1.8 works by walking the Abstract Syntax Tree. Python, Ruby 1.9, JRuby, and Rubinius use byte code, which allows compilation to an Intermediate Representation (byte code). From MRI Ruby 2.3 it has become easy to do this, see this answer below.

    With Rubinius, you can do something as described in this post: http://rubini.us/2011/03/17/running-ruby-with-no-ruby/

    In JRuby you can use the "Ahead Of Time" compiler through, I believe, jrubyc.

    This isn't really the standard way of doing things and you're generally better off just letting your Ruby implementation handle it like it wants to. Rubinius, at least, will cache byte code after the first compilation, updating it as it needs to.

    0 讨论(0)
  • 2020-12-13 14:44

    From ruby 2.3.0 its so easy to compile your source code to bytecodes that the Ruby-VM understands.

    byte_code = RubyVM::InstructionSequence.compile_file '/home/john/somefile.rb'
    
    File.binwrite '/home/john/bytecode', byte_code.to_binary
    

    and in Command Line

    $ cat bytecode 
    
    YARB�
    IUsx86_64-linux*.*1
    
    +1�!AA*1
    !qy��������yyQ� E/home/john/somefile.rbE<main>E <class:A>EshivaEhelloEAEputsEcore#define_methodu����� 5M
    

    The content of the file

    class A
      def shiva
        puts 'hello'
      end
    end
    

    What is the purpose?

    Well, ruby takes time to compile your source code into byte codes so you can load your bytecodes directly into ruby and execute. No overhead of grammar checking and compilation. It much faster than normal processes.

    How to load byte code?

    bytecode = File.binread('/home/john/bytecode')
    instruction_from_byte_code = RubyVM::InstructionSequence.load_from_binary bytecode
    
    instruction_from_byte_code.eval
    # => :shiva
    

    Note: This answer is tested in MRI only. It might or might not work in other Ruby Implementations

    0 讨论(0)
提交回复
热议问题