Haskell ตอบสนองต่อ Node.js คืออะไร?


217

ฉันเชื่อว่าชุมชน Erlang ไม่ได้มีความริษยาของ Node.js เนื่องจากเป็นแบบไม่บล็อก I / O และมีวิธีการปรับใช้งานได้อย่างง่ายดายไปยังตัวประมวลผลมากกว่าหนึ่งตัว รายละเอียดเพิ่มเติมได้ที่http://journal.dedasys.com/2010/04/29/erlang-vs-node-jsและNode.js หรือ Erlang

แล้ว Haskell ล่ะ Haskell สามารถให้ประโยชน์บางอย่างของ Node.js ได้หรือไม่นั่นคือโซลูชันที่สะอาดเพื่อหลีกเลี่ยงการบล็อก I / O โดยไม่ต้องขอความช่วยเหลือจากการเขียนโปรแกรมแบบหลายเธรด?


มีหลายสิ่งที่น่าสนใจสำหรับ Node.js

  1. เหตุการณ์: ไม่มีการจัดการเธรดโปรแกรมเมอร์ให้การเรียกกลับเท่านั้น (ในกรอบงาน Snap)
  2. รับประกันการโทรกลับเพื่อให้ทำงานในหัวข้อเดียว: ไม่มีสภาพการแข่งขัน
  3. API ที่ใช้งานง่ายและเป็นมิตรกับ UNIX โบนัส: รองรับ HTTP ที่ยอดเยี่ยม นอกจากนี้ยังมี DNS
  4. I / O ทุกตัวเป็นค่าเริ่มต้นแบบอะซิงโครนัส ทำให้ง่ายขึ้นในการหลีกเลี่ยงการล็อค อย่างไรก็ตามการประมวลผล CPU มากเกินไปในการติดต่อกลับจะส่งผลต่อการเชื่อมต่ออื่น ๆ (ในกรณีนี้งานควรแบ่งออกเป็นงานย่อยที่มีขนาดเล็กลงและกำหนดเวลาใหม่)
  5. ภาษาเดียวกันสำหรับฝั่งไคลเอ็นต์และฝั่งเซิร์ฟเวอร์ (ฉันไม่เห็นคุณค่ามากเกินไปในตัวนี้ jQuery และ Node.js ใช้โมเดลการเขียนโปรแกรมเหตุการณ์ แต่ส่วนที่เหลือแตกต่างกันมากฉันไม่เห็นว่ารหัสที่ใช้ร่วมกันระหว่างฝั่งเซิร์ฟเวอร์และฝั่งไคลเอ็นต์ทำได้อย่างไร มีประโยชน์ในทางปฏิบัติ)
  6. ทั้งหมดนี้บรรจุในผลิตภัณฑ์เดียว

17
ฉันคิดว่าคุณควรถามคำถามนี้กับโปรแกรมเมอร์แทน
Jonas

47
ไม่รวมรหัสบางส่วนไม่ได้ทำให้มันเป็นคำถามอัตนัย
gawi

20
ฉันไม่รู้อะไรเกี่ยวกับ node.js มาก แต่มีสิ่งหนึ่งที่ทำให้ฉันสงสัยเกี่ยวกับคำถามของคุณ: ทำไมคุณถึงพบว่าโอกาสของเธรดไม่เป็นที่พอใจ? เธรดควรเป็นทางออกที่ถูกต้องในการมัลติเพล็กซิ่ง I / O ฉันใช้คำว่าเธรดกว้าง ๆ ที่นี่รวมถึงกระบวนการของ Erlang บางทีคุณอาจกังวลเกี่ยวกับการล็อคและสถานะที่ไม่แน่นอน คุณไม่ต้องทำสิ่งต่าง ๆ เช่นใช้การส่งข้อความหรือการทำธุรกรรมหากเหมาะสมกับแอปพลิเคชันของคุณ
Simon Marlow

9
@gawi ฉันไม่คิดว่ามันฟังดูง่ายมากหากไม่มีใบจองคุณต้องจัดการกับความเป็นไปได้ที่จะเกิดความอดอยากและเวลาแฝงที่ยาวนาน โดยทั่วไปแล้วเธรดเป็นสิ่งที่เหมาะสมสำหรับเว็บเซิร์ฟเวอร์ - ไม่จำเป็นต้องจัดการกับ I / O อะซิงโครนัสและความยากลำบากทั้งหมดที่เกิดขึ้นพร้อมกับสิ่งนั้นเพียงแค่ทำมันในเธรด ฉันเขียนบทความเกี่ยวกับเว็บเซิร์ฟเวอร์ใน Haskell ซึ่งคุณอาจสนใจ: haskell.org/~simonmar/papers/web-server-jfp.pdf
Simon Marlow

3
"การรับประกันการโทรกลับจะทำงานในหัวข้อเดียว: ไม่มีเงื่อนไขการแข่งขัน" ไม่ถูกต้อง. คุณสามารถมีเงื่อนไขการแข่งขันได้อย่างง่ายดายใน Node.js; แค่สมมติว่าการกระทำของ I / O อย่างใดอย่างหนึ่งจะเสร็จสิ้นก่อนอื่นและ BOOM สิ่งที่เป็นไปไม่ได้คือสภาพการแข่งขันประเภทหนึ่งคือการเข้าถึงแบบไม่ซิงโครไนซ์พร้อมกันกับไบต์เดียวกันในหน่วยความจำ
rightfold

คำตอบ:


219

ตกลงดังนั้นเมื่อได้ดูการนำเสนอ node.js เล็กน้อยที่ @gawi ชี้ให้ฉันฉันสามารถพูดเพิ่มเติมเล็กน้อยเกี่ยวกับวิธีที่ Haskell เปรียบเทียบกับ node.js ในงานนำเสนอไรอันอธิบายถึงประโยชน์ของกรีนเธรดบางส่วน แต่จากนั้นกล่าวต่อไปว่าเขาไม่พบว่าการขาดเธรดนามธรรมเป็นข้อเสีย ฉันไม่เห็นด้วยกับตำแหน่งของเขาโดยเฉพาะอย่างยิ่งในบริบทของ Haskell: ฉันคิดว่า abstractions ที่ thread จัดเตรียมนั้นจำเป็นสำหรับการทำให้โค้ดเซิร์ฟเวอร์ง่ายขึ้นเพื่อให้ถูกต้องและมีประสิทธิภาพยิ่งขึ้น โดยเฉพาะอย่างยิ่ง:

  • การใช้หนึ่งเธรดต่อการเชื่อมต่อช่วยให้คุณเขียนรหัสที่แสดงการสื่อสารกับไคลเอนต์เดียวแทนที่จะเขียนโค้ดที่เกี่ยวข้องกับไคลเอนต์ทั้งหมดในเวลาเดียวกัน คิดว่ามันเป็นเช่นนี้: เซิร์ฟเวอร์ที่จัดการกับไคลเอนต์หลายรายการที่มีเธรดดูเหมือนเกือบจะเหมือนกับไคลเอ็นต์ที่จัดการไคลเอ็นต์เดียว ความแตกต่างที่สำคัญคือมีforkที่ไหนสักแห่งในอดีต หากโปรโตคอลที่คุณใช้อยู่นั้นซับซ้อนการจัดการเครื่องสถานะสำหรับไคลเอนต์หลายคนพร้อมกันนั้นค่อนข้างยุ่งยากในขณะที่เธรดให้คุณเพียงแค่สคริปต์การสื่อสารกับไคลเอนต์เดียว รหัสนั้นง่ายต่อการทำความเข้าใจและบำรุงรักษา

  • การเรียกกลับบนเธรด OS เดียวคือการทำงานมัลติทาสกิ้งแบบร่วมมือซึ่งตรงข้ามกับมัลติทาสกิ้งแบบยึดเอาเสียก่อนซึ่งเป็นสิ่งที่คุณได้รับจากเธรด ข้อเสียเปรียบหลักกับการทำงานหลายอย่างแบบร่วมมือกันคือโปรแกรมเมอร์ต้องรับผิดชอบในการทำให้แน่ใจว่าไม่มีความอดอยาก มันสูญเสีย modularity: ทำผิดพลาดในที่เดียวและมันสามารถทำให้ทั้งระบบขึ้น นี่เป็นสิ่งที่คุณไม่ต้องกังวลและการจองเป็นวิธีแก้ปัญหาง่ายๆ ยิ่งไปกว่านั้นการสื่อสารระหว่างการโทรกลับเป็นไปไม่ได้

  • การเกิดขึ้นพร้อมกันนั้นไม่ยากใน Haskell เนื่องจากรหัสส่วนใหญ่นั้นบริสุทธิ์และมีความปลอดภัยในการสร้างเธรด มีการสื่อสารเบื้องต้น การถ่ายภาพตัวเองด้วยเท้าพร้อมกันใน Haskell นั้นยากกว่าการใช้ภาษาที่มีผลข้างเคียงที่ไม่ จำกัด


42
ตกลงดังนั้นฉันจึงได้รับ node.js ที่เป็นวิธีการแก้ปัญหาที่ 2: 1- การเกิดขึ้นพร้อมกันยากในภาษาส่วนใหญ่ 2- การใช้เธรด OS ที่กว้างขวาง วิธีแก้ปัญหา Node.js คือการใช้การทำงานพร้อมกันตามเหตุการณ์ (w / libev) เพื่อหลีกเลี่ยงการสื่อสารระหว่างเธรดและเพื่อหลีกเลี่ยงปัญหาความสามารถในการขยายของเธรด OS Haskell ไม่มีปัญหา # 1 เนื่องจากความบริสุทธิ์ สำหรับ # 2 Haskell มีเธรดที่มีน้ำหนักเบา + ตัวจัดการเหตุการณ์ซึ่งได้รับการปรับให้เหมาะสมใน GHC สำหรับบริบทขนาดใหญ่เมื่อเร็ว ๆ นี้ นอกจากนี้การใช้ Javascript ไม่สามารถถูกมองว่าเป็นประโยชน์สำหรับนักพัฒนา Haskell ได้ สำหรับบางคนที่ใช้ Snap Framework, Node.js นั้น "แย่"
gawi

4
การประมวลผลการร้องขอเป็นส่วนใหญ่ตามลำดับของการดำเนินการระหว่างกัน ฉันมักจะเห็นด้วยว่าการใช้การเรียกกลับสำหรับการดำเนินการบล็อกทุกครั้งอาจเป็นเรื่องยุ่งยาก หัวข้อมีความเหมาะสมดีกว่าโทรกลับนี้
gawi

10
อ้อ! และมัลติเพล็กซิ่ง I / O ใหม่ใน GHC 7 ทำให้เซิร์ฟเวอร์การเขียนใน Haskell ดียิ่งขึ้น
andreypopp

3
จุดแรกของคุณไม่สมเหตุสมผลสำหรับฉัน (ในฐานะคนนอก) ... เมื่อประมวลผลคำขอใน node.js ข้อเรียกกลับของคุณกับลูกค้ารายเดียว การจัดการสถานะกลายเป็นสิ่งที่ต้องกังวลเมื่อปรับไปสู่กระบวนการหลาย ๆ อย่างและแม้จะเป็นเรื่องง่ายมากที่ใช้ไลบรารีที่มีอยู่
Ricardo Tomasi

12
มันไม่ใช่ปัญหาแยกต่างหาก หากคำถามนี้เป็นการค้นหาของแท้สำหรับเครื่องมือที่ดีที่สุดสำหรับงานใน Haskell หรือตรวจสอบว่ามีเครื่องมือที่ยอดเยี่ยมสำหรับงานอยู่ใน Haskell หรือไม่ดังนั้นข้อสันนิษฐานโดยนัยว่าการเขียนโปรแกรมแบบมัลติเธรดจะต้องไม่ถูกท้าทายเพราะ Haskell หัวข้อค่อนข้างแตกต่างกันตามที่ Don Stewart ชี้ให้เห็น คำตอบที่อธิบายว่าเหตุใดชุมชน Haskell จึงไม่อิจฉา Node.js ด้วยเช่นกันสำหรับคำถามนี้ คำตอบของ gawi แสดงให้เห็นว่ามันเป็นคำตอบที่เหมาะสมสำหรับคำถามของเขา
AndrewC

154

Haskell สามารถให้ประโยชน์บางอย่างของ Node.js ได้หรือไม่นั่นคือโซลูชันที่สะอาดเพื่อหลีกเลี่ยงการบล็อก I / O โดยไม่ต้องขอความช่วยเหลือจากการเขียนโปรแกรมแบบหลายเธรด?

ใช่ในความเป็นจริงเหตุการณ์และหัวข้อเป็นปึกแผ่นใน Haskell

  • คุณสามารถตั้งโปรแกรมในเธรดที่มีน้ำหนักเบาอย่างชัดเจน (เช่นเธรดนับล้านบนแล็ปท็อปเครื่องเดียว)
  • หรือ; คุณสามารถตั้งโปรแกรมในรูปแบบเหตุการณ์ที่ขับเคลื่อนด้วย async ตามการแจ้งเตือนเหตุการณ์ที่ปรับขนาดได้

เธรดถูกนำไปใช้จริงในแง่ของเหตุการณ์และวิ่งข้ามหลายคอร์ด้วยการโยกย้ายเธรดที่ไร้รอยต่อด้วยประสิทธิภาพเอกสารและแอปพลิเคชัน

เช่นสำหรับ

  • การประสานงานอย่างหนาแน่น
  • การปรับขนาดคอลเลกชันพร้อมกันใน 32 หรือ 48 แกน
  • การสนับสนุนเครื่องมือสำหรับโปรไฟล์และแก้ไขข้อบกพร่องของโปรแกรมแบบมัลติเธรด / หลายเหตุการณ์
  • ที่มีประสิทธิภาพสูงเหตุการณ์ที่ขับเคลื่อนด้วยเว็บเซิร์ฟเวอร์
  • ผู้ใช้งานที่น่าสนใจ: เช่นการซื้อขายความถี่สูง

คอลเลกชันที่เกิดขึ้นพร้อมกันบน 32 คอร์

ข้อความแสดงแทน

ใน Haskell คุณมีทั้งเหตุการณ์และหัวข้อและมันเป็นเหตุการณ์ทั้งหมดภายใต้ประทุน

อ่านบทความที่อธิบายถึงการนำไปปฏิบัติ


2
ขอบคุณ ฉันต้องย่อยทั้งหมดนี้ ... นี่น่าจะเป็น GHC ที่เฉพาะเจาะจง ฉันเดาว่ามันโอเค ภาษา Haskell บางครั้งก็เป็นสิ่งที่ GHC สามารถรวบรวม ในทำนองเดียวกัน Haskell "แพลตฟอร์ม" เป็น GHC ที่มากขึ้นหรือน้อยลง
gawi

1
@gawi: นั่นและแพ็คเกจอื่น ๆ ทั้งหมดที่รวมเข้าด้วยกันเพื่อให้มันมีประโยชน์ทันทีที่ออกจากกล่อง และนี่คือภาพเดียวกับที่ฉันเห็นในหลักสูตร CS ของฉัน และส่วนที่ดีที่สุดคือมันไม่ยากใน Haskell เพื่อให้ได้ผลลัพธ์ที่ยอดเยี่ยมในโปรแกรมของคุณ
Robert Massaioli

1
สวัสดีดอนคุณคิดว่าคุณสามารถลิงก์ไปยังเว็บเซิร์ฟเวอร์ Haskell ที่ทำงานได้ดีที่สุด (Warp) เมื่อตอบคำถามเช่นนี้หรือไม่? นี่คือมาตรฐานที่เกี่ยวข้องกับ Node.js: yesodweb.com/blog/2011/03/…
Greg Weber

4
ในทางทฤษฎี Haskell "เธรดที่มีน้ำหนักเบา" ไม่ได้มีน้ำหนักเบาอย่างที่คุณคิด มันถูกกว่ามากมากในการลงทะเบียนการติดต่อกลับบนอินเทอร์เฟซแบบ epoll กว่ากำหนดเวลาเธรดสีเขียวที่เรียกว่าพวกเขาแน่นอนราคาถูกกว่าเธรด OS แต่ไม่ฟรี การสร้าง 100.000 ของพวกเขาใช้ประมาณ หน่วยความจำ 350 MB และใช้เวลาพอสมควร ลองเชื่อมต่อ 100.000 กับ node.js ไม่มีปัญหาเลย . มันจะเป็นเรื่องมหัศจรรย์ถ้ามันไม่เร็วขึ้นเนื่องจาก ghc ใช้ epoll ใต้ฝากระโปรงดังนั้นพวกมันจึงไม่สามารถเร็วกว่าการใช้ epoll โดยตรง การเขียนโปรแกรมด้วยเธรดอินเตอร์เฟสนั้นค่อนข้างดี
Kr0e

3
นอกจากนี้: ตัวจัดการ IO ใหม่ (ghc) ใช้อัลกอริทึมการจัดตารางเวลาซึ่งมีความซับซ้อน (m log n) (โดย m คือจำนวนเธรดที่รันได้และ n จำนวนเธรดทั้งหมด) Epoll มีความซับซ้อน k (k คือจำนวนที่สามารถอ่าน / เขียนได้ fd's = ดังนั้น ghc มี O (k * m log n) มากกว่าความซับซ้อนทั้งหมดซึ่งไม่ดีมากถ้าคุณเผชิญกับการเชื่อมต่อที่มีปริมาณการใช้สูง Node.js มีเพียงความซับซ้อนเชิงเส้น . โดย epoll และเพียงแค่ให้เราไม่ได้พูดคุยเกี่ยวกับหน้าต่างที่มีประสิทธิภาพ ... Node.js เป็นได้เร็วขึ้นมากเพราะใช้ IOCP.
Kr0e

20

ก่อนอื่นฉันไม่เก็บมุมมองของคุณว่า node.js กำลังทำสิ่งที่ถูกต้องซึ่งจะแสดงการเรียกกลับทั้งหมด คุณจบลงด้วยการเขียนโปรแกรมของคุณใน CPS (สไตล์การส่งต่ออย่างต่อเนื่อง) และฉันคิดว่ามันควรจะเป็นหน้าที่ของคอมไพเลอร์ในการทำการเปลี่ยนแปลง

เหตุการณ์: ไม่มีการจัดการเธรดโปรแกรมเมอร์ให้การเรียกกลับเท่านั้น (ในกรอบงาน Snap)

ดังนั้นในใจคุณสามารถเขียนโดยใช้สไตล์อะซิงโครนัสหากคุณต้องการ แต่โดยการทำเช่นนั้นคุณจะพลาดการเขียนในสไตล์ซิงโครนัสที่มีประสิทธิภาพด้วยหนึ่งเธรดต่อคำขอ Haskell มีประสิทธิภาพอย่างน่าหัวเราะที่โค้ดซิงโครนัสโดยเฉพาะเมื่อเปรียบเทียบกับภาษาอื่น มันคือกิจกรรมทั้งหมดภายใต้

รับประกันการโทรกลับเพื่อให้ทำงานในหัวข้อเดียว: ไม่มีสภาพการแข่งขัน

คุณยังสามารถมีสภาพการแข่งขันใน node.js แต่มันยากขึ้น

ทุกคำขออยู่ในกระทู้ของตัวเอง เมื่อคุณเขียนโค้ดที่ต้องสื่อสารกับเธรดอื่น ๆ มันเป็นเรื่องง่ายมากที่จะทำให้มันเป็น threadsafe ด้วยการทำงานแบบพร้อมกันของ haskell

API ที่ใช้งานง่ายและเป็นมิตรกับ UNIX โบนัส: รองรับ HTTP ที่ยอดเยี่ยม นอกจากนี้ยังมี DNS

ดูการแฮ็กและดูด้วยตัวคุณเอง

I / O ทุกตัวเป็นค่าเริ่มต้นแบบอะซิงโครนัส (ซึ่งอาจสร้างความรำคาญในบางครั้ง) ทำให้ง่ายขึ้นในการหลีกเลี่ยงการล็อค อย่างไรก็ตามการประมวลผล CPU มากเกินไปในการติดต่อกลับจะส่งผลต่อการเชื่อมต่ออื่น ๆ (ในกรณีนี้งานควรแบ่งออกเป็นงานย่อยที่มีขนาดเล็กลงและกำหนดเวลาใหม่)

คุณไม่มีปัญหาดังกล่าว ghc จะแจกจ่ายงานของคุณในระบบปฏิบัติการจริง

ภาษาเดียวกันสำหรับฝั่งไคลเอ็นต์และฝั่งเซิร์ฟเวอร์ (ฉันไม่เห็นคุณค่ามากเกินไปในอันนี้ JQuery และ Node.js ใช้โมเดลการเขียนโปรแกรมเหตุการณ์ แต่ส่วนที่เหลือแตกต่างกันมากฉันไม่เห็นว่ารหัสการแชร์ระหว่างฝั่งเซิร์ฟเวอร์และฝั่งไคลเอ็นต์ทำได้อย่างไร มีประโยชน์ในทางปฏิบัติ)

Haskell อาจชนะที่นี่ไม่ได้ ... คิดอีกครั้ง, http://www.haskell.org/haskellwiki/Haskell_in_web_browser

ทั้งหมดนี้บรรจุในผลิตภัณฑ์เดียว

ดาวน์โหลด ghc, fire up cabal มีแพ็คเกจสำหรับทุกความต้องการ


ฉันแค่เล่นเป็นผู้สนับสนุนของปีศาจ ใช่ฉันเห็นด้วยกับคะแนนของคุณ ยกเว้นการรวมภาษาฝั่งไคลเอ็นต์และฝั่งเซิร์ฟเวอร์ ในขณะที่ฉันคิดว่ามันเป็นไปได้ทางเทคนิคฉันไม่คิดว่าในที่สุดมันอาจแทนที่ระบบนิเวศ Javascript ทั้งหมดในวันนี้ (JQuery และเพื่อน) ในขณะที่การโต้เถียงโดยผู้สนับสนุน Node.js ฉันไม่คิดว่ามันเป็นสิ่งที่สำคัญมาก คุณต้องการแชร์รหัสจำนวนมากระหว่างเลเยอร์การนำเสนอและแบ็กเอนด์ของคุณหรือไม่? พวกเราตั้งเป้าให้โปรแกรมเมอร์รู้ภาษาเดียวหรือไม่?
gawi

ชัยชนะที่แท้จริงคือคุณสามารถแสดงผลหน้าทั้งบนเซิร์ฟเวอร์และฝั่งไคลเอ็นต์ทำให้การสร้างหน้าเรียลไทม์ง่ายขึ้น
dan_waterworth

@dan_waterworth แน่ ๆ ดูmeteor or derby.js
mb21

1
@gawi เรามีบริการการผลิตที่ 85% ของรหัสที่ใช้ร่วมกันระหว่างลูกค้าและเซิร์ฟเวอร์ สิ่งนี้เรียกว่า JavaScript สากลในชุมชน เรากำลังใช้ React เพื่อแสดงเนื้อหาบนเซิร์ฟเวอร์เพื่อลดเวลาในการเรนเดอร์ที่มีประโยชน์ในไคลเอนต์ ในขณะที่ฉันทราบว่าคุณสามารถเรียกใช้ Haskell ในเบราว์เซอร์ได้ฉันไม่ทราบถึงแนวทางปฏิบัติที่ดีที่สุด "universal Haskell" ชุดใด ๆ ที่อนุญาตสำหรับการแสดงผลฝั่งเซิร์ฟเวอร์และฝั่งไคลเอ็นต์โดยใช้รหัสฐานเดียวกัน
Eric Elliott

8

ฉันเห็น Node.js และการเขียนโปรแกรมด้วยการโทรกลับเป็นการส่วนตัวในระดับต่ำโดยไม่จำเป็นและเป็นสิ่งที่ผิดธรรมชาติเล็กน้อย ทำไมโปรแกรมที่มีการโทรกลับเมื่อรันไทม์ที่ดีเช่นที่พบใน GHC อาจจัดการกับการโทรกลับสำหรับคุณและทำได้อย่างมีประสิทธิภาพ

ในขณะเดียวกัน GHC runtime ได้รับการปรับปรุงอย่างมาก: ตอนนี้มี "ผู้จัดการ IO ใหม่ใหม่" ชื่อMIOโดยที่ "M" หมายถึงมัลติคอร์ที่ฉันเชื่อ มันสร้างบนพื้นฐานของผู้จัดการ IO ที่มีอยู่และเป้าหมายหลักคือการเอาชนะสาเหตุของการลดประสิทธิภาพของแกน 4+ ตัวเลขประสิทธิภาพที่ให้ไว้ในบทความนี้ค่อนข้างน่าประทับใจ ดูตัวเอง:

ด้วย Mio เซิร์ฟเวอร์ HTTP ที่เหมือนจริงในระดับ Haskell ถึง 20 คอร์ของ CPU ให้ได้ประสิทธิภาพสูงสุดถึง 6.5 เท่าเมื่อเทียบกับเซิร์ฟเวอร์เดียวกันโดยใช้ GHC รุ่นก่อนหน้า เวลาแฝงของเซิร์ฟเวอร์ Haskell ได้รับการปรับปรุงด้วย: [... ] ภายใต้ภาระงานปานกลางลดเวลาตอบสนองที่คาดไว้ 5.7x เมื่อเปรียบเทียบกับ GHC รุ่นก่อนหน้า

และ:

นอกจากนี้เรายังแสดงให้เห็นว่าด้วย Mio, McNettle (คอนโทรลเลอร์ SDN ที่เขียนใน Haskell) สามารถปรับขนาดได้อย่างมีประสิทธิภาพมากกว่า 40 คอร์เข้าถึงการร้องขอใหม่มากกว่า 20 ล้านครั้งต่อวินาทีบนเครื่องเดียวและรวดเร็วที่สุดของคอนโทรลเลอร์ SDN ที่มีอยู่ทั้งหมด .

Mio ได้เปิดตัว GHC 7.8.1 แล้ว ฉันเองเห็นว่านี่เป็นก้าวสำคัญในการแสดงของ Haskell มันจะน่าสนใจมากเมื่อเปรียบเทียบประสิทธิภาพเว็บแอปพลิเคชันที่มีอยู่ซึ่งรวบรวมโดย GHC เวอร์ชันก่อนหน้าและ 7.8.1


6

เหตุการณ์ IMHO นั้นดี แต่การเขียนโปรแกรมด้วยการโทรกลับไม่ใช่

ปัญหาส่วนใหญ่ที่ทำให้การเข้ารหัสและการดีบักแบบพิเศษของเว็บแอปพลิเคชันมาจากสิ่งที่ทำให้สามารถปรับขนาดได้และมีความยืดหยุ่น สิ่งที่สำคัญที่สุดคือลักษณะไร้สัญชาติของ HTTP สิ่งนี้ช่วยเพิ่มความสามารถในการนำทาง แต่สิ่งนี้ทำให้การควบคุมกลับกันโดยที่องค์ประกอบ IO (เว็บเซิร์ฟเวอร์ในกรณีนี้) เรียกใช้ตัวจัดการต่าง ๆ ในรหัสแอปพลิเคชัน รูปแบบกิจกรรมนี้ - หรือรูปแบบการโทรกลับพูดอย่างแม่นยำมากขึ้น - เป็นฝันร้ายเนื่องจากการโทรกลับไม่แชร์ขอบเขตตัวแปรและมุมมองที่ใช้งานง่ายของการนำทางจะหายไป มันยากมากที่จะป้องกันการเปลี่ยนแปลงสถานะที่เป็นไปได้ทั้งหมดเมื่อผู้ใช้นำทางกลับไปกลับมาท่ามกลางปัญหาอื่น ๆ

อาจกล่าวได้ว่าปัญหาคล้ายกับการเขียนโปรแกรม GUI ที่รูปแบบเหตุการณ์ทำงานได้ดี แต่ GUI ไม่มีการนำทางและไม่มีปุ่มย้อนกลับ ที่เพิ่มจำนวนการเปลี่ยนสถานะที่เป็นไปได้ในเว็บแอปพลิเคชัน ผลลัพธ์ของความพยายามในการแก้ปัญหาเหล่านี้คือเฟรมเวิร์กที่หนักหน่วงด้วยการกำหนดค่าที่ซับซ้อนมากมายตัวระบุเวทย์มนตร์ที่แพร่หลายโดยไม่ต้องถามรากของปัญหา: โมเดลการเรียกกลับและการขาดการแบ่งปันขอบเขตตัวแปรโดยธรรมชาติและไม่มีการเรียงลำดับ สร้างโดยการเชื่อมโยงตัวระบุ

มีเฟรมเวิร์กตามลำดับเช่น ocsigen (ocaml) ริมทะเล (smalltalk) WASH (หยุดการทำงาน, Haskell) และ mflow (Haskell) ที่แก้ปัญหาการจัดการของรัฐในขณะที่ยังคงความสามารถในการควบคุม ภายในกรอบเหล่านี้โปรแกรมเมอร์สามารถแสดงการนำทางเป็นลำดับที่จำเป็นซึ่งโปรแกรมส่งหน้าและรอการตอบสนองในเธรดเดียวตัวแปรอยู่ในขอบเขตและปุ่มย้อนกลับทำงานโดยอัตโนมัติ สิ่งนี้จะสร้างรหัสที่สั้นกว่าปลอดภัยกว่าและอ่านได้ง่ายกว่าโดยที่โปรแกรมเมอร์สามารถมองเห็นการนำทางได้อย่างชัดเจน (คำเตือนที่เป็นธรรม: ฉันเป็นผู้พัฒนา mflow)


ใน node.js callbacks ใช้สำหรับจัดการ async I / O เช่นฐานข้อมูล คุณกำลังพูดถึงสิ่งที่แตกต่างซึ่งในขณะที่น่าสนใจไม่ตอบคำถาม
Robin Green

คุณพูดถูก ใช้เวลาสามปีกว่าจะได้รับคำตอบว่าฉันหวังว่าจะได้พบกับข้อคัดค้านของคุณ: github.com/transient-haskell
agocorona

ตอนนี้โหนดรองรับฟังก์ชั่น async ซึ่งหมายความว่าคุณสามารถเขียนโค้ดลักษณะที่ไม่แน่นอนซึ่งเป็นแบบอะซิงโครนัสได้จริง ใช้สัญญาภายใต้ประทุน
Eric Elliott

5

คำถามนี้ค่อนข้างไร้สาระเพราะ 1) Haskell ได้แก้ไขปัญหานี้ในทางที่ดีขึ้นมากและ 2) ในแบบเดียวกับที่ Erlang มี นี่คือเกณฑ์เปรียบเทียบกับโหนด: http://www.yesodweb.com/blog/2011/03/preliminary-warp-cross-language-benchmarks

ให้ Haskell 4 คอร์และสามารถทำคำขอได้ 100k (ง่าย) ต่อวินาทีในแอพพลิเคชั่นเดียว โหนดไม่สามารถทำได้หลายอย่างและไม่สามารถปรับขนาดแอปพลิเคชันเดี่ยวข้ามคอร์ได้ และคุณไม่ต้องทำอะไรเพื่อเก็บเกี่ยวสิ่งนี้เพราะรันไทม์ของ Haskell นั้นไม่มีการบล็อก ภาษาอื่น ๆ (ค่อนข้างทั่วไป) ที่ไม่มีการบล็อก IO ที่มีอยู่ในรันไทม์คือ Erlang


14
ไร้สาระ? คำถามไม่ใช่ "Haskell มีการตอบสนอง" แต่ไม่ใช่ "การตอบสนองของ Haskell คืออะไร" ในช่วงเวลาที่มีการถามคำถาม GHC 7 ยังไม่ได้รับการปล่อยตัวดังนั้น Haskell ยังไม่ได้ "อยู่ในเกม" (ยกเว้นในกรณีของเฟรมเวิร์กที่ใช้ libev เช่น Snap) นอกจากนั้นฉันเห็นด้วย
gawi

1
ฉันไม่รู้ว่านี่เป็นเรื่องจริงหรือไม่เมื่อคุณโพสต์คำตอบนี้ แต่ในความเป็นจริงแล้วตอนนี้มีโมดูลโหนดที่อนุญาตให้แอปโหนดปรับขนาดข้ามแกนได้อย่างง่ายดาย นอกจากนี้ลิงก์นั้นกำลังเปรียบเทียบ node.js ที่ทำงานบนแกนเดียวกับ Haskell ที่ทำงานบน 4 คอร์ ฉันต้องการที่จะเห็นมันทำงานอีกครั้งในการกำหนดค่าที่เป็นธรรม แต่อนิจจา repo GitHub หายไป
Tim Gautier

2
Haskell ที่ใช้มากกว่า 4 คอร์จะลดประสิทธิภาพของแอพพลิเคชั่นลง มีบทความเกี่ยวกับปัญหานี้ใช้งานได้ แต่ก็ยังเป็นปัญหาอยู่ ดังนั้นการรัน Node.js 16 อินสแตนซ์ของเซิร์ฟเวอร์ 16 หลักน่าจะดีกว่าแอพพลิเคชั่น ghc เดี่ยวโดยใช้ + RTS -N16 ซึ่งแน่นอนว่าช้ากว่า + RTS -N1 เนื่องจากข้อผิดพลาดรันไทม์นี้ เป็นเพราะพวกเขาใช้ IOManager เพียงอันเดียวซึ่งจะทำให้ช้าลงเมื่อใช้กับเธรด OS จำนวนมาก ฉันหวังว่าพวกเขาจะแก้ไขข้อผิดพลาดนี้ แต่มันมีอยู่ตั้งแต่เคยดังนั้นฉันจะไม่หวังมาก ...
Kr0e

ใครก็ตามที่ดูคำตอบนี้ควรระวังว่า Node สามารถประมวลผลคำร้องของ่าย ๆ ได้ 100k บนคอร์เดียวและง่ายมากที่จะไต่ระดับแอปพลิเคชั่นโหนดไร้สัญชาติข้ามหลายคอร์ pm2 -i max path/to/app.jsจะปรับขนาดเป็นจำนวนอินสแตนซ์ที่เหมาะสมโดยอัตโนมัติตามแกนที่มีให้ นอกจากนี้โหนดยังไม่มีการบล็อกตามค่าเริ่มต้น
Eric Elliott

1

1
คำถามนี้จะตอบคำถามได้อย่างไร
dfeuer

1
@dfeuer ลิงก์ต้องอ่านเช่น Snap Haskell Web Framework ได้ลดลง libev ฉันไม่รู้ว่าทำไมการจัดรูปแบบจึงล้มเหลว โหนดเซิร์ฟเวอร์รันไทม์นั้นเกี่ยวกับ Linux libev เมื่อเริ่มทำงานดังนั้น Snap Web FrameWork ก็เช่นกัน Haskell with Snap นั้นเหมือนกับ ECMAscript กับ nodejs ดังนั้น Snap ที่วิวัฒนาการมาพร้อมกับ nodejs นั้นมีความเกี่ยวข้องมากกว่า Haskell ซึ่งสามารถเปรียบเทียบได้อย่างถูกต้องกับ ECMAscript ในบริบทนี้
Chawathe Vipul S
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.