ComBioLaw.De » Blog » เขียนโปรแกรม » Hard Fight : Java vs. Python vs. Ruby

Hard Fight : Java vs. Python vs. Ruby

imageผมเป็นคนที่ชอบศึกษาเรื่องภาษาเขียนโปรแกรม ดังจะเห็นได้จาก จำนวนบล็อกที่ผมเขียนเกี่ยวกับภาษาเขียนโปรแกรม ที่มีมากกว่าในเรื่องอื่น ๆ จากการศึกษาโดยการเข้าไปหาข้อมูลในอินเตอร์เนตพบว่า เรื่องภาษาเขียนโปรแกรมเป็นเรื่องศาสนา คือ เป็นเรื่องที่มีพื้นฐานอยู่บนความเชื่อ มากกว่าเหตุผล

ทฤษฎีทางความเชื่อเกี่ยวกับภาษาเขียนโปรแกรมจำนวนมาก ได้ถูกกล่าวอ้างโดยไม่ได้รับข้อพิสูจน์ โดยเฉพาะจากเหล่าสาวกของภาษานั้น ๆ บางครั้งเวลาผมอ่านก็เคลิ้มตามไปเหมือนกัน บางครั้งก็อดตั้งคำถามไม่ได้ว่า มันจะจริงเหรอ ???

