From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: AS4713 221.184.0.0/13 X-Spam-Status: No, score=-2.6 required=3.0 tests=BAYES_00,DKIM_ADSP_CUSTOM_MED, FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM,HEADER_FROM_DIFFERENT_DOMAINS, RCVD_IN_DNSWL_MED,SPF_PASS,T_RP_MATCHES_RCVD shortcircuit=no autolearn=no autolearn_force=no version=3.4.0 Received: from neon.ruby-lang.org (neon.ruby-lang.org [221.186.184.75]) by dcvr.yhbt.net (Postfix) with ESMTP id 310011F404 for ; Sun, 28 Jan 2018 17:50:17 +0000 (UTC) Received: from neon.ruby-lang.org (localhost [IPv6:::1]) by neon.ruby-lang.org (Postfix) with ESMTP id A9C6D1209A4; Mon, 29 Jan 2018 02:50:12 +0900 (JST) Received: from o1678916x28.outbound-mail.sendgrid.net (o1678916x28.outbound-mail.sendgrid.net [167.89.16.28]) by neon.ruby-lang.org (Postfix) with ESMTPS id 886AE1209A1 for ; Mon, 29 Jan 2018 02:50:09 +0900 (JST) Received: by filter0008p3las1.sendgrid.net with SMTP id filter0008p3las1-745-5A6E0D4E-11 2018-01-28 17:50:06.296014135 +0000 UTC Received: from herokuapp.com (ec2-54-234-186-62.compute-1.amazonaws.com [54.234.186.62]) by ismtpd0009p1iad1.sendgrid.net (SG) with ESMTP id IOYWo89FQUG0vPntdKl7PA Sun, 28 Jan 2018 17:50:06.169 +0000 (UTC) Date: Sun, 28 Jan 2018 17:50:06 +0000 (UTC) From: danieldasilvaferreira@gmail.com To: ruby-core@ruby-lang.org Message-ID: References: Mime-Version: 1.0 X-Redmine-MailingListIntegration-Message-Ids: 60447 X-Redmine-Project: ruby-trunk X-Redmine-Issue-Id: 13618 X-Redmine-Issue-Author: normalperson X-Redmine-Issue-Assignee: normalperson X-Redmine-Sender: dsferreira X-Mailer: Redmine X-Redmine-Host: bugs.ruby-lang.org X-Redmine-Site: Ruby Issue Tracking System X-Auto-Response-Suppress: All Auto-Submitted: auto-generated X-SG-EID: ync6xU2WACa70kv/Ymy4QrNMhiuLXJG8OTL2vJD1yS5NKKvEbRDy/XO2iquLL9W6qtzcCcnD174NTx 2l7qusljqXElc6oGjAlVGXLgs4ikfxMFFOMKUVpovF2mPBSSM/QBTlCJmp2Q++KZFH2bue+CjJMLMG tWKGvJvBxS+45FdRzNztbSgEXn+UIDAeyosS47oR5tdd0nnfTAmUEnmAgg== X-ML-Name: ruby-core X-Mail-Count: 85186 Subject: [ruby-core:85186] [Ruby trunk Feature#13618] [PATCH] auto fiber schedule for rb_wait_for_single_fd and rb_waitpid X-BeenThere: ruby-core@ruby-lang.org X-Mailman-Version: 2.1.15 Precedence: list Reply-To: Ruby developers List-Id: Ruby developers List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: ruby-core-bounces@ruby-lang.org Sender: "ruby-core" Issue #13618 has been updated by dsferreira (Daniel Ferreira). ko1 (Koichi Sasada) wrote: > I'm not sure we should limit to use them on Threadlet or not. > > 1. Threads and Threadlets can share same synchronization tools > -> Good: no learning efforts > -> Bad: People can cause sync issues with mis-using or missing syncs > 2. Introduce Threadlets special synchronization tools and introduce special rules communicate with other threads > -> Good: people can only use good tools (such as Queues) > -> Bad: we need to learn new tools and rules I'm all for (2) for the reasons I already mentioned: * Specially the big minus that we have in (1): "People can cause sync issues" * Using only good tools is a big +. * Not causing sync issues is a big ++. * The fact that people will be forced to learn new tools and rules is also a big + for me. * It draws the border between the old async scenario and the new one we are trying to implement. > If we think Threadlet is a special Thread (and the name indicates it), then (1) seems nice for me. I agree `Threadlet` has that implication. Since we prefer to use names already in use in the async world what about call it: **Lane** * Lua is always a source of inspiration to me. * Lanes is a lightweight, native, lazy evaluating multithreading library for Lua. * Lane meaning: a narrow road or division of a road * Lane gem (v0.1.0). 247 downloads. https://rubygems.org/gems/lane. The sense of speed and direction pleases me a lot. Note: [About Threads vs Lanes in Lua](http://lualanes.github.io/lanes/comparison.html) LuaThread provides thread creation...and need therefore to be guarded against multithreading conflicts. Whether this is exactly what you want, or whether a more loosely implemented multithreading (s.a. Lanes) would be better, is up to you. One can argue that a loose implementation is easier for the developer, since no application level lockings need to be considered. ---------------------------------------- Feature #13618: [PATCH] auto fiber schedule for rb_wait_for_single_fd and rb_waitpid https://bugs.ruby-lang.org/issues/13618#change-69931 * Author: normalperson (Eric Wong) * Status: Assigned * Priority: Normal * Assignee: normalperson (Eric Wong) * Target version: ---------------------------------------- ``` auto fiber schedule for rb_wait_for_single_fd and rb_waitpid Implement automatic Fiber yield and resume when running rb_wait_for_single_fd and rb_waitpid. The Ruby API changes for Fiber are named after existing Thread methods. main Ruby API: Fiber#start -> enable auto-scheduling and run Fiber until it automatically yields (due to EAGAIN/EWOULDBLOCK) The following behave like their Thread counterparts: Fiber.start - Fiber.new + Fiber#start (prelude.rb) Fiber#join - run internal scheduler until Fiber is terminated Fiber#value - ditto Fiber#run - like Fiber#start (prelude.rb) Right now, it takes over rb_wait_for_single_fd() and rb_waitpid() function if the running Fiber is auto-enabled (cont.c::rb_fiber_auto_sched_p) Changes to existing functions are minimal. New files (all new structs and relations should be documented): iom.h - internal API for the rest of RubyVM (incomplete?) iom_internal.h - internal header for iom_(select|epoll|kqueue).h iom_epoll.h - epoll-specific pieces iom_kqueue.h - kqueue-specific pieces iom_select.h - select-specific pieces iom_pingable_common.h - common code for iom_(epoll|kqueue).h iom_common.h - common footer for iom_(select|epoll|kqueue).h Changes to existing data structures: rb_thread_t.afrunq - list of fibers to auto-resume rb_vm_t.iom - Ruby I/O Manager (rb_iom_t) :) Besides rb_iom_t, all the new structs are stack-only and relies extensively on ccan/list for branch-less, O(1) insert/delete. As usual, understanding the data structures first should help you understand the code. Right now, I reuse some static functions in thread.c, so thread.c includes iom_(select|epoll|kqueue).h TODO: Hijack other blocking functions (IO.select, ...) I am using "double" for timeout since it is more convenient for arithmetic like parts of thread.c. Most platforms have good FP, I think. Also, all "blocking" functions (rb_iom_wait*) will have timeout support. ./configure gains a new --with-iom=(select|epoll|kqueue) switch libkqueue: libkqueue support is incomplete; corner cases are not handled well: 1) multiple fibers waiting on the same FD 2) waiting for both read and write events on the same FD Bugfixes to libkqueue may be necessary to support all corner cases. Supporting these corner cases for native kqueue was challenging, even. See comments on iom_kqueue.h and iom_epoll.h for nuances. Limitations Test script I used to download a file from my server: ----8<--- require 'net/http' require 'uri' require 'digest/sha1' require 'fiber' url = 'http://80x24.org/git-i-forgot-to-pack/objects/pack/pack-97b25a76c03b489d4cbbd85b12d0e1ad28717e55.idx' uri = URI(url) use_ssl = "https" == uri.scheme fibs = 10.times.map do Fiber.start do cur = Fiber.current.object_id # XXX getaddrinfo() and connect() are blocking # XXX resolv/replace + connect_nonblock Net::HTTP.start(uri.host, uri.port, use_ssl: use_ssl) do |http| req = Net::HTTP::Get.new(uri) http.request(req) do |res| dig = Digest::SHA1.new res.read_body do |buf| dig.update(buf) #warn "#{cur} #{buf.bytesize}\n" end warn "#{cur} #{dig.hexdigest}\n" end end warn "done\n" :done end end warn "joining #{Time.now}\n" fibs[-1].join(4) warn "joined #{Time.now}\n" all = fibs.dup warn "1 joined, wait for the rest\n" until fibs.empty? fibs.each(&:join) fibs.keep_if(&:alive?) warn fibs.inspect end p all.map(&:value) Fiber.new do puts 'HI' end.run.join ``` ---Files-------------------------------- 0001-auto-fiber-schedule-for-rb_wait_for_single_fd-and-rb.patch (82.8 KB) -- https://bugs.ruby-lang.org/