使用 jRuby 在 rails 4 中构建多线程模型

Multithreaded model building in rails 4 with jRuby

我正在尝试 optimize/multi-thread 一次性构建大量模型(300 多个)以加快创建速度 table 以将其保存到我的数据库中Rails 4 个应用程序。

我尝试使用备忘录变量等将尽可能多的对对象等的引用移动到线程之外,但我只是不确定该尝试什么了。

我的代码如下,我试图让多线程的代码尽可能小但是我让运行进入循环依赖错误and/or不是所有的记录被创建。感谢任何帮助。

示例 1:

 def create
    @checklist = Checklist.new(checklist_params)

    respond_to do |format|
      if @checklist.save

        tasks = Task.where(:active => true)
        checklist_date_as_time = Time.parse(@checklist.date.to_s).at_beginning_of_day
        checklist_id = @checklist.id.to_i
        threads = []

        ActiveRecord::Base.transaction do
          tasks.each do |task|
            time = task.start_time
            begin
              threads << Thread.new do
                complete_time = checklist_date_as_time + time.hour.hours + time.min.minutes
                task.responses.build( task_start_time: complete_time, must_complete_by: complete_time + task.time_window, checklist_id: checklist_id, task_id: task.id)
              end
            end while (time += task.frequency.minutes) < task.end_time
            threads.map(&:join)
            task.save
          end
        end

        format.html { redirect_to @checklist, notice: 'Checklist was successfully created.' }
        format.json { render :show, status: :created, location: @checklist }
      else
        format.html { render :new }
        format.json { render json: @checklist.errors, status: :unprocessable_entity }
      end
    end

AR 不是 "thread-safe" ... 这意味着在线程之间共享时单个记录实例的 behaviour/correctness 不是框架 defined/guaranteed。

您问题的最简单答案是在 1 个后台线程中执行整个 tasks = ...; ActiveRecord::Base.transaction do ... 工作(DelayedJob 等框架可能会有所帮助)- 这样 "heavy" 计算就是不是响应周期的一部分。

另请注意,使用多个线程可能会导致您使用多个连接 - 从而实质上耗尽 AR pool。这也意味着(取决于 task.responses.build 期间发生的事情)ActiveRecord::Base.transaction { ... } 的预期意图可能不正确(由于涉及多个连接对象)。