2 คะแนน โดย GN⁺ 2023-11-27 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • การพอร์ต fish-shell ไปยัง Rust เสร็จไปแล้ว “เกือบทั้งหมด” โดยเมื่อวัดตามวิธีคำนวณจะนับความคืบหน้าได้ตั้งแต่ 60% ตามการลบ C++ SLOC ไปจนถึง 74% ตามสัดส่วน Rust SLOC ต่อ C++ SLOC
  • งานใหญ่ที่ยังเหลือคือการย้าย reader และระบบอินพุต โดย reader 3.5k บรรทัด, screen handling 1.3k บรรทัด, input 1k บรรทัด และ pager 700 บรรทัด มีการผูกกันแน่นมาก
  • โค้ด C++ ทั้งหมดจะถูกลบออก และจะไม่มี partial Rust release ระหว่างทาง โดยรีลีสอย่าง fish 4.0 ตั้งเป้าให้มีเฉพาะ Rust และ C++ เป็นศูนย์
  • ไม่เคยมีแผนทำพอร์ตสำหรับ Windows และการย้ายไป Rust ก็ไม่ใช่คำตอบของปัญหาการรองรับ Windows ขณะที่ผู้ใช้สภาพแวดล้อม MSYS2/cygwin กังวลว่าการไม่มี target ดังกล่าวใน Rust อาจทำให้การอัปเดตถูกขัดขวาง
  • ประสิทธิภาพของพอร์ตที่เสร็จสมบูรณ์ยังไม่ชัดเจน และแม้ผลช่วงแรกจะน่าพอใจ แต่ในบางกรณีก็อาจ ช้าลงราว 20% จึงมองว่า Rust รีลีสแรกควรมีเวอร์ชันเบต้า

สถานะความคืบหน้าของพอร์ต Rust

  • การเขียน fish-shell ใหม่ด้วย Rust เสร็จไปแล้ว “เกือบทั้งหมด”
  • ความคืบหน้าจะแตกต่างกันตามเกณฑ์ที่ใช้วัด
    • ตาม การลบ C++ SLOC อยู่ที่ 60%
    • ตาม Rust SLOC เทียบกับ C++ SLOC อยู่ที่ 74%
  • โค้ดบางส่วนเป็น scaffolding ที่ซ้ำซ้อนและจะลบได้เมื่อไม่มีตัวเรียกใช้งานตัวสุดท้ายแล้ว
    • ตัวอย่างเช่น wgetopt ถูกแปลเป็น Rust ไปแล้ว แต่จะยังคงเวอร์ชัน C++ ไว้จนกว่าตัวเรียกใช้งาน C++ ตัวสุดท้ายจะถูกย้าย
    • วิธีนี้ง่ายกว่าการใส่โค้ดแปลงให้กับตัวเรียกใช้งาน C++ ทุกตัว
  • หลังจากตัวเรียกใช้งานตัวสุดท้ายหายไป โค้ดซ้ำซ้อนที่ถูกลบออกจะทำให้มีส่วนที่ถูกเก็บกวาดต่อเนื่องกันเหมือนโดมิโน

งานใหญ่ที่ยังเหลือ

  • องค์ประกอบหลักที่ยังเหลือมากที่สุดคือ reader และระบบอินพุต
  • โค้ดที่เกี่ยวข้องผูกกันแน่นมาก
    • reader: 3.5k บรรทัด
    • screen handling: 1.3k บรรทัด
    • input: 1k บรรทัด
    • pager: 700 บรรทัด
  • หลังจากนั้นยังเหลือโค้ดบางส่วนและการ เลิกพึ่งพา C++ ในระบบ build
    • เอา cmake ออก
    • เปลี่ยนให้ cargo จัดการทุกอย่างที่จำเป็น
    • แม้แต่การ build และติดตั้งเอกสารกับไฟล์ completion ก็ต้องให้ cargo รับผิดชอบ
  • การ build ของ fish ไม่ได้มีแค่การคอมไพล์โค้ด Rust แต่รวมถึงผลลัพธ์เสริมหลายอย่าง จึงไม่ใช่การเปลี่ยนผ่านแบบง่าย ๆ
  • งานนี้ไม่ใช่งานประเภทที่เหมาะกับ “drive-by contribution”