ผมจึงรู้สึกว่า น่าจะเขียนบล็อกขึ้นมาหนึ่งบล็อก เพื่อเปรียบเทียบคุณสมบัติต่าง ๆ ของภาษาเขียนโปรแกรมขึ้นมาหนึ่งบล็อก เพื่อเปรียบเทียบให้เห็นกันจะ ๆ และพยายามเป็นกลางให้มากที่สุด (อันนี้แหละยาก) เผื่อว่าใครจะเอาข้อมูลไปใช้ประกอบการตัดสินใจ โดยภาษาที่ผมจะนำมาเปรียบมวยมีด้วยกัน 3 ภาษา คือ Java, Python และ Ruby เพราะเป็นภาษาที่ได้รับความนิยมในขณะนี้ และดูที่อนาคตจะไปได้สวย (จริง ๆ อยากเขียน C# เหมือนกัน แต่ดูเหมือน C# จะแผ่วไปเยอะในช่วงหลัง)

อันที่จริง ...

เขียนโปรแกรม เขียนโปรแกรม

bow_der_kleine bow_der_kleine

มีคนเปรียบมวย Python กับ Java ไว้แล้วเยอะเหมือนกัน ไม่ว่าจะเป็น Python & Java: Side by Side Comparison

(รู้สึกหน้านี้จะเสีย ลองไปอ่านที่ Google-Cache ดูครับ), C++ vs Java vs Python vs Ruby : a first impression และ Python vs. Perl vs. Java vs. C++ Runtimes แต่ส่วนมากมักเป็นข้อมูลเก่า (ยกเว้น C++ vs Java vs Python vs Ruby : a first impression ข้อมูลค่อนข้างใหม่) ผมจึงอยากอัพเดดข้อมูลบางอย่างเพิ่มเติมลงไป และทดสอบโดยใช้โปรแกรมที่ใกล้เคียงกับการใช้งานจริงมากที่สุด

About me

ก่อนอื่นผมต้องแนะนำตัว เกี่ยวกับพื้นหลังการเขียนโปรแกรมของผมก่อนครับ เพื่อให้คนอ่านใช้ประกอบวิจรณญาณในการอ่าน

ทุกวันนี้ผมทำงานโดยใช้ Python ในการเขียนโปรแกรม Simulation เกี่ยวกับเคเบิลใยแก้วนำแสง ดังนั้น คนอ่านไม่ต้องแปลกใจครับ หากผมจะลำเอียงไปทาง Python แต่ผมจะพยายามรักษาความเป็นกลางไว้ให้มากที่สุดครับ

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

ผมไม่เคยศึกษา Ruby อย่างเป็นเรื่องเป็นราว แต่ก็ผ่าน ๆ ตามาบ้าง โดยการใช้งาน Ruby on Rails ความรู้ Ruby ผมจึงเป็นแบบ งูงู ปลาปลา อย่าถือสากันนะครับ :D

About this fight

การเปรียบมวยครั้งนี้ ผมได้เขียนขึ้นโดยวิเคราะห์จากการเขียนโปรแกรม โปรแกรมค้นหาข้อมูลสำหรับ CMS ซึ่งเดิมทีนั้น ผมเขียนขึ้นโดยใช้ PHP แล้วนำมาเขียนใหม่โดยใช้ Java, Python และ Ruby โดยมีการตัดโค้ดบางส่วนออก และปรับปรุงอีกเล็กน้อย เพื่อให้เหมาะสมกับการทดสอบ

ส่วนการทดสอบความเร็วนั้น ผมได้อ้างอิงตาม Python vs. Perl vs. Java vs. C++ Runtimes โดยมาปรับปรุงสำหรับ Ruby และเพิ่มการทดสอบในกรณีอื่น ๆ เข้าไปอีกเล็กน้อย

ในแต่ละยกผมจะให้คะแนน แต่ละภาษาโดยให้เป็น image ยิ่งมากยิ่งดี โดยมีคะแนนเต็ม imageimageimageimageimage (คิดถึงตอนเรียนอนุบาลเลย)

Round 1 : The first impression

ในยกนี้ผมวิเคราะห์ตามความรู้สึกของผม ที่ได้เขียนโปรแกรมในภาษานั้น ๆ เป็นครั้งแรก ประกอบกับความรู้สึกของเพื่อน ๆ ที่เขียนโปรแกรมภาษานั้น ๆ เป็น

  • Java : image : เป็นภาษาที่เหมาะกับวิศวกรซอพท์แวร์ แต่ไม่ค่อยถูกโฉลกกับคนวงการอื่น ๆ ในครั้งแรกที่เริ่มเขียน Java อะไร ๆ ก็ดูยากไปหมด ผมและเพื่อนทุกคนเห็นพ้องต้องกันตอนเรียน Java ว่า Java ยากกว่า C อีก อีกทั้งตัวภาษาไม่เอื้อต่องานประเภท Quick and Dirty คือลองเขียนเล่น ๆ สั้น ๆ คนที่จะเขียนโปรแกรม Java โปรแกรมแรกได้นั้น ต้องรู้จัก JRE, JDK, class, object, public, static, void, main ก่อนถึงจะเขียนได้ อีกทั้งยังเจอ Concept แปลก ๆ ที่คนที่ไม่เคยเขียน Java มาก่อน ก็ต้องงงไปตาม ๆ กัน เช่น Interface, Abstact Class, Iteration, Type Cast เป็นต้น สรุปคือ กว่าจะเขียน Java เป็นต้องใช้เวลาค่อนข้างนาน
  • Python : imageimageimageimage : คงเหมือนกับภาษา Script ภาษาอื่น ๆ ที่ไม่ต้องรู้อะไรมากก็ลงมือเขียนได้เลย มี Interactive-Console ให้ใช้งาน ลองเล่นไปตามเรื่องตามราว แต่สิ่งที่กวนประสาทมาก ๆ คือ Indent เป็นเรื่องที่ต้องใช้เวลาในการปรับตัวกันนานพอสมควร
  • Ruby : imageimageimageimageimage : ครั้งแรกที่ลองใช้งาน อะไร ๆ ก็ดูง่ายไปหมด หากรู้จักภาษา Script อื่น ๆ มาก่อน Ruby แล้ว การเรียนรู้ Ruby ก็จะใช้เวลาน้อยมาก

Round 2 : Community

Community เป็นปัจจัยสำคัญมากในการเลือกใช้งานภาษาเขียนโปรแกรมในปัจจุบัน ภาษาที่มี Community ที่แข็งแกร่ง ย่อมหมายถึงโอกาสอยู่รอดของภาษาในอีกสิบปี ยี่สิบปีข้างหน้าก็จะสูงตามไปด้วย

  • Java : imageimageimageimageimage : เนื่องจาก Java เป็นภาษาที่ได้รับความนิยมสูงสุด มีบริษัทยักษ์ใหญ่จำนวนมากให้การสนับสนุน Java และเลือก Java เป็นภาษาหลักในพัฒนาซอพท์แวร์ของตัวเอง อีกทั้งในขณะนี้ Java กลายเป็น OpenSource เป็นที่เรียบร้อยแล้ว ดังนั้น Community ของ Java จึงแข็งแกร่งไร้เทียมทาน
  • Python : imageimageimageimageimage: Python เป็น OpenSource โดยกำเนิด และเป็นภาษาที่ได้รับความนิยมมากขึ้นเรื่อย ๆ มีองค์กรณ์สนับสนุนอย่างเป็นทางการมากมาย (PSF, Google, Zope) แม้ความนิยมในตัว Python ยังไม่เทียบเท่า Java แต่ความแข็งแกร่งของ Community ก็ไม่ได้เป็นรอง Java แม้แต่น้อย
  • Ruby :imageimageimageimage: แม้ว่า Ruby จะเป็นภาษาที่ค่อนข้องใหม่ แต่ในระยะเวลาสองปีที่ผ่านมา Ruby ได้รับความนิยมเพิ่มขึ้นอย่างรวดเร็ว สาเหตุก็เนื่องมาจาก Ruby on Rails ความแข็งแกร่งของ Community ของ Ruby จึงเพิ่มขึ้นอย่างน่าจับตามอง แม้กระนั้นก็ตาม Community ของ Ruby ยังอยู่ในภาวะสร้างตัว จึงยังไม่แข็งกร่งเท่าภาษาเขียนโปรแกรมรุ่นพี่อย่าง Java และ Python แต่คาดว่าอีกปีหรือสองปี Ruby อาจเทียบชั้นมาตีเสมอได้ไม่ยาก

Round 3 : Library

  • Java : imageimageimageimage : เนื่องจาก Java เป็นภาษาที่ได้รับความนิยมอย่างสูง จึงไม่ใช่เรื่องแปลกที่ Java จะมี Library ให้เลือกใช้มากมาย โดยเฉพาะอย่างยิ่งการเขียนโปรแกรมเชิงธุรกิจ แต่ Library ส่วนใหญ่ของ Java ได้รับการออกแบบมาซับซ้อนเกินไป ทำให้ใช้ยาก อีกทั้งยังขาด Library สำหรับโปรแกรมทางวิทยาศาสตร์อีกจำนวนมาก
  • Python : imageimageimageimage : แม้ว่า Library ของ Python คลอบคลุมการใช้งานมากกว่า Java (ทางวิทยาศาสตร์, Image Processing, Latex, 3D-Rendering, etc.) แต่ Library ส่วนใหญ่ยังมีมาตรฐานไม่เทียบเท่าของ Java ส่วนหนึ่งเนื่องมาจากเป็นโครงการ OpenSource ขนาดเล็ก
  • Ruby : imageimageimage : ความเป็นภาษาใหม่ของ Ruby ทำให้ Ruby มี Library ให้เลือกใช้ยังไม่มากนัก แต่ Library ของ Ruby ก็น่าจับตามอง เนื่องเพราะเป็น Library ที่ใช้งานง่าย และมีมาตรฐาน เมื่อเปรียบเทียบกับ Java และ Python

Round 4 : Time to code

  • Java : imageimage : ใครบอกว่า Java เขียนง่ายผมคนหนึ่งล่ะที่ไม่เชื่อ คนส่วนใหญ่บอกว่า Java เขียนง่ายกว่า C++ ผมเห็นด้วยเพียงครึ่งเดียว Concept ของ Java แม้จะทำให้เขียนโปรแกรมง่ายกว่า C++ ก็จริง แต่ก็เข้าใจยากกว่าเหมือนกัน (แค่ Itration อ. ที่สอนต้องใช้เวลาอธิบายอยู่หลายอาทิตย์ กว่าพวกผมจะเข้าใจ) และเนื่องจาก Java ยังเป็น Compiled Language อยู่ การลองโน่นลองนี่จึงไม่ใช่เรื่องง่าย เพราะต้องเสียเวลาในการ Compile อีกทั้งความพยายามออกแบบ Java ให้ Common มากที่สุด ก็ทำให้ Java ซับซ้อนเกินกว่าเหตุ
  • Python : imageimageimageimageimage : ความเป็น Script ของ Python ทำให้การเขียนโค้ดด้วย Python รวดเร็วทันใจอยู่แล้ว บวกกับคอนเซพท์ที่เข้าใจง่ายของ Python ยิ่งทำการเขียนโค้ดของ Python เร็วขึ้นไปอีก เครื่องมือในการหาข้อผิดพลาดที่พร้อม คุณภาพโค้ดที่ได้ก็สูง เพราะโดนบังคับโดยตัวภาษา โครงสร้างของภาษาที่รองรับโครงการขนาดใหญ่ โดยส่วนตัวผมเห็นว่า Python น่าจะเป็นภาษาที่เขียนโค้ดได้เร็วที่สุดในขณะนี้
  • Ruby : imageimageimageimage : คุณสมบัติดี ๆ หลายอย่างของ Perl และ Python ถูกสอดแทรกลงใน Ruby ได้อย่างลงตัว แม้ว่า Ruby จะเป็นภาษาที่ใช้เครื่องหมายมากเกินไป (ออกแนว Perl) ทำให้โค้ดที่ได้อ่านยากไปบ้าง แต่ก็ถูกทดแทนด้วยคอนเซพท์หลายอย่างที่ไม่เหมือนใคร (symbol, attr_reader) ในขั้นต้นการเขียนโค้ดด้วย Ruby อาจเร็วกว่า Python แต่ในระยะยาว Ruby อาจประสบปัญหาเดียวกับ Perl คือ Write only coding

Round 5 : How does the language do ?

5.1 : Block

  • Java : imageimageimageimageimage : สำหรับผมแล้วการแบ่งบล็อกด้วยวงเล็บปีกกา {} เป็นการแบ่งบล็อกที่ผมชอบมากที่สุด เพราะสามารถทำได้ง่าย รวดเร็ว และชัดเจน แม้ว่าจะมีปัญหาเกิดขึ้นบ้าง เวลาที่มีบล็อกซ้อนบล็อกมากเกินไป แต่ปัญหานี้ไม่ว่าจะใช้วิธีการแบ่งบล็อกแบบไหน ก็เกิดขึ้นได้ทั้งนั้น การเลี่ยงการเขียนบล็อกซ้อนบล็อกจึงน่าจะเป็นทางออกที่ดีกว่า
  • Python : imageimageimageimage : แม้ว่าการแบ่งบล็อกด้วย indentation มีข้อดีหลายอย่าง ทั้งง่าย รวดเร็ว เป็นการบังคับให้คนเขียนโปรแกรมเขียนโค้ดที่อ่านง่าย แต่ก็มีอันตรายแอบแฝงหลายอย่าง เช่น การใช้ Tabalator ผสมกับการเว้นวรรค ขนาด indentation ที่ไม่เท่ากัน การเขียนโปรแกรมด้วย Python จึงต้องใช้ Editor ที่มีคุณภาพพอสมควร เพื่อป้องกันปัญหาดังกล่าว อีกทั้งต้องมีการตกลงกันระหว่าคนเขียนโปรแกรมว่าจะใช้ indentation แบบใด
  • Ruby : imageimageimage : การแบ่งบล็อกด้วย begin และ end แม้ว่าจะทำให้อ่านง่ายขึ้น แต่ก็ง่ายกว่าการใช้วงเล็บปีกกาไม่มากนัก Ruby เองก็ไม่ใช่ภาษาที่อ่านง่ายอยู่แล้ว การใช้ begin และ end จึงไม่มีข้อได้เปรียบที่ชัดเจน นอกจากจะทำให้โค้ดยาวขึ้น
5.2 : Loop

  • Java : imageimageimage : การวนลูปของ Java เริ่มต้นเดิมทีได้นำวิธีการของ C มาใช้ จากนั้นก็เพิ่ม Iteration เข้ามา แม้ว่า Iteration จะได้เปรียบ for ธรรมดาอยู่หลายอย่าง แต่ก็ทำให้โค้ดที่ได้อ่านยาก ต้องเขียนโค้ดยาว งง ๆ คนส่วนมากจึงยังคงใช้ for ธรรมดามากกว่า Iteration ใน Java 5 จึงได้มี for-each เพิ่มเข้ามา แต่ก็ยัง for-each ที่ยัง งง ๆ อยู่ ถึงตอนนี้ผมยังคอมไพล์โปรแกรมที่มี for-each ไม่ผ่านเลยครับ
  • Python : imageimageimageimageimage : คอนเซพท์ for-loop ของ Python ถือว่าเป็นคอนเซพท์ที่ดีมาก มีการนำ iteration มาใช้โดยที่คนเขียนไม่ต้องทำความเข้าใจเรื่อง iteration แต่อย่างใด for-each เป็นการวนลูปที่เร็วที่สุดใน Python (เร็วกว่า while) มีฟังก์ชั่น zip() ให้ใช้ ทำให้สามารถใช้ for-each กับข้อมูลสองชุดที่มีขนาดเท่ากันพร้อมกันได้
  • Ruby : imageimageimageimage : คอนเซพท์วนลูปของ Ruby คล้ายคลึงกับของ Python มาก ข้อเสียเดียวที่ผมมองเห็นในการวนลูปของ Ruby คือ incosistence Ruby มีการวนลูปหลายรูปแบบเกินไป ทำให้เกิดความสับสนในการใช้งานในบางครั้ง
5.3 : Container

  • Java : imageimage : ตอนผมเรียน Java อ.ที่สอนท่านชอบบอกว่า Collection-Classes ของ Java มันเจ๋งอย่างไรบ้าง หากเปรียบมวยกับ Array ของ C++ มันก็เจ๋งกว่าจริง ๆ นั่นแหละ แต่มันซับซ้อนมาก ๆ มากเกินไป การทำความเข้าใจ Collection-Classes ของ Java ให้แตกฉาน เป็นศาสตร์ และศิลป์ในตัว ต้องใช้เวลานาน มีจำนวน Classes ให้เลือกใช้มากเกินไป ทั้งที่แต่ละ Class ก็ไม่ต่างกันมาก การนำข้อมูลดิบใส่ลงไปใน Container ก็ไม่ใช่เรื่องง่าย ๆ (ดูตัวออย่างโปรแกรม)
  • Python : imageimageimageimageimage : ใน Python มี Container เพียงสามแบบ คือ [List], {Dictionary} และ (Tuple) สามารถนำไปใช้งานง่าย คลอบคลุมทุกการใช้งาน เจ๋งไหม
  • Ruby : imageimageimageimage : คอยเซพท์ Container ของ Ruby เหมือนของ Python ทุกอย่าง แต่ไม่มี Tuple ให้ใช้

Round 6 : OOP

  • Java : imageimageimageimageimage : Java เป็นภาษาเขียนโปรแกรมที่นำทฤษฎี OOP มาใช้งานได้เต็มรูปแบบ และสมบูรณ์ที่สุด มีเพียง C# เท่านั้น ที่สามารถเทียบชั้นกับ Java ได้ในเรื่องนี้ แต่คำถามคือ เรามีความจำเป็นเพียงใด ในการใช้ OOP เต็มรูปแบบ
  • Python : imageimage : แม้ว่า Python จะรองรับการเขียนโปรแกรมแบบ OOP แต่ผมก็มองว่าเป็น OOP แบบขำ ๆ มีคอนเซพท์ OOP หลายอย่างที่ขาดใน Python (public, private, protected, interface, abstact calss, etc.) อีกทั้งทุกอย่างใน Python ไม่จำเป็ต้องเป็น Object สำหรับคนที่เรียน วิชา Software Engineering หรือ Software Architect มา อาจเริ่มต้นกับ Python ไปไม่ถูกเหมือนกัน แต่สิ่งเหล่านี้ถูกทดแทนได้โดย Meta- , Functional-Programming และ Dynamic Typing
  • Ruby : imageimageimageimageimage : Ruby อาจไม่รองรับ OOP เท่า Java แต่ดีกว่า Python และทำหน้าที่ OOP ได้อย่างไม่ขาดตกบกพร่อง OOP ในส่วนที่ขาดไปของ Ruby สามารถทดแทนได้ด้วย Dynamic Typing

Round 7 : Web-Development

  • Java : imageimageimage : แม้ว่า Java จะสร้างชื่อเสียงของตัวเองด้วยการใช้งานบนอินเตอร์เนต แต่ Framework เกี่ยวกับ Web-Development ของ Java ก็ไม่เคยประสบความสำเร็จอย่างจริงจัง Applet โดนโลกลืมอย่างน่าสงสาร Servlet และ JSP ก็โดน PHP กินส่วนแบ่ง ทิ้งห่างอย่างไม่เห็นฝุ่น เพราะมันดันใช้ยาก และตะกละตะกลาม แม้ว่าจะมี Web-Framework ใหม่ ๆ ออกมาให้ใช้งานมากมาย แต่ก็กินส่วนแบ่งกันเอง และไม่มีนวัตกรรมใหม่ ๆ ที่น่าสนใจ
  • Python : imageimageimageimage : Plone ถือเป็น Killer Application ของ Python และเป็นเครื่องยืนยันได้ถึงคุณภาพด้านนี้ของ Python ได้อย่างดี อีกทั้ง Google และ YouTube ต่างก็หันมาใช้ Python อย่างออกหน้าออกตา สำหรับ Framework ก็มีทั้ง Zope , Django และ Turbo-Gear ให้เลือกใช้ แต่ปัญหามันอยู่ตรงนี้แหละครับ มันมีให้เลือกใช้เยอะเกินไปจน inconsistence
  • Ruby : imageimageimageimageimage : บอกได้คำเดียวครับว่า Rails มันสุดยอด

Round 8 : GUI

  • Java : imageimage : เป็นจุดอ่อนของที่ติดตัว Java มานานนับปี AWT , SWT และ Swing ต่างก็มีจุดอ่อนจุดแข็งของตัวเอง แต่เมื่อเปรียบเทียบทั้งสามกับ GUI ภาษาอื่น บอกได้เลยครับว่ามันห่วย สาเหตุก็เนื่องมาจาก Java มันเป็น Manage Code จึงไม่สามารถดึงพลังของ CPU มาใช้สำหรับ GUI ได้เท่า Native Code
  • Python : imageimageimageimageimage : Python เป็นภาษาเขียนโปรแกรมที่มี GUI ให้เลือกใช้มากที่สุดภาษาหนึ่ง ไม่ว่าจะเป็น Tk, Qt, KDE, GTK, Gnome, wxPython และทุก GUI-Toolkit ต่างก็เป็น GUI-Toolkit ที่มีประสิทธิภาพทั้งสิ้น
  • Ruby : imageimageimageimage : ความเป็นภาษาใหม่ของ Ruby ทำให้ Ruby ยังมี GUI ให้ใช้ไม่มากนัก แต่ไม่นานครับ ตอนนี้นักพัฒนาโปรแกรมของ Ruby ต่างเร่งผลิต Toolkit เหล่านี้ให้เราใช้งานอยู่ อีกสองสามปี ผมคิดว่า GUI ของ Ruby คงเทียบชั้น Python ได้ไม่ยาก

Round 9 : ETC.

9.1 : Tools

  • Java : imageimageimageimageimage : เนื่องจาก Java เป็นภาษาที่เขียนยาก แต่มีคนใช้เยอะ เลยมี IDE ดี ๆ ให้เลือกใช้งานหลากหลายตามไปด้วย สองผู้นำในวงการ IDE ของ Java ได้แก่ NetBeans และ Ecipse ซึ่งทั้งสองเป็น IDE ที่มีคุณภาพสูง แถมทั้งคู่เป็น OpenSource อีกต่างหาก นอกจาก IDE แล้ว Java ยังมีเครื่องมืออื่น ๆ ให้เลือกใช้อย่างจุใจ
  • Python : imageimageimage : IDLE เป็นเครื่องมือมาตรฐานที่ติดตัวมากับ Python อันประกอบด้วย Editor และ Interactive-Python ซึ่งเป็นเครื่องมือที่เหมาะสำหรับงานขั้นพื้นฐานเท่านั้น แม้ว่า Python จะเป็นภาษาที่ค่อนข้างได้รับความนิยม แต่ถือว่ามีเครื่องมือจำพวก IDE ให้เลือกใช้งานน้อยมาก
  • Ruby : imageimage : ความเป็นน้องใหม่ของ Ruby ทำให้ Ruby เสียเปรียบในหลาย ๆ ด้าน ไม่เว้นแม้แต่ด้านเครื่องมือการพัฒนาโปรแกรม โดยส่วนตัวผมคิดว่า ในอนาคตเราก็อาจไม่มีเครื่องมืออลังการอย่าง NetBeans หรือ Eclipse สำหรับ Ruby หรือ Python มาใช้งานกัน เพราะคุณสมบัติของภาษา Script ทำให้เครื่องมือต่าง เป็นเพียงเครื่องอำนวยความสดวก มากกว่าเครื่องมือจำเป็น
9.2 : Platform

  • Java : imageimageimageimageimage : คอนเซพท์ Write once run any where ของ Java นั้น ถือเป็นนวรรตกรรมบรรลือโลก ที่ถึงตอนนี้ยังไม่มีใครมาเทียบรัศมี (.NET ฟังดูดี แต่ในความเป็นจริงมันงี่เง่า เพราะใช้งานได้เฉพาะ OS ความหวังจึงน่าจะอยู่ที่ Mono) Byte-Code ที่ได้ไม่ต้องเปลี่ยนแปลงใด ๆ ก็ใช้งานได้ทุก OS ดังนั้นเรื่อง Plattform ต้องยกให้ Java เขาไป
  • Python : imageimageimageimage : แม้ว่า Python จะรองรับหลาย OS ไม่แพ้ Java แต่โค้ดบางส่วน ก็ต้องมีการแก้ไขเพื่อให้เข้ากับ OS โดยเฉพาะในส่วนที่ใช้ Module os ของ Python อีกทั้งการนำไปใช้งาน ก็เป็นการนำซอร์สโค้ดไปใช้ ไม่ได้เป็น Byte-Code อย่าง Java
  • Ruby : imageimageimageimage : เหมือน Python ครับ :P

Round 10 : Performance

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

Platform

Computer-Modell : Notebook Samsung R55

CPU : Intel Core 2 Duo Centrino T5500

CPU-Freq : 1830 MHz

RAM : 1 GB

OS : Ubuntu 6.04 LTS

Java-1.4 : gij (GNU libgcj) version 4.1.0 (Ubuntu 4.1.0-1ubuntu8)

Java-1.6 : Java(TM) SE Runtime Environment (build 1.6.0-b105)

Python : Python 2.4.3 (#2, Oct 6 2006, 07:52:30) , [GCC 4.0.3 (Ubuntu 4.0.3-1ubuntu5)] on linux2

Ruby : ruby 1.8.4 (2005-12-24) [i486-linux]

หมายเหตุ สำหรับ Java ให้ยึด Java 1.6 เป็นหลักครับ เพราะ Java ของ GNU มันไม่ดีเท่า Java 1.6 ของ Sun แต่สูสี Java 1.4 ของค่ายอื่น ๆ อยู่ (แต่จากการคาดการณ์ ผมคิดว่าคนส่วนใหญ่ยังใช้ Java 1.4 อยู่นะ)

Speed

image

Test Java 1.4 Java 1.6 Python Ruby
Console 12.2 13.9 11.7 12.8
Hash 7.4 2.0 3.6 11.3
IO 1.2 0.7 1.9 6.5
List 2.2 0.4 0.4 5.5
Math 0.7 0.5 0.3 4.4
Real-World-Application 14.8 3.6 0.9 1.5

Memory-usage

image

Test Java 1.4 Java 1.6 Python Ruby
Console 17.9 8.9 17.5 1.6
Hash 17.7 8.9 2.4 40.7
IO 17.9 8.9 2.3 1.6
List 17.9 8.9 2.3 4.1
Math 24.7 22.3 13.9 19.1
Real-World-Application 45.3 37.2 6.2 16.7

Console

ในส่วนนี้ไม่มีใครได้เปรียบเสียเปรียบอย่างได้ชัดในเรื่องความเร็ว แต่การใช้ Memory ต้องยกใช้ Ruby ส่วน Python มีการใช้ Memory มากผิดปกติ สาเหตุน่าจะมาจาก range() ที่ต้องผลิต list ขนาดยักษ์

public class test {
    public static void main(String[] args) {
        for (int i = 0; i < 1000000; i++) {
            System.out.println(i);
        }
    }
}
plain code

for x in range(1000000):
    print x
plain code

1000000.times do |i|
	puts i
end
plain code

Hash

Ruby ทำได้ไม่ดีนัก ทั้งในเรื่องความเร็ว และการใช้ Memory ในทางกลับกัน Python กลับทำได้ดีจนน่าแปลกใจ มีการใช้ Memory ขั้นต่ำสุด ความเร็วห่างจาก Java 1.6 ไม่มากนัก

import java.util.*;
 
public class test {
	public static void main(String[] args) {
		for (int i = 0; i < 6000; i++) {
			Map x = new HashMap();
			for (int j = 0; j < 1000; j++) {
				Integer I=new Integer(i);
				Integer J=new Integer(j);
				x.put(J,I);
				x.get(J);
			}
		}
	}
}
plain code

for i in range(6000):
    x={}
    for j in range(1000):
        x[j]=i
        x[j]
plain code

6000.times do |i|
	x={}
	1000.times do |j|
		x[j] = i
		x[j]
	end
end
plain code

IO

ในเรื่องความเร็ว ไม่มีอะไรน่าแปลกใจ แต่การใช้ Memory ของทุกภาษาอยู่ในขั้นต่ำสุด

import java.io.*;
 
public class test
{
	public static void main(String[] args) {
		try {
			File f = new File("/tmp/scratch");
		PrintWriter pw= new PrintWriter(
				new BufferedWriter(
				new FileWriter(f)));
			for (int i = 0; i < 1000000; i++) {
				pw.print(i);
			}
			pw.close();
		}
		catch(IOException ioe) {
			ioe.printStackTrace();
		}
	}
}
plain code

f=open('/tmp/scratch','wb')
for i in xrange(1000000):
    f.write(str(i))
f.close()
plain code

f = File.new("/tmp/scratch", "w")
1000000.times do |i|
	f.syswrite(i.to_s)
end
f.close
plain code

List

งานนี้มีการใช้ทริกเล็กน้อยสำหรับ Python ทำให้ Python มีความเร็วเทียบเท่า Java-1.6 ขึ้นมาได้ ส่วน Ruby รั้งท้ายเหมือนเดิม

import java.util.*;
 
public class test {
    public static void main(String[] args) {
	List initial = new ArrayList();
	initial.add("a");
	initial.add("b");
	initial.add("c");
	initial.add("d");
	initial.add("e");
	initial.add("f");
	initial.add("g");
 
        for (int i = 0; i < 3000; i++) {
            List v = new ArrayList(initial);
            for (int j = 0; j < 1000; j++) {
                v.add(new Integer(j));
                v.get(j);
            }
        }
    }
}
plain code

a = map(lambda x : ['a','b','c','d','e','f','g']+range(1000),range(3000))
for i in a : i
plain code

3000.times do |i|
	v=['a','b','c','d','e','f','g']
	1000.times do |j|
		v.push(j)
		v[j]
	end
end
plain code

Math

การทดสอบในส่วนนี้ค่อนข้างใกล้เคียงการใช้งานจริงที่ผมใช้อยู่ ที่ตลกคือ การจัดการ Memory และระบบ Typecast ของ Java ตอนแรกผมใช้ Class ArrayList ในการเก็บข้อมูล แต่ก็ต้องมานั่งปวดหัวกับเรื่อง Typecast มากกว่าจะมาจดจ่อกับตัวโปรแกรม เลยต้องหันใช้ double[] แทน แต่ตัว double[] ก็เก็บข้อมูลได้เพียง 2000000 หน่วย และไม่สามารถประกาศตัวแปรขนาด 2000000 หน่วย ติดต่อกันได้เกิน 3 ตัวแปร ไม่งั้นมีเรื่อง ส่วน Ruby ก็ช้าจนน่าเกลียด

import java.lang.Math;
 
public class test {
	public static void main(String[] args) {
		double[] x       = new double[200000];
		double[] gauss   = new double[200000];
		double[] laplace = new double[200000];
		double[] si      = new double[200000];
		double[] sisqr   = new double[200000];
		double[] bp      = new double[200000];
		for(int i = 0 ; i < 200000; i++){
			x[i]       = (i/10000.0)-10.0;
			gauss[i]   = Math.exp(-1.0 * x[i] * x[i]);
			laplace[i] = Math.exp(-1.0 * Math.abs(x[i]));
			si[i]      = Math.sin(x[i]*Math.PI)/(x[i]*Math.PI);
			sisqr[i]   = si[i]*si[i];
			bp[i]      = si[i]*Math.cos(x[i]*100);
		}
	}
}
plain code

import numpy
x = numpy.arange(-10,10,0.0001)
gauss   = numpy.exp(-(x**2))
laplace = numpy.exp(-numpy.abs(x))
si      = numpy.sin(x*numpy.pi)/(numpy.pi)
sisqr   = si**2
bp      = si*numpy.cos(x*100)
plain code

x = []
gauss = []
laplace = []
si = []
sisqr = []
bp = []
200000.times do |i|
	x.push( (i / 10000.0)-10.0 )
	gauss.push( Math.exp(-1.0 * x[i] * x[i]) )
	laplace.push(Math.exp(-1.0 * x[i].abs ))
	si.push(Math.sin(x[i]* Math::PI) / (x[i] * Math::PI))
	sisqr.push(si[i]*si[i])
	bp.push(si[i]*Math.cos(x[i]*100))
end
plain code

Real-World-Application

การทดสอบสุดท้าย ผมคิดว่าน่าจะใกล้เคียงกับการใช้งานจริงมากที่สุด ในการทดสอบนี้ตัวโปรแกรมต้องสร้าง Query เพื่อสอบถามไปยังฐานข้อมูลก่อน เมื่อได้ข้อมูลมาแล้ว จึงเปลี่ยนแปลงรูปแบบข้อมูลด้วย RegEx และ Splitจากนั้นข้อมูลจะถูกเก็บไว้ใน Hash สุดท้ายก็แสดงผลข้อมูลออกมาทาง Console จะเห็นได้ว่า การทดสอบนี้ มีส่วนประกอบที่ใช้ในการเขียนโปรแกรมเวบไซท์ค่อนข้างครบ

ข้อมูลที่อยู่ในฐานข้อมูลก็คือข้อมูลของ BioLawCom.De คำที่ผมใช้หาในฐานข้อมูลคือ ตัวอักษร a ข้อมูลที่ได้มีทั้งสิ้น 690 rows

สิ่งที่น่าเบื่อมากใน Java คือ Typecast และไม่สามารถบรรจุข้อมูลลงใน Hash และ List ได้แบบง่าย ๆ อย่าง Python กว่าผมจะเขียนโปรแกรมนี้ด้วย Java ได้ต้องใช้เวลานานมาก เพราะต้องแก้ไขข้อผิดพลาดเกือบทุกครั้งที่คอมไพล์ ส่วน Ruby และ Python นั้นมีความคล้ายคลึงกันมาก ต่างกันเพียงแค่รายละเอียดเล็กน้อยเท่านั้น

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

(เนื่องจากโค้ดยาวมาก ดังนั้น ผมเลยแยกโค้ดออกมาต่างหาก สามารถดาวน์โหลดได้ที่ Real.zip ครับ)

  • Java : imageimageimage : มีความเร็วเหนือกว่า Ruby และ Python ในเรื่องง่าย ๆ และพื้น ๆ เท่านั้น โปรแกรมที่มีความซับซ้อนมากขึ้น Java จะเริ่มตะกละ และอุ้ยอ้าย การจะเขียน Application ขนาดใหญ่ด้วย Java จึงต้องเตรียมรับเรื่องนี้ไว้ให้ดี
  • Python : imageimageimageimageimage : ต้องยกให้เป็นผู้ชนะในครั้งนี้ครับ เพราะมีความเร็วสูงสุดใน 4 จาก 6 การทดสอบ ในการทดสอบที่ Python ช้ากว่า Java ก็มีความแตกต่างเกิดขึ้นไม่มากนัก
  • Ruby : imageimageimage : แม้ว่า Ruby จะไม่ชนะในการทดสอบใดเลย แต่ก็รักษาตำแหน่งการใช้ Memory น้อยได้โดยตลอด แม้ว่าการทดสอบพื้น ๆ Ruby จะเป็น looser แต่ในการใช้งานจริง โดยเฉพาะ Web-Application Ruby ก็สามารถรักษาความเร็วของตัวเองได้ดีทีเดียว แต่สำหรับโปรแกรมจำพวก Simulation ลืม Ruby ไปได้เลยครับ

Conclusion

ในส่วนของผลรวมคะแนน ผมคิดว่าแต่ละคนคงมีตัวคูณสำหรับคะแนนจากแต่ละยกที่ไม่เท่ากัน สำหรับผม ในเรื่อง Peformance x 3 และ Time to code x 2 และ Python ก็เป็นแชมป์ในครั้งนี้ แต่ทั้งหมดทั้งสิ้นก็เป็นการให้คะแนนโดยผมเพียงคนเดียว ซึ่งอาจไม่ตรงใจหลาย ๆ คน ก็สามารถให้คะแนนแต่ละส่วนกันได้ตามความพอใจครับ

ทั้งนี้และทั้งนั้น ในส่วนของ Performance และ Time to code เป็นส่วนสำคัญมาก และ ผลก็คงเปลี่ยนแปลงจากนี้ไปได้ไม่มาก จากสองส่วนนี้ผมพอจะสรุปได้ว่า Java เป็นอะไรที่ไม่น่าใช้เอาเสียเลย เพราะต้องเสียเวลาเขียนโค้ดนาน แต่โปรแกรมที่ได้กลับไม่มีข้อได้เปรียบใด ๆ

สำหรับบริษัทพัฒนาโปรแกรม หากเลือกใช้ Java เหมือนกับเป็นการเสียเงินลงทุนไป 5-10 เท่าโดยใช่เหตุ ส่วนหนึ่งต้องลงทุนไปกับการเขียนโค้ดที่ต้องใช้เวลานานขึ้น ส่วนหนึ่งต้องเสียไปกับการซื้อเครื่องมือมาช่วยในการพัฒนาโปรแกรม ส่วนหนึ่งต้องเสียไปในการอบรมพนักงาน และอื่น ๆ อีกมากมาย

ข้อได้เปรียบเดียวของ Java คือ เครื่องมือที่พร้อม และมีทฤษฎีรองรับมากมาย ทฤษฎีการวางโครงสร้างระบบส่วนมาก ใช้ Java เป็นภาษาอ้างอิง ในส่วนของทฤษฎีผมมองว่า เราสามารถนำมาปรับใช้กับ Python และ Ruby ได้ไม่ยาก

ส่วน Python นั้นเป็นภาษาที่สามารถนำไปใช้งานได้หลายรูปแบบ ใช้เวลาในการเขียนโค้ดน้อย โปรแกรมที่ได้มี Performance สูง (ว่ากันว่า Python 3000 จะมีความเร็วเพิ่มขึ้นอีก 20-30%) จึงไม่ใช่เรื่องแปลกที่ Python จะเป็นภาษาที่ได้รับความนิยมมากขึ้นเรื่อย ๆ

ข้อเสียเปรียบเดียวของ Ruby คือ เป็นภาษาที่ยังใหม่อยู่ จึงยังอาจไม่พร้อมในหลาย ๆ เรื่อง แต่ Community ของ Ruby ก็โตวันโตคืน ทำให้ Ruby ได้รับการพัฒนาอย่างรวดเร็ว และ อาจเทียบชั้นภาษารุ่นพี่อย่าง Java และ Python ได้ในอนาคตอันใกล้

แม้กระนั้นก็ตาม Web-Application ถือเป็นจุดแข็งที่สำคัญที่สุดของ Ruby คุณภาพของ Ruby on Rails อาจทำให้ Ruby เป็นภาษาที่เข้ามาแทนที่ PHP ในอนาคต แต่เรื่องนี้เราคงด่วนสรุปไม่ได้ เพราะขณะนี้มีโปรแกรมจำนวนมากใช้ PHP การเข้ามาแทนที่ PHP ของ Ruby จึงต้องใช้ระยะเวลา และปัจจัยอื่น ๆ อีกมากมาย

08 Apr 07 | by | tags เขียนโปรแกรม ไอที Java Python Ruby

read 9001

<<สัจธรรม "ม" || กระต่าย(อีสเตอร์) ตื่นตูม กับหมีสีเทาที่เมืองไทย>>

Kesorn

ดีค่ะ บทความดีๆ อย่างงี้ต้องขอส่งต่อให้เพื่อนช่วยกันอ่าน

ตอนนี้เขียน PHP ค่ะ  ไม่เคยคิดจะหาความรู้อย่างลึกซึ้งในเรื่องที่ทำอยู่เลย

เป็นคนที่แย่มั๊ก มาก(แบบว่ารู้ตัว)  เอาแค่ให้มันทำงานได้ก็พอใจ

Java ก็เคยเขียน ก็ทำความเข้าใจตามที่เขาบอกเท่านั้นว่ามันหรูเลิศ

เอาละ  ที่บ่นมาให้ฟัง เอ้ย อ่านเนี่ย  จะได้เตือนตัวเองแหละค่ะ  ว่าต้องขยันมากกว่านี้

 ขอบคุณนะค่ะ  สำหรับบทความดีๆ มาช่วยกระตุ้นต่อมสำนึกในตัว  ให้มันทำงานบ้าง Innocent

22 May 07

Naamchan

ส่วน Python มีการใช้ Memory มากผิดปกติ สาเหตุน่าจะมาจาก range() ที่ต้องผลิต list ขนาดยักษ์

ลองใช้ xrange แทนสิครับ เพราะมันจะไม่สร้าง list ขึ้นมาในทีเดียว

ส่วนใหญ่เห็นด้วยกับบทความนี้มากๆ เลยครับ

23 Jul 07

BST

ทำไมการเปรียบเทียบความเร็วของ PyThon กับ Java ของเวปที่อ้างอิง http://furryland.org/~mikec/bench/

กับเวปนี้ถึงต่างกันลิบลับทั้งที่ใช้โค๊ดเดียวกันอะครับ

ที่โน่นให้ C อันดับ 1 Java อันดับ 2 ส่วน PyThon ที่โหล่

ส่วนที่นี่ใช้โค๊ดการวัดเดียวกันแต่กลายเป็นว่า PyThon อันดับ 1

เพราะตอนแรกผมอ่านเวปนี้แล้วก็อยากใช้ PyThon แต่พอไปอ่านเวปอ้างอิง กลับไปใช้ C++ เหมือนเดิมหรือไม่ก็ Java ดีกว่า

26 Jul 07

wipass

C++ vs Java vs Python vs Ruby : a first impression Executive Summary I am a language agnostic journeyman programmer. I am not a fan of a particular language (I almost said 'fanboy') but thats a bit inflammatory). I just want to write useful programs and have fun doing it. I know C++ and Java pretty well. I did some beginner work in Python and Ruby. I then came up with the following conclusions. But before you flame, read the whole article. Go right to the side-by-side comparison C++ vs Java Java garbage collection is the big productivity gain Java is significantly slower than C++ C++ is (much) harder to code correctly than any of the others Java vs Python/Ruby Python/Ruby interpreted execution and dynamic typing are big productivity gains over Java. Python/Ruby are slower than Java Python/Ruby programs need less extraneous scaffolding (cleaner code) There are two important tradeoffs : [interpreted vs. compiled] and [static vs. dynamic typing] Python vs. Ruby nearly equivalent intro When running various distributions of Linux, I always ran into the choice of KDE or GNOME. There are plenty of advocates on both sides, but there was no overriding authority. Then recently Linus Torvalds came out with a definitive opinion. He took the unequivocal position that KDE is best. Not that he is necessarily the final arbiter of user interfaces, but at least he provides a strong datapoint, and since he is smarter than me and since all the other opinions seem to come from biased sources, I can now pick KDE and feel better about it. Paraphrasing the old IBM criteria, 'no one was ever fired for following a Linus directive'. Heh, after all that it turned out that I wanted to use Ubuntu which works best with GNOME so I ended up with that for now. So 'most practical' won out over 'best'. In the meantime I realized I needed to learn a new language and the current buzz is Python and Ruby. Again I couldn't find a definitive answer of which one is best. From all the buzz, I came up with a vague impression that Ruby is more pure and is set to win in the long run, but that Python is currently more practical for now. And Google uses Python, which is a significant datapoint. They aren't idiots over there. To see what I could figure out myself, I decided to code up something in Java, then port it to Python and Ruby and see how I felt about each, and try to identify where the big wins are for each language. One caveat. If something significant is missing from a language, like garbage collection, then I don't want to hear a response that says "well, if you use XYZ unsupported library, or you do ABC convoluted technique, then you can do the same thing in [put language name here]". I am trying to evaluate the STANDARD here, since of course you can probably do anything in any language including assembler if you work hard enough. And the problem with using a nonstandard library is not just the extra integration work, it's that you are basing your code on something that may fall by the wayside later on and then you are stuck. Sometimes it's worth it but that has to be proven on a case-by-case basis as far as I am concerned. history I started in C in 1985, learned C++ in 1990 (Zortech C++) and have been using it ever since. I learned Java in the mid-90's when it was first coming out, and found three big win's for Java over C++: Garbage collection, portability and simplicity. Garbage collection and simplicity created big productivity gains, and portability is portability. Not having done a garbage collected language before, the productivity gain was readily apparent. The simplicity of Java over C++ was really nice. When coding C++, I needed Meyer's Effective C++ on my desk at all times to be sure I wasn't invoking some weird type coercion or copy constructor/assignment operator anomaly. And don't even start with templates. With Java I never needed that because it is just simpler. And the Java libraries were more comprehensive and string handling was easier. So in general I was more productive coding away in Java. I still liked C++ but it seems that when programming C++, the fun is in figuring out the language and library , like solving a puzzle. That leaves less time to spend on solving the application domain problem. the code The attached code samples are implementations of a Red-Black tree algorithm adapted from descriptions in "Algorithms in C++", Sedgewick and "Introduction To Algorithms",Cormen/Leiserson/Rivest. I picked this because it was short but had some complexity. code notes and disclaimers: commenting is sparser than usual to avoid obscuring code I probably made some convention errors in Python and Ruby due to ignorance of the proper idioms all these programs compile and/or run without warnings and output the same result I believe the programs to be correct. there may be bugs but if so they are in all 3 versions Java 5.0 SDK,Python 2.4, Ruby 1.8.3, C++ Microsoft Visual C++ 2005 Compare side by side Java implementation Python implementation Ruby implementation C++ implementation the source zip file porting It was surprisingly easy to port the Java code to Python and then port the Python to Ruby. A lot of it was regular expression search and replace, getting some naming conventions right and adapting to a few language differences. During the porting process, the two big gotchas I ran into were Python block indenting errors and Ruby's horrible compiler diagnostics. Porting the Java code to C++ was much more a hassle. I attempted to make use of as much static type checking mechanisms as I could. In Java I used generics for the tree, and in C++ I used templates for the container and 'const' where appropriate. The big gotchas on porting to C++ were: The dichotomy between primitive types and objects in C++ is much more pronounced even than Java (and Java is worse off than Python or Ruby). This dichotomy makes it hard to write a class that supports both primitives and objects. My implementation might need some fixups to work with objects rather than 'int'. Java,Ruby and Python all use a consistent reference only scheme to refer to objects which are always on the heap or equivalent. In C++, you can have a statically declared objects, a pointer to an object, or a reference to an object, each with features and limitations. A C++ 'reference' is not the same thing as a reference in the other languages. C++ really wants you to use pointers. These alternatives means that when you write something in C++ you have to come up with a consistent strategy for using the 3 types of object access, and your strategy might not be the same as what others prefer. There is 'more than one way to do it'. The lack of built-in mechanisms or even just conventions for operations that should be common across types means you have to make things up. Like converting a type to string representation. All the other languages have support of one kind or another but in C++ you have to make up your own convention Maybe its just me, but C++ always leaves you wondering what you might have done wrong. Its hard to tell. If you read Meyer's Effective C++ you see that there are numerous detailed infrastructure things like constructors and assignment operators that you have to get exactly right or things fail at runtime. C++ is really hard to get right, and I never feel totally secure that I did it properly In my opinion (and I have written a lot of C++), use C++ only where you have to for compatibility or performance reasons, or where you arbitrarily decide that you would rather use C++ because its more fun because its harder. As Tom Cargill (a noted C++ guy) said, "If you think C++ is not overly complicated, just what is a protected abstract virtual base pure virtual private destructor and when was the last time you needed one?". python block indenting It took me a while to get my editor (JEdit) happy with Python and getting to not use tabs. Fortunately I never screwed up the file so bad that the code didn't work but I always had an unpleasant uncertainty about the indentation simmering in the background. Some (or all) of this may be prejudice. I really liked braces better than either Ruby Do-End or Python indenting, at least when I was coding. On the other hand, a properly indented Python file looks much much cleaner and is easier to read than any of the others because you don't need all the block closing symbols. However the explicit 'self' argument makes it look less clean than it could. ruby syntax errors Many of the compiler diagnostics I got during the Ruby porting simply said "syntax error" and gave the line number for the last line in the file. Great. I spent a lot of time doing binary searches on my code to find the error source. The visitor pattern One thing I did differently in each language was try to adapt a 'Visitor' pattern (for traversing the tree) to the preferred idiom for each language. You could of course simply code up a Visitor class that is nearly identical for each language, but instead I did the following. Java : one scheme : an anonymous class implementing a predefined interface. Python : two schemes : a named class similar to Java and just a named function passed in as a parameter. Ruby : two schemes : a lamba anonymous function, and a Ruby block implementation The Java and C++ approaches give you static type checking but takes a lot more cruft to get going. I found the Python named function parameter very convenient. But it doesn't carry any state so if you need state then you use a class. Surprisingly, I found the Ruby lambda easier to understand and implement than the Ruby 'block'. That is because my traversal algorithm is recursive, and the lambda just gets passed around as a parameter (like the python named function parameter). I didn't exploit the full potential of a lambda closure. The Ruby block scheme (pun not intended) requires some tricky syntax in the recursive calls, and I could not find a good explanation of how to handle recursive use of blocks in the Ruby documentation. I found a single web hit with an example and after fiddling with it I got it to work. I think I understand them now but it is still a bit fuzzy. I mean, I know what to do now but it takes some concentration to figure out what exactly is happening and why the code looks like it does. I found that viewing a Ruby block as a co-routine (per the documentation) and not as a subroutine to be the best way to understand the whole thing. All that said about the Visitors, I am a Python/Ruby novice so possibly I did things the hard way :) interpreted vs. compiled There has always been this tradeoff. In fact, the Python/Ruby vs. Java performance controversy sounds a lot like the C/Assembler/Forth discussions in the embedded systems world of the early 1980's. Forth was interpreted, it didn't need a compile cycle and it had (supposedly) productivity enhancing features that C didn't have. Development cycles were much shorter with Forth. Performance was not as fast as C or assembler but was close. The drawback of Forth was the weirdness of the language. C won out and Forth went to the dark corner of mostly forgotten languages. Interpreted languages give you a much quicker development cycle, especially on big programs. There is no doubting that. Its simply a tradeoff of execution speed vs. productivity. Some applications need the speed. I think it is a premature optimization to say the "I like C/Java better than Python/Ruby because they execute faster". Interpreted is better if you can get it. When I was testing the code I experienced the advantage of interpreted. I didn't really measure performance but other sources show the differences. But since Python/Ruby seem to interface to C/C++ pretty readily, I would be very comfortable working in the interpreted world and descending into the netherworld of compiled C/C++ when required. Yes, Python is actually compiled for a VM but you don't have an explicit compile operation so it acts to the user like an interpreted language. static vs. dynamic type checking Ok, I like the productivity increase provided by dynamic typing because it eliminates a lot of scaffolding. I found it quite interesting to see errors pop out at runtime that would normally be compile time in C++/Java. These runtime errors were obviously influenced by the paths taken in the test program (or how far it got before it barfed). For a given run, I clearly wasn't seeing all the instances of this class of errors as I would have with static type checking. Coming from a statically typed language background, my gut says that dynamic typing creates a risk. The Python/Ruby bloggers say that if you just unit test properly, then there is no problem. Brucke Eckel has a well reasoned essay on the issue. I would argue that expecting unit test to catch typing errors has two issues: in a really big system, its hard to test exhaustively testing for type correctness makes the programmer do the work that a computer could do We static typers may be wrong. I had a similar experience moving from PVCS to Subversion version control. Oh, My, God, no locking? The code will be completely ruined in a week. But it turned out to be a non-issue and Subversion added so much less friction to the development cycle that productivity was improved maybe 10%. The collective good experience overrode the predjudice based theoretical 'proof'. The same argument can be made for dynamic vs. static typing. I wouldn't mind a separate 'lint' tool for Python/Ruby (is it possible?). I use lint for C/C++ religiously. The whole compiled language community is moving towards more static type checking (Java Generics, for example) rather than less. Are they all idiots? (don't answer that) My conclusion is that dynamic 'duck' typing is more productive, more pleasant, gives cleaner looking code but it incurs a risk that you will get a runtime type exception in your application at some later date. The risk is there, quit denying it. the results These results are meant to cover issues I noticed in the porting/testing I did. Not an overall evaluation. If I mention stuff that I didn't run into first hand, then throw that out. C++ vs Java Garbage collection is THE big win for Java. Java simplicity over C++ complexity is a big win for Java. C++ is much harder to write and get right than Java or any of the other choices C/C++ is way faster than Java Language scaffolding requirements are similar for both C/C++ is the only way to go for low level systems programming. Java vs Python/Ruby interpreted vs. compiled is a big productivity win for Python/Ruby dynamic typing is a big productivity win for Python/Ruby Java is way faster than Python or Ruby minimal scaffolding is a big productivity win for Python/Ruby. Makes programming more pleasant not to have to build all the infrastructure. mostly first class functions a big win for Python/Ruby. built-in lists/arrays and hashes/dictionaries a big win over Java [] and library based collections. Java 5.0 fixes some of this but in Java collections still seem tacked on rather than integrated. dynamic code loading in Python/Ruby is a big win. Yes you can do it in Java but again, the cruft. Ruby OO completeness over Java dichotomy between primitive types vs. objects is a big win for Ruby, less so for Python. There is some weirdness in Python and Ruby lexical scoping of names. The documentation for each has several warnings about edge cases where names don't bind in the expected way. This gives me a queasy feeling although in practice it may not matter. Another win for static type checking. Java 'Comparable' interface ugly compared to Python/Ruby built in comparison mechanisms that require only that a single function be implemented to get the full set of comparison operators. An example of excess Java scaffolding. lack of multiline comments in Python/Ruby was annoying TRADEOFFS static typing is a correctness win for Java, especially with Generics in 5.0. The C++/Java trend is toward stronger static type checking, not less dynamic typing is a productivity win for Python/Ruby at the cost of some risk interpreted vs. compiled trades off execution speed for shorter development cycles. Python vs Ruby none of these are that important PYTHON WINS Ruby's compiler/runtime error messages were mostly 'syntax error' with no help. in many cases almost useless Why does Ruby use rescue/ensure when the rest of the world has settled on try/catch/finally? I mean, its an arbitrary choice so why not follow the general convention? Once the indentation is correct, a Python program is the cleanest looking RUBY WINS somewhat uneasy over Python indenting vs. Ruby explicit 'end'. probably a predjudice. Python requirement for explicit 'self' parameter to methods and instance variable access is very annoying Ruby OO completeness is a win over Python. EQUIVALENT Ruby blocks/lambda/yield seemed more or less equivalent (to me) to Python's named class or function. Didn't seem a big win to be able to write an anonymous function inline. In fact, one could argue that anonymous classes/functions/lambdas reduce testability because they can't be tested independently of the containing code. But on the other hand I wasn't using lambdas in the most complete sense, in which they can act on the containing environment in a way that a named function can't. A final thought on C++. To me the C++ Standard Template Library is distinguished from the other language libraries in that it seems to be much more mathematically thought out. The containers and algorithms in the STL all have explicit runtime complexity guarantees. There seems to be much more computer science in the STL than in the other language libraries. Java is sort of like that, whereas Ruby and Python libraries seem much more ad-hoc. That probably has a lot to do with their open community driven approach to libraries. I really like how the STL was thought out and designed. conclusion Java is more productive than C/C++. Use C/C++ only when speed or bare metal access is called for. Python/Ruby is more productive than Java and more pleasant to code in. There is a big question on static vs. dynamic typing. I contend that static typing has to be better for the purposes of program correctness, but the required cruft reduces productivity. If actual practice in large systems shows that in fact runtime typing errors don't occur often and are worth the productivity tradeoff, then I will bow to dynamic typing. I can't come up with a definitive answer to Python vs. Ruby. They seem very equivalent. Would choose based on practicality in a given situation. My general feeling was that Python annoyed me in ways that Ruby didn't, but I think those annoyances would disappear if I was using Python all the time.

20 Jul 09

wipass

C++ vs Java Garbage collection is THE big win for Java. Java simplicity over C++ complexity is a big win for Java. C++ is much harder to write and get right than Java or any of the other choices C/C++ is way faster than Java Language scaffolding requirements are similar for both C/C++ is the only way to go for low level systems programming. Java vs Python/Ruby interpreted vs. compiled is a big productivity win for Python/Ruby dynamic typing is a big productivity win for Python/Ruby Java is way faster than Python or Ruby minimal scaffolding is a big productivity win for Python/Ruby. Makes programming more pleasant not to have to build all the infrastructure. mostly first class functions a big win for Python/Ruby. built-in lists/arrays and hashes/dictionaries a big win over Java [] and library based collections. Java 5.0 fixes some of this but in Java collections still seem tacked on rather than integrated. dynamic code loading in Python/Ruby is a big win. Yes you can do it in Java but again, the cruft. Ruby OO completeness over Java dichotomy between primitive types vs. objects is a big win for Ruby, less so for Python. There is some weirdness in Python and Ruby lexical scoping of names. The documentation for each has several warnings about edge cases where names don't bind in the expected way. This gives me a queasy feeling although in practice it may not matter. Another win for static type checking. Java 'Comparable' interface ugly compared to Python/Ruby built in comparison mechanisms that require only that a single function be implemented to get the full set of comparison operators. An example of excess Java scaffolding. lack of multiline comments in Python/Ruby was annoying TRADEOFFS static typing is a correctness win for Java, especially with Generics in 5.0. The C++/Java trend is toward stronger static type checking, not less dynamic typing is a productivity win for Python/Ruby at the cost of some risk interpreted vs. compiled trades off execution speed for shorter development cycles.

20 Jul 09

wipass

Java / C++ Rock : The performance of Java and C++ was head and shoulders beyond other languages (nearly 100 times faster). My thought is that while a difference of 10x was only to be expected - this difference was just way too massive Java is faster than C++ : Though I had read about other microbenchmarks reaching the same conclusions, it is the first time I actually ran one where Java was faster. There are many others I have run where C++ beats Java quite handsomely. More importantly - the performance of C++ worsened by almost 40% once I added code which started freeing memory that was being allocated (there’s still a small memory leak in the code - there is no Chain destructor which will clean up first). I would later definitely want to look at the impact of garbage collection in this context, and whether the Java garbage collector simply was much faster than the hand crafted new - delete calls in C++. Update:Using the customised memory management (which is not used in any of the other examples) but the same algorithm as in the code written by Alberto, C++ is much faster than Java Ruby 1.9 is twice as fast as Python : While it has been known for a while Ruby 1.9 is much faster than Ruby 1.8.6, heres one more supporting data point. I was expecting ruby 1.9 to give python a run for its performance money. But at least in this particular context it seems to be much much faster. JRuby is faster than Ruby : Even ruby 1.9. Very interesting indeed. Jython still has some catching up to do : Though in the ballpark as the other languages, it was the slowest in the pack. Overhead of dynamism is dominant : I have no idea if JRuby ran much faster because of the java bytecode or because of its implementation (though its performance was not even remotely close to that of Java). However even after I compiled groovy code, to java bytecode, it still ran much slower than python and ruby. It seems the overhead of supporting dynamic constructs is much more dominant than any benefits that one gets out of compilation (whether to java byte code or to intermediate compiled files). I think the argument that because something compiles to java bytecode it is likely to be fast should be looked at a little carefully. PHP stays at the rear end : Though I benchmarked PHP for the first time, I wasn’t completely surprised by the fact that PHP could only manage to be faster than Jython.

20 Jul 09

ความคิดเห็น (click here to comment)

Search

Navigation

รวมลิงก์น่าสนใจ

ความเคลื่อนไหว

Login

name password

ลืมรหัสผ่าน