1 คะแนน โดย GN⁺ 2023-12-26 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • YJIT ปรับปรุงประสิทธิภาพและการใช้หน่วยความจำอย่างมากเมื่อเทียบกับ Ruby 3.2 และเร็วกว่าอินเทอร์พรีเตอร์มากกว่า 3 เท่าใน Optcarrot
  • Code GC ของ YJIT ถูกปิดใช้งานเป็นค่าเริ่มต้น และ --yjit-exec-mem-size ทำงานเป็น hard limit ที่หยุดการคอมไพล์โค้ดใหม่
  • เพิ่ม RubyVM::YJIT.enable ทำให้สามารถเปิดใช้งาน YJIT ขณะรันไทม์ได้โดยไม่ต้องเปลี่ยนอาร์กิวเมนต์บรรทัดคำสั่งหรือตัวแปรสภาพแวดล้อม
  • เพิ่มพาร์เซอร์ Prism เป็น gem พื้นฐาน และสามารถใช้ API Prism.parse(source), Prism.parse_comments(source), Prism.parse_success?(source) ได้
  • สามารถทดลองคอมไพเลอร์ Prism ได้ด้วย ruby --parser=prism หรือ RUBYOPT="--parser=prism" แต่แฟล็กดังกล่าวมีไว้สำหรับดีบักเท่านั้น
  • ตัวสร้างพาร์เซอร์ถูกเปลี่ยนจาก Bison เป็น Lrama และพาร์เซอร์ภายในของ Lrama ถูกเปลี่ยนเป็น LR parser ที่สร้างโดย Racc เพื่อให้บำรุงรักษาได้ง่ายขึ้น
  • คอมไพเลอร์ JIT แบบ pure-Ruby RJIT มาแทนที่ MJIT แต่รองรับเฉพาะสถาปัตยกรรม x86-64 บน Unix และจำกัดไว้เพื่อการทดลองเท่านั้น
  • มีการนำ M:N thread scheduler มาใช้ โดยให้ N เธรดเนทีฟจัดการ M เธรดของ Ruby แต่อาจทำให้ความเข้ากันได้กับส่วนขยาย C เสียหาย จึงปิดใช้งานเป็นค่าเริ่มต้นใน main Ractor
  • วิธีการที่ it ถูกเรียกโดยไม่มีอาร์กิวเมนต์และถูกใช้ในบล็อกที่ไม่มีพารามิเตอร์ปกติจะถูกเลิกสนับสนุน (deprecation) และใน Ruby 3.4 จะกลายเป็นการอ้างอิงพารามิเตอร์ตัวแรกของบล็อก
  • Regexp::new อนุญาตอาร์กิวเมนต์ได้สูงสุด 2 ตัวเท่านั้น แทนการเรียกแบบ 3 อาร์กิวเมนต์ที่ถูกเลิกสนับสนุนใน Ruby 3.2
  • ext/readline ถูกปลดระวาง และต่อไปจะพึ่งพา reline ซึ่งเป็นการใช้งานแบบ pure Ruby ที่เข้ากันได้กับ API ของ ext/readline
  • หากต้องใช้ ext/readline สามารถติดตั้งจาก rubygems.org ด้วย gem install readline-ext ได้ และไม่จำเป็นต้องติดตั้งไลบรารีอย่าง libreadline หรือ libedit อีกต่อไป
  • RubyGems และ Bundler จะแจ้งเตือนเมื่อมีการ require gem บางรายการโดยไม่ได้เพิ่ม gem เหล่านั้นไว้ใน Gemfile หรือ gemspec และ gem เหล่านี้จะกลายเป็น bundled gem ใน Ruby เวอร์ชันอนาคต
  • เมื่อใช้ gem bootsnap คำเตือนดังกล่าวจะถูกระงับ และเนื่องจากข้อจำกัดของเวอร์ชันนี้ แนะนำให้รันแอปพลิเคชันอย่างน้อยหนึ่งครั้งพร้อมตัวแปรสภาพแวดล้อม DISABLE_BOOTSNAP=1
  • เพิ่ม prism 0.19.0 เป็น gem พื้นฐาน และ racc 1.7.3 ถูกยกระดับจาก default gem เป็น bundled gem

1 ความคิดเห็น

 
GN⁺ 2023-12-26
ความคิดเห็นจาก Hacker News
  • มองว่าใน Ruby 3.3 นั้น Ruby กลับมาอย่างยิ่งใหญ่แล้ว ภาษาที่เคยโฟกัสความสุขของนักพัฒนาแต่ถูกล้อว่าเชื่องช้า ตอนนี้ไม่ช้าอีกต่อไปแล้ว
    YJIT เป็นเทคโนโลยีที่น่าทึ่ง และเมื่อรวมกับ object shape รวมถึงการปรับแต่ง garbage collection หลายอย่าง Ruby ก็กำลังเร็วขึ้นพอสมควร ผู้ใช้ Ruby รายใหญ่อย่าง Shopify ก็เปิดใช้ YJIT บนเวอร์ชัน pre-release ของ 3.3 ใน production และรายงานว่าประสิทธิภาพดีขึ้นเป็นเปอร์เซ็นต์สองหลัก
    ส่วนตัวแล้วตื่นเต้นมากกับ Ruby และอนาคตของมัน และอยากลองทำงานด้วย Ruby 3.3 แล้วนำไปใช้กับไซต์ production ของลูกค้า
    https://railsatscale.com/2023-09-18-ruby-3-3-s-yjit-runs-sho...

    • ประสิทธิภาพที่ดีขึ้นเล็กน้อยอาจไม่ถึงขั้นทำให้คนเลือก Ruby ใหม่ แต่การปรับปรุงแบบค่อยเป็นค่อยไปก็เป็นเรื่องน่ายินดี การกังวลเรื่องประสิทธิภาพมากเกินไปแทบจะเป็น การ optimize ก่อนเวลาอันควร เสมอ และ Ruby ก็เร็วพอสำหรับงานที่ต้องการมาจนถึงตอนนี้
      เคยใช้เป็นโค้ดกาวระหว่างที่เก็บ DNS record บน Redis กับ PowerDNS ด้วย โดยทั้งสแต็กประมวลผลคิวรี 500 ล้านครั้งต่อเดือนบน VPS เล็ก ๆ 14 เครื่อง และแทบไม่เห็นร่องรอยใน htop เลย ที่ใช้ PowerDNS ไม่ใช่เพราะเรื่องประสิทธิภาพ แต่เพราะโดยทั่วไปไม่ใช่ความคิดที่ดีที่จะ implement สิ่งอย่างการเข้ารหัส, HTTP, DNS ที่เปิดออกสู่อินเทอร์เน็ตสาธารณะด้วยตัวเอง
      ความย้อนแย้งของเว็บยุคนี้คือ เว็บแอปที่สร้างด้วย Ruby ที่ “ช้า” และ server rendering กลับโหลดหน้าได้เร็วกว่า database แบบ eventual consistency ที่ช้าจริง ๆ กับ frontend web app ที่อ้วนเทอะทะ ในเว็บสมัยใหม่ เราเห็น loading spinner บ่อยเกินไปแม้แต่ตอนทำเรื่องเล็กน้อย
    • ตัวภาษา Ruby เองอาจเร็วได้ แต่ ecosystem โดยรวมช้าจนเจ็บปวด ถ้าสร้างเซิร์ฟเวอร์ด้วย Rails ที่คืน JSON 1MB ต่อ request ผ่านการ query database และเรียก service อื่น ๆ จะได้ประมาณ 100 requests ต่อวินาที แต่พอเขียน service เดียวกันใหม่ด้วย Go ก็รับได้ 100,000 requests ต่อวินาที
    • สงสัยว่า “ประสิทธิภาพดีขึ้นเป็นเปอร์เซ็นต์สองหลัก” หมายถึงเร็วขึ้น 10% หรือเร็วขึ้น 10 เท่า
      กดลิงก์ไปดูแล้วพบว่าเป็น การดีขึ้นระดับสิบกว่าเปอร์เซ็นต์ คิดว่าคงเปลี่ยนภาพจำที่ว่า Ruby ช้ากว่าภาษา “เร็ว” อย่าง Rust, Java, Go, C++ ประมาณ 50–200 เท่าได้ไม่มากนัก
    • อีกด้านหนึ่งที่ Ruby สามารถปรับปรุง developer experience ได้คือ ประสบการณ์การดีบัก ที่ดีกว่านี้ อาจเพราะคุ้นกับ Chrome DevTools มากเกินไป แต่ครั้งสุดท้ายที่ดีบักโค้ด Ruby ที่ใช้ metaprogramming หนัก ๆ การทำความเข้าใจว่าเกิดอะไรขึ้นเป็นเรื่องทรมานมาก
    • ได้ยินคำว่า “สองหลัก” แล้วคาดหวังไว้ 50% หรือ 80% แต่พอดูลิงก์แล้วเป็น 13–15%
  • Ruby 3.3 ดูเหมือนจะเป็นหนึ่งในรีลีส Ruby ที่สำคัญและมีฟีเจอร์มากที่สุดในรอบ 10 ปีที่ผ่านมา ไม่คิดว่าจะมี JIT ที่พร้อมใช้งานใน production ออกมาก่อน Python และยังมี Prism, Lrama, IRB ด้วย
    แต่สิ่งที่ยังถูกพูดถึงไม่พอคือ Ractor, M:N thread scheduler, Fiber, Async โดยเฉพาะในบริบทของ Rails อยากฟังความคิดเห็นว่ามีใครใช้ฟีเจอร์เหล่านี้ใน production หรือไม่

    • การที่ Ruby มี JIT ที่พร้อมใช้งานใน production ก่อน Python นั้นคาดเดาได้พอสมควร เพราะ Ruby ไม่มี ชุมชน scientific computing ขนาดใหญ่ที่พึ่งพารายละเอียดการ implement ของ host interpreter ทุกจุด
    • สงสัยว่า Ruby 3.3 เป็นรีลีสที่สำคัญขนาดนั้นหรือเปล่า ไม่แน่ใจว่าอะไรทำให้มันมีความหมายมากขนาดนั้น
      ถึงอย่างนั้น Ractor ก็ควรได้รับความสนใจมากกว่านี้ เป็นฟีเจอร์ใหญ่มาก
    • ไม่เข้าใจจริง ๆ ว่าทำไมถึงไม่มี คิวงาน เดียวที่ครอบคลุมทั้ง Ruby และ Python รู้ว่าตั้งแต่จุดหนึ่งผู้คนเริ่มส่งข้อมูลกันผ่าน microservice บน HTTP แต่สุดท้ายแล้วคิวงานแบบเรียบง่ายที่มีรูปแบบการจัดเก็บร่วมกันระหว่างสองภาษา น่าจะเป็นวิธีที่ดีกว่าในการเชื่อมระบบที่ใช้ Ruby/Rails กับสแต็ก machine learning
      เดาว่าภายในบริษัทต่าง ๆ คงมีโซลูชัน custom ส่วนตัวบน RabbitMQ หรือ Redis อยู่เป็นพัน ๆ แบบ
  • ทุกปีในวันคริสต์มาสเหมือนตั้งนาฬิกาไว้ Ruby Lang จะออกรุ่นใหม่เสมอ

  • ใช้งานบน Heroku ได้แล้ว: https://devcenter.heroku.com/changelog-items/2772

  • ดูดีนะ IRB ตัวใหม่คือ interactive Ruby interpreter ที่มี autocomplete และการดีบักดีขึ้น การเปลี่ยนแปลงส่วนใหญ่ใน Ruby 3.3 น่าจะนำไปสู่การปรับปรุงเครื่องมือสำหรับนักพัฒนา
    API ของภาษายังคงสอดคล้องกับรีลีสก่อนหน้าโดยรวม ผมเขียนคู่มืออัปเดต Ruby 3.3 พร้อมโน้ตสำหรับ version manager หลายตัวไว้แล้ว: https://mac.install.guide/ruby/update.html
    สงสัยอยู่ว่าควรแนะนำ version manager ตัวไหนดี ก่อนหน้านี้เคยแนะนำ asdf, frum, chruby

    • ไม่รู้สึกว่ามีปัญหาอะไรกับ rbenv หรือ asdf ใช้ทั้งในเครื่อง local และ production อยู่
  • ตอนนี้สามารถยกเลิก name resolution อย่าง Socket.getaddrinfo ได้แล้ว และว่ากันว่าจะสร้าง worker pthread ทุกครั้งที่ต้อง resolve ชื่อ แล้วรัน getaddrinfo(3) ในนั้น
    สงสัยว่า runtime ของภาษาอื่นก็ทำคล้ายกันไหม การสร้าง thread ดูหนักเกินไป แต่ในทางปฏิบัติอาจไม่ใช่ปัญหาใหญ่ก็ได้ แม้ตาม benchmark ของตัวเอง overhead จะน้อยแต่ก็ไม่ใช่ศูนย์
    10000.times { Addrinfo.getaddrinfo("www.ruby-lang.org";, 80) } ใช้เวลา 2.3 วินาทีก่อนแพตช์ และ 3.0 วินาทีหลังแพตช์ ส่วน 100.times { URI.open("https://www.ruby-lang.org";).read } ใช้เวลา 3.36 วินาทีก่อนแพตช์ และ 3.40 วินาทีหลังแพตช์

    • สงสัยว่าเป็นเพราะ operation I/O ทั้งหมดใน standard library ต้องรองรับ async/fiber หรือเปล่า
      ไม่ได้ reimplement operation เดิมด้วย “สี” แบบ async เหมือน Python แต่รู้สึกเหมือนทุกอย่างถูกย้ายไปเป็น asynchronous โดยค่าเริ่มต้น ไม่แน่ใจว่าเข้าใจถูกไหม
    • คิดว่า fiber น่าจะเบากว่าการสร้าง thread ใหม่หรือเปล่า
  • หากรู้ Python กับ NodeJS อยู่แล้ว ก็สงสัยว่า Ruby ยังควรค่าแก่การเรียน หรือไม่ Ruby ดูน่าสนใจแต่ก็รู้สึกว่ายาก

    • โดยพื้นฐานแล้ว Ruby คล้ายกับ Python ที่ได้รับความนิยมน้อยกว่าแต่สง่างามกว่า เป็นภาษาทั่วไปที่แข็งแรง และเหมาะเป็นพิเศษกับงานอย่างเชลล์สคริปต์หรือการจัดระเบียบข้อมูล
      ถ้าเชี่ยวชาญ Node และ Python อยู่แล้ว ก็น่าจะเรียนได้ค่อนข้างง่าย ข้อเสียคือถ้ารู้ภาษาเหล่านั้นอยู่แล้ว มันไม่ได้ให้อะไรใหม่ในเชิงพื้นฐานนัก ข้อดีส่วนใหญ่เป็นเรื่องสุนทรียะ Ruby มีและสนับสนุนวิธีแสดงโค้ดให้สวยงามจริง ๆ และการได้สัมผัสสิ่งนั้นก็สนุก
    • มองว่า Ruby ดีกว่า Python หรือ Node มากสำหรับ งานแนวเชลล์สคริปต์ และการเขียนโปรแกรมแบบโต้ตอบ·สำรวจสำหรับงานระบบ ถ้าใช้เป็น “bash ที่ดีกว่า” หรือ “Perl ที่ดีกว่า” ก็ถือว่าคุ้มค่าแล้ว
      แม้จะทำงานกับโค้ดเบส TypeScript เป็นหลัก แต่เวลาจัดการข้อมูลล็อกหรือข้อความกึ่งมีโครงสร้าง หรือทำการเขียนใหม่ตาม regex ในหลายไฟล์ ก็มักหยิบ Ruby มาใช้ Ruby สนุกมาก และในบรรดาภาษาที่เคยใช้เป็นประจำ น่าจะเป็นภาษาที่สนุกที่สุด จึงเป็นรางวัลในตัวเอง
    • ขึ้นอยู่กับว่าต้องการได้อะไร ส่วนที่น่าสนใจที่สุดคือ Ruby ในหลายแง่คล้าย Python มาก แต่ขณะเดียวกันก็ต่างกันพอสมควร
      ตัวอย่างใหญ่ที่สุดคือ Ruby ชอบ บล็อก มาก มีอยู่ทั่วทั้งไลบรารีมาตรฐาน มี syntax sugar มากมาย และมี DSL ที่สร้างรอบบล็อกนับไม่ถ้วน ฟีเจอร์เชิงฟังก์ชันมาตรฐานก็อยู่ในไลบรารีมาตรฐานมานานแล้ว ทำให้เขียนสไตล์ฟังก์ชันได้ลื่นไหลและอ่านง่าย
      ใน Python ส่วนใหญ่ทำได้ในทางเทคนิค แต่ดูเขียนและอ่านเก้งก้างกว่ามาก Python มี lambda แต่ให้ความรู้สึกว่าไม่ค่อยชอบให้ใช้เกินงานเล็ก ๆ น้อย ๆ และแทนที่จะเป็นเช่นนั้น ฟังก์ชันถูกใช้เป็นค่า first-class ได้ทุกที่
    • ถ้าต้องการคำแนะนำเพื่อปรับปรุงโค้ดระหว่างเรียน แนะนำให้ใช้ Rubocop เป็นทั้งลินเตอร์และครูที่ยอดเยี่ยม
    • เคยใช้ Ruby เล็กน้อย หรือให้ถูกคือ Ruby ใน Rails ช่วงปี 2011–2013 ซึ่งกว่าสิบปีก่อน ตอนนั้นยังเป็นช่วงที่กระแสตกค้างของ RoR ซึ่งเปิดตัวในปี 2005 และฮิตมากในปี 2007–2009 ยังมีอยู่
      คนที่ไวต่อเทคโนโลยีใหม่ ๆ กำลังย้ายไปสู่การพัฒนาแบบเน้น API บน node.js และ AngularJS ซึ่งเร็วกว่าอย่างมากเมื่อเทียบกับสิ่งที่สร้างด้วย RoR ในปี 2013 วิธีมาตรฐานของ RoR ยังเป็นแบบโมโนลิทิก และดูแก่ลงเพราะปรับตัวเข้ากับพาราไดม์ใหม่ของการแยกฟรอนต์เอนด์/แบ็กเอนด์ได้ไม่ดี
      เหตุผลที่พูดถึงเฟรมเวิร์กที่สร้างด้วย Ruby ยาว ๆ แทนที่จะพูดถึง Ruby เอง คือแม้ตอนนี้ก็คาดว่า 95% ของการพัฒนา Ruby น่าจะเป็นแอปพลิเคชัน Rails Ruby มีชื่อเสียงขึ้นมาส่วนใหญ่เพราะ Ruby on Rails และถ้า RoR อยู่ในขาลง Ruby ก็น่าจะเดินตามเส้นทางเดียวกันจนเหลือเป็นชุมชนเล็ก ๆ ที่มีแฟนเหนียวแน่น คล้าย Perl
      ถ้ามองเฉพาะตัวภาษาเอง นึกเหตุผลไม่ออกว่าจะเลือก Ruby แทน Python หรือ TypeScript ทำไม ดูเหมือน Ruby ไม่ได้ทำอะไรได้ดีกว่าคู่แข่งที่ตั้งหลักได้มั่นคงกว่าแล้ว ไม่ว่าจะในแง่ภาษา หรือแพลตฟอร์ม
  • Prism น่าสนใจ สงสัยว่ามีเครื่องมือวิเคราะห์โค้ด Ruby ที่ใช้สิ่งนี้หรือไม่ กำลังมองหาวิธีวิเคราะห์โค้ดของบริษัทอยู่

    • Ruby LSP ใช้ Prism อยู่ Kevin Newton ได้ทำ แบ็กเอนด์ที่อิง Prism สำหรับ gem whitequark/parser ซึ่งใช้ร่วมกับ Rubocop ได้: https://github.com/kddnewton/parser-prism
  • ว่ากันว่าตัวแปรสภาพแวดล้อม RUBY_MAX_CPU=n ตั้งค่าสูงสุดเป็น N ตัว หรือก็คือจำนวนเนทีฟเธรดสูงสุด และค่าเริ่มต้นคือ 8
    รู้สึกว่าค่าเริ่มต้นควรเป็น จำนวน logical core เหมือน Rust Tokio หรือ runtime แบบ M:N อีกมากมายไม่ใช่หรือ

    • เป็นการปรับแต่งที่เพิ่มได้ภายหลัง และมีรายละเอียดปลีกย่อยอยู่บ้าง เท่าที่จำได้ Go ก็เคยคล้ายกันอยู่หลายปี และยังจำได้ว่าตั้งค่า GO_MAX_PROCS ใน init() หรือ main()
    • การกำหนด hard cap ให้จำนวน CPU สูงสุดดูไม่ถูก คิดว่าน่าจะอิงตามจำนวนคอร์ที่ใช้งานได้ก็พอ
  • ใน Ruby 4.0 อยากให้อนุญาต explicit import แทนวิธีปัจจุบันที่นำ gem เข้ามาใน namespace แบบ global และ implicit

    • อาจสนใจ Im ของ Chris Salzberg ซึ่งใช้ได้แล้วใน Ruby 3.2: https://github.com/shioyama/im
      ยังมีการถกเถียงเรื่องฟีเจอร์ “namespace on read” ที่อยู่ในขั้นคาดการณ์ด้วย: https://bugs.ruby-lang.org/issues/19744
    • มองว่า global namespace ไม่ว่าจะ implicit หรือ explicit ก็โอเค ในทางทฤษฎีอาจดูขัด ๆ แต่ในทางปฏิบัติมักไม่ค่อยเป็นปัญหา เพราะมีขนบและบรรทัดฐานทางสังคมช่วยอยู่
      การที่ global namespace รองรับได้แค่เวอร์ชันเดียวของแต่ละ gem พอดี ยังช่วยส่งเสริมวัฒนธรรมที่ดี ซึ่งให้ความสำคัญกับ ABI ที่เสถียรและช่วงเวลาผ่อนผันก่อนเลิกใช้ เมื่อเทียบกับระบบนิเวศของบางภาษาแล้ว นี่เหมือนฝันเลย
    • คิดว่านี่น่าจะเป็นเรื่องของ Rails ไม่ใช่ Ruby หรือเปล่า รู้อยู่ว่าในโปรเจกต์ส่วนใหญ่ ความแตกต่างนี้แทบไม่มีความหมาย แต่ก็อาจเป็นการตัดสินใจของทีม Rails และไม่เกี่ยวกับสิ่งที่ทีม Ruby ทำ
      หรือไม่ก็อาจกำลังพูดผิดไปทั้งหมดก็ได้
    • Ruby 4.0 น่าจะยังไม่เห็นก่อนปี 2030
      https://youtu.be/4MM5b2F9zrM?si=UT3aUbD6p_uBZehS&t=2347