แผนการรีลีสและลำดับเวอร์ชัน

  • fish-shell ไม่มีแผนจะออกรุ่นแบบ partial Rust release
  • ตัวอย่างเช่น fish 4.0 จะประกอบด้วย Rust ทั้งหมดและมี C++ เป็นศูนย์
  • โดยทั่วไปโครงการเลิกทำเบต้าและ release candidate ไปแล้ว แต่การเปลี่ยนผ่านครั้งนี้ถูกมองว่าใหญ่พอที่จะควรมีเบต้า
    • ก่อนหน้านี้เบต้าและ release candidate ถูกยกเลิกเพราะไม่ได้รับการทดสอบมากพอ
  • ยังต้องการมี รีลีสคั่นกลาง 3.7.0 ที่ยังอิง C++ ก่อนจะไปยังเวอร์ชัน Rust
    • เพื่อใช้เป็นจุดตั้งต้นที่ดีกว่าสำหรับแพลตฟอร์มที่รองรับเวอร์ชัน Rust ไม่ได้
    • 3.7.0 คือ 3.6.1 ที่มีการ backport การเปลี่ยนแปลงบางส่วนเข้ามา
  • งานของ 3.7.0 ดำเนินอยู่บน Integration_3.7.0 branch
    • มี CHANGELOG ฉบับเบื้องต้นด้วย
    • การเปลี่ยนแปลงสำคัญมีทั้ง timeout ของคีย์คอมบิเนชัน, การปรับปรุง history-pager, การแก้ rendering glitch และ glob ที่เร็วขึ้น

ไฟล์ที่ยังเหลือและขอบเขตที่ชัดเจน

  • รายการไฟล์ที่ยังเหลือ ณ วันที่ 1 ธันวาคม 2023 มีดังนี้
src/fish_indent_common.cpp
src/fish_indent.cpp
src/fish_key_reader.cpp
src/builtins/bind.cpp
src/builtins/commandline.cpp
src/fish_tests.cpp
src/pager.cpp
src/reader.cpp
  • รายการนี้แสดงขอบเขตการย้าย C++ ที่ยังเหลือในระดับไฟล์

แก้ความเข้าใจผิดและข้อจำกัด

  • โค้ด C++ ทั้งหมดจะถูกลบออก
  • ไม่มีแผนทำพอร์ตสำหรับ Windows และในอดีตก็ไม่เคยมี
    • C++ เองก็รองรับ Windows ได้ดีอยู่แล้ว ดังนั้น Rust ไม่ได้แก้ปัญหาพอร์ต Windows โดยตัวมันเอง
    • ปัญหาของพอร์ต Windows ไม่ใช่เรื่องภาษา แต่เป็นเพราะ Windows ไม่ใช่ Unix
  • จะไม่เปลี่ยนชื่อหรือมาสคอต
  • มีแนวโน้มสูงว่าจะไม่เพิ่ม “written in Rust” ลงใน tagline
    • แต่อาจพูดถึงว่าเขียนด้วย Rust บน fishshell.com
    • ในการพูดคุยเพิ่มเติมเมื่อเดือนกันยายน 2024 ก็ยืนยันจุดยืนอีกครั้งว่าจะไม่ใส่ “written in rust” ใน tagline
  • ประสิทธิภาพของพอร์ตที่เสร็จสมบูรณ์ยังไม่อาจสรุปได้
    • ผลลัพธ์ช่วงแรกดูน่าพอใจ
    • แต่ในบางกรณีก็อาจ ช้าลงราว 20%
    • แม้พอร์ตช่วงแรกจะเสร็จแล้ว ก็ไม่ได้หมายความว่าโครงการจะจบ เพราะยังมีงานอีกมาก

ความกังวลของผู้ใช้ Windows และ MSYS2/cygwin

  • ผู้ใช้รายหนึ่งอธิบายว่าตนใช้ fish ในสภาพแวดล้อม MSYS2 และ MSYS2 มี POSIX utility ที่ทำให้ fish ทำงานได้ดี
  • เนื่องจาก Rust ไม่มี target สำหรับ cygwin หรือ MSYS2 ผู้ใช้จึงกังวลว่าหลังการเขียนใหม่ด้วย Rust แล้ว จะไม่สามารถคอมไพล์ fish สำหรับ target cygwin หรือ MSYS2 ได้
  • ผู้ใช้รายนี้มองว่าการย้ายไป Rust อาจทำให้ผู้ใช้ fish บน Windows บางส่วนไม่สามารถอัปเดตได้
  • ความกังวลดังกล่าวไม่ได้มีไว้เพื่อโจมตีงานนี้หรือภาษา แต่เป็นการย้ำถึงข้อจำกัดที่ว่า Windows ไม่ใช่ Unix

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

 
GN⁺ 2023-11-27
ความคิดเห็นบน Hacker News
  • ถ้าผมเข้าใจไม่ผิด สิ่งที่น่าทึ่งคือการ ค่อย ๆ เขียนใหม่จาก C++ เป็น Rust แต่ยังคงให้โปรแกรมทำงานได้ตลอดจนถึงท้ายที่สุด
    ความคืบหน้าก็เร็วมาก และถ้ายังไม่เคยลองใช้ fish ก็แนะนำอย่างยิ่งให้ลอง เป็นเชลล์ที่ค่าเริ่มต้นดี ใช้งานสะดวกแม้ไม่ปรับแต่ง และหลังจากย้ายมาจาก bash เมื่อหลายปีก่อนก็ไม่คิดจะกลับไปอีก
    แถมยังไม่ต้องกูเกิลไวยากรณ์ for loop ของ bash ที่ไม่ค่อยได้ใช้และไม่ค่อยเป็นธรรมชาติทุกครั้งด้วย

    • ดูเหมือนจะไม่ได้ทำแบบค่อยเป็นค่อยไปนะ
      เขาบอกว่า “ไม่มีแผนจะออกรุ่นที่มี Rust ผสมอยู่บางส่วน” และตัวอย่างเช่น fish 4.0 ตั้งใจจะออกเป็น Rust ล้วน, C++ 0% ส่วนระหว่างทางก็น่าจะออกรุ่น 3.7.0 ที่ใช้แต่ C++ ด้วย เพื่อเป็นจุดตั้งต้นที่ดีกว่าสำหรับแพลตฟอร์มที่รับมือกับเวอร์ชัน Rust ไม่ได้
      https://github.com/fish-shell/fish-shell/discussions/10123#d...
    • สคริปต์ผมยังมักเขียนด้วย Bash หรือไม่ก็หยิบ Python/Perl มาใช้เลย แต่สำหรับ การใช้งานเทอร์มินัล แล้ว Fish ดีกว่าแน่นอน
    • ตัวอย่างลูป Bash ที่จำง่าย สำหรับดัชนีที่เพิ่มค่า ใช้แบบ for ((i = 0; i < 10; i++)); do echo $i; done ก็ได้
      การวนลูปผ่านอาร์เรย์ก็ทำได้โดยกำหนด foo[0]=a, foo[1]=b แล้วใช้รูปแบบ for i in ${foo[@]}; do echo $i; done
  • มีรายละเอียดแรงจูงใจในการเขียนใหม่มากขึ้นที่นี่
    https://github.com/fish-shell/fish-shell/pull/9512#issuecomm...

    • ข้อความของผู้ดูแลโปรเจกต์ดูเป็นผู้ใหญ่ มีเหตุผล มีอารมณ์ขันพอดี ๆ และหนักแน่น จนทำให้ความคิดที่เคยแค่ว่าจะลองใช้ Fish เปลี่ยนไปเป็น ดูเหมือนเรากำลังพลาดโปรเจกต์ที่ยอดเยี่ยมอยู่
    • การมองว่าการพอร์ตไป C++17 นั้น “ยุ่งยากเกินไป” แต่การเขียนใหม่ทั้งหมดด้วยภาษาใหม่กลับโอเค บอกอะไรได้ค่อนข้างมาก
      สุดท้ายแล้วคิดว่ายากที่จะเอาชนะเรื่อง การไล่ตามของใหม่แวววาว ในโลกการพัฒนาโดยรวมได้ ถึงอย่างนั้นแม้ผมไม่ได้ใช้ Fish ก็ขอให้ไปได้ดี
  • ในฐานะคนที่ใช้ Fish ทุกวันบนระบบปฏิบัติการราว 4 ตัวและชอบมันมาก การเขียนใหม่นี้น่าตื่นเต้นจริง ๆ และเมื่อคิดถึง ขนาดกับความซับซ้อนของโค้ดเบส แล้ว ความคืบหน้าน่าทึ่งมาก
    น่าจะช่วยให้หลายคนรวมถึงผมมีส่วนร่วมได้ง่ายขึ้นด้วย สิ่งที่ถูกพูดถึงน้อยกว่าแต่ผมตั้งตารอมากกว่าคือแผนในอนาคตที่จะเปลี่ยนให้ fish ใช้ UTF-8 แทน wchar_t UCS2 และ UTF-16 เป็นปัญหาชวนปวดหัวในซอฟต์แวร์มาโดยตลอด และ Rust จัดการ UTF-8 ได้สะดวกกว่ามาก

    • ถ้าต้องรองรับคอมไพเลอร์หลายตัวในโค้ดเบสเดียวกัน ความซับซ้อนจะเพิ่มขึ้น
      sizeof(wchar_t) บน MSVC เป็น 2 ไบต์จึงเป็น UTF-16 ส่วนบน gcc เป็น 4 ไบต์จึงเป็น UTF-32
  • Fish เป็นเชลล์ที่ถูกประเมินต่ำเกินไป
    มันตัดสินใจแบบแรง ๆ อย่าง การละทิ้งความเข้ากันได้กับ POSIX แต่ผลลัพธ์คือกลายเป็นเชลล์ที่ดีมาก ใช้มานานกว่า 10 ปีแล้วและยังชอบอยู่
    การเขียนสคริปต์ด้วย Fish shell ก็ใช้ง่ายมาก ให้ความรู้สึกเหมือน bash ที่ออกแบบตามหลักสรีรศาสตร์มากขึ้น ทุกโปรเจกต์ย่อมมีข้อบกพร่อง แต่ไม่เคยมีอะไรขวางไม่ให้ผมทำสิ่งที่ตั้งใจจะทำจริง ๆ

  • ในฐานะคนใช้ zsh + spaceship อยากรู้ว่าถ้าย้าย Fish มาเป็นเชลล์หลักจะได้ประโยชน์อะไรบ้าง
    ผมไม่ได้ใช้สคริปต์ bash เยอะ เลยให้ความสำคัญกับฝั่งสคริปต์น้อยกว่า

    • ถ้าตั้งค่า zsh ไว้ตามต้องการอยู่แล้ว ก็คงไม่ได้มีข้อดีใหญ่ ๆ มากนัก
      จุดเด่นใหญ่ของ Fish คือมันใกล้เคียงกับ เชลล์ในอุดมคติที่ใช้ได้ทันทีโดยไม่ต้องตั้งค่า การเติมคำอัตโนมัติทำงานทันที ค้นประวัติได้ง่าย มีการเติมคำสั่งจากประวัติ และการเลือกพรอมป์ก็ง่ายแค่ระดับเปิดเบราว์เซอร์ มันปรับแต่งเชิงลึกได้เหมือน zsh แต่แค่ค่าเริ่มต้นก็เป็นเชลล์ที่ดีพอสมควรแล้ว
    • เหตุผลที่เลือก Fish แทน zsh ในปี 2017 คือฟีเจอร์ที่ต้องการมีมาให้ในตัว และรู้สึกได้ว่าเร็วกว่าเยอะ
      หลังจากนั้นแทบไม่ต้องใช้เวลากับ การดูแลค่าตั้งเชลล์ อีกเลย ซึ่งดีมาก
    • เพราะความเร็ว
      Fish ทำหลายอย่างที่บน zsh ต้องใช้ปลั๊กอินให้มาในตัว ปลั๊กอิน zsh ช้า จนการเริ่มเชลล์ใช้เกิน 3 วินาที แต่ Fish แม้ใส่ปลั๊กอินก็ยังเริ่มได้เร็วกว่ามาก
    • ครั้งแรกที่สร้างไฟล์ fish_prompt.fish ในไดเรกทอรีที่ถูกต้อง แล้วเขียนฟังก์ชัน fish_prompt ในนั้นให้ส่งสตริงออกไปที่เอาต์พุตมาตรฐานเพื่อ ทำพรอมป์เชลล์เอง ผมแทบจะลบ zsh ทิ้ง
      มันทำให้ยากที่จะกลับไปใช้วิธียัดอะไรต่อมิอะไรลงใน $PS1 แล้วหวังว่าจะออกมาดี แนะนำให้ลองใช้สักสองสามวัน เพราะจะเริ่มเห็นว่าสิ่งที่เคยคิดว่าเป็นเรื่องปกติ อะไรบ้างที่จริง ๆ เป็นฟีเจอร์เฉพาะของแต่ละเชลล์ อย่างแย่ที่สุดก็แค่บอกว่า “ไม่ใช่แนวผม” แล้วกลับไปใช้เชลล์ที่ชอบอย่าง bash/zsh ก็ได้
    • ผมย้ายจาก zsh มา Fish เมื่อหลายปีก่อน ฟีเจอร์แทบจะใกล้เคียงกัน แต่ ไฟล์ตั้งค่า Fish มีขนาดประมาณ 10% ของการตั้งค่า zsh
      สิ่งที่ต้องการส่วนใหญ่มีมาให้โดยค่าเริ่มต้น และตอนนี้ใช้ปลั๊กอินแค่ fzf.fish ตัวเดียว
  • หนึ่งในเชลล์ที่เร็วที่สุดมีโอกาสสูงที่จะเร็วขึ้นอีก
    หลังจากย้ายจาก zsh มา Fish ประสิทธิภาพการทำงานในเทอร์มินัล ของผมเพิ่มขึ้นมาก

    • ผมไม่เดิมพันกับเรื่องนั้นหรอก
      ตามลิงก์บอกว่าในความเป็นจริงยังไม่รู้ว่าประสิทธิภาพของพอร์ตที่เสร็จแล้วจะเป็นอย่างไร ผลลัพธ์ช่วงแรกน่าดีใจ แต่ก็มีความเป็นไปได้ไม่น้อยว่าในบางกรณีอาจ ช้าลงราว 20%
    • ผมคิดว่าความต่างด้านประสิทธิภาพระหว่าง C++ กับ Rust ไม่ได้มากขนาดนั้น
      น่าจะสูสีกันมาก และอาจไม่มีผู้ชนะที่ชัดเจน
    • อยากรู้ว่าประสิทธิภาพของเชลล์กลายเป็นคอขวดในเวิร์กโฟลว์แบบไหน
      ปกติผมคิดว่ามันใกล้เคียงกับ โค้ดกาว ที่ส่งงานไปให้ที่อื่นมากกว่า อาจเป็นปัญหาประสิทธิภาพของ pipe หรืออาจเป็นเพราะพวกสายแปลกที่เขียนทั้งโปรแกรมด้วย bash ก็ได้ แต่ Fish มีการปรับปรุงคุณภาพชีวิตให้ใช้สะดวกอยู่เยอะ การยกความเร็วเป็นจุดขายหลักเลยดูแปลกนิดหน่อย
    • คงไม่มีใครพิมพ์และจัดการงานได้เร็วพอจนความต่างระหว่าง C, C++, Rust หรือภาษาอื่นมีนัยสำคัญ เลยสงสัยว่า Fish มีอะไรให้อีกหรือเปล่า
  • ใช้ Fish มา 1 ปีแล้ว
    ไม่ค่อยชอบตรงที่มันทำลายความเข้ากันได้กับมาตรฐานจนสคริปต์บางตัวอย่าง gvm, nvm รันไม่ได้ แต่ฟีเจอร์ที่ปกติใน zsh ต้องตั้งค่าเองนั้นมีมาให้หมดแล้ว เคยพยายามตั้งค่า zsh บนหลายเครื่องแล้วถอดใจ สุดท้ายเปลี่ยนทั้งหมดมาใช้ Fish ค่าเริ่มต้น
    มันก็ทำงานได้ดีอยู่แล้ว เลยไม่ค่อยแน่ใจว่าการพอร์ตไป Rust จะได้อะไร ถ้าเป็นเรื่องความปลอดภัย ก็อดคิดไม่ได้ว่าสิ่งที่สามารถแตะต้อง Fish อย่างประสงค์ร้ายได้นั้นคงขึ้นมาอยู่ในระบบแล้วไม่ใช่หรือ

    • อย่างที่เคยคุยกันในประเด็น Rust เดิม เหตุผลที่ย้ายไป Rust มีหลายอย่าง
      หลัก ๆ คือเรื่อง การดึงผู้ร่วมพัฒนา และการเพิ่มโหมด async/parallel ที่ผู้ดูแลมั่นใจได้
      [1] https://github.com/fish-shell/fish-shell/pull/9512
  • Fish ดีมาก
    ผมเปลี่ยนจาก ZSH+Prezto มาใช้แค่ Fish อย่างเดียว ไม่มีอะไรให้เสียดาย แถมเร็วขึ้นมาก บนเซิร์ฟเวอร์ทุกเครื่องยังมี bash และยังใช้ bash scripts อยู่เหมือนเดิม แต่สำหรับ งานเทอร์มินัลประจำวัน Fish ก็เพียงพอแล้ว

  • สนใจ Fish มาตลอด แต่ลังเลเพราะ ไม่เข้ากันกับ POSIX
    อยากรู้ว่ามีใครแชร์ปัญหาที่เจอในส่วนนี้และวิธีเลี่ยงได้บ้างไหม

    • Fish ไม่ได้มีไว้แทน bash/shell scripts แต่มีไว้ใช้เป็น interactive shell ดังนั้นการเป็นไปตาม POSIX จึงไม่ใช่ปัญหาใหญ่ในทางปฏิบัติ
      ข้อเสียคือจำเป็นต้องสลับบริบทเล็กน้อย โดยเฉพาะถ้าใช้ bash/zsh มาทั้งชีวิตก็อาจยิ่งรู้สึกแบบนั้น ส่วนตัวแล้วการแยกว่าตอนไหนใช้ shell เป็น user interface และตอนไหนใช้ bash/sh เป็น interpreter นั้นทำได้ง่าย แต่ก็อาจไม่ใช่เรื่องที่ทุกคนจะเข้าใจได้ทันที
      อีกอย่าง หลังจากเลิกใช้ shell ที่เข้ากันได้กับ POSIX เป็น shell ประจำวันแล้ว สคริปต์ที่เมื่อก่อนคงแก้ด้วย bash ก็ถูกยกระดับไปเป็นภาษาใช้งานทั่วไปได้เร็วขึ้น
    • Bash/zsh scripts ก็รันด้วย Bash/zsh ได้เลย: bash script.sh
      ตอนเริ่มใช้ Fish ใหม่ ๆ ก็ติดเรื่องไม่เข้ากันกับ POSIX เหมือนกัน แต่พอเรียน syntax ที่ต่างออกไปนิดหน่อยและข้ามจุดนั้นมาได้ ก็คิดว่า syntax ของ Fish ที่ sane กว่านั้นคุ้มกับความพยายาม ตอนนี้ใช้เทอร์มินัลได้สนุกขึ้นมาก
      แถม 90% ของเวลาไม่จำเป็นต้องรักษาความเข้ากันได้กับ POSIX และทุกวันนี้สคริปต์หรือส่วนขยายจำนวนมากก็รองรับ Fish ด้วย ในสภาพแวดล้อมองค์กรก็ยังใช้ Bash/zsh ซึ่งเป็นมาตรฐานต่อไป
  • สงสัยว่าทำไมถึงเปลี่ยนเป็น Rust
    โค้ดเบส C++ เริ่มรับมือยากแล้วหรือเปล่า?