ฉันพบว่า Xamarin อ้างว่าการใช้งานโมโนบน Android และแอพที่รวบรวมด้วย C # นั้นเร็วกว่าโค้ด Java ใครบ้างที่มีการวัดประสิทธิภาพจริง ๆ บนโค้ด Java และ C # ที่คล้ายกันมากบนแพลตฟอร์ม Android ที่แตกต่างกันเพื่อตรวจสอบการอ้างสิทธิ์ดังกล่าวสามารถโพสต์โค้ดและผลลัพธ์ได้หรือไม่
เพิ่มเมื่อวันที่ 18 มิถุนายน 2013
เนื่องจากไม่มีคำตอบและไม่สามารถหามาตรฐานดังกล่าวที่ทำโดยผู้อื่นได้ตัดสินใจทำการทดสอบของฉันเอง น่าเสียดายที่คำถามของฉันยังคง "ถูกล็อก" ดังนั้นฉันจึงไม่สามารถโพสต์สิ่งนี้เป็นคำตอบได้เพียงแก้ไขคำถามเท่านั้น โปรดลงคะแนนเพื่อเปิดคำถามนี้อีกครั้ง สำหรับ C # ฉันใช้ Xamarin.Android Ver 4.7.09001 (เบต้า) ซอร์สโค้ดข้อมูลทั้งหมดที่ฉันใช้สำหรับการทดสอบและรวบรวมแพ็คเกจ APK อยู่ใน GitHub:
Java: https://github.com/gregko/TtsSetup_Java
ค#: https://github.com/gregko/TtsSetup_C_sharp
หากมีคนต้องการทดสอบซ้ำบนอุปกรณ์หรือโปรแกรมจำลองอื่น ๆ ฉันก็สนใจที่จะเรียนรู้ผลลัพธ์เช่นกัน
ผลลัพธ์จากการทดสอบของฉัน
ฉันโอนย้ายคลาสตัวแยกประโยคเป็น C # (จากแอป @Voice Aloud Reader) ของฉันและรันการทดสอบบางไฟล์ในไฟล์ HTML 10 ไฟล์เป็นภาษาอังกฤษรัสเซียฝรั่งเศสโปแลนด์และเช็ก การดำเนินการแต่ละครั้งมีการดำเนินการ 5 ครั้งในไฟล์ทั้ง 10 ไฟล์และเวลารวมสำหรับอุปกรณ์ต่าง ๆ 3 ตัวและตัวจำลองหนึ่งตัวจะถูกโพสต์ไว้ด้านล่าง ฉันทดสอบบิลด์ "Release" เท่านั้นโดยไม่เปิดใช้งานการดีบัก
HTC Nexus One Android 2.3.7 (API 10) - CyanogenMod ROM
Java: เวลาทั้งหมด (5 รัน): 12361 ms, รวมไฟล์ที่อ่านได้: 13304 ms
C #: เวลารวมทั้งหมด (5 วิ่ง): 17504 ms, รวมการอ่านไฟล์: 17956 ms
Samsung Galaxy S2 SGH-I777 (Android 4.0.4, API 15) - CyanogenMod ROM
Java: เวลาทั้งหมด (5 รัน): 8947 มิลลิวินาที, รวมไฟล์ที่อ่านได้: 9186 ms
C #: เวลารวมทั้งหมด (5 วิ่ง): 9884 ms, รวมการอ่านไฟล์: 10247 ms
Samsung GT-N7100 (Android 4.1.1 JellyBean, API 16) - Samsung ROM
Java: เวลาทั้งหมด (5 รัน): 9742 ms, รวมไฟล์ที่อ่านได้: 10111 ms
C #: เวลารวมทั้งหมด (5 วิ่ง): 10459 ms, รวมการอ่านไฟล์: 10696 ms
Emulator - Intel (Android 4.2, API 17)
Java: เวลาทั้งหมด (5 รัน): 2699 ms, รวมไฟล์ที่อ่านได้: 3127 ms
C #: เวลารวมทั้งหมด (5 วิ่ง): 2049 ms, รวมไฟล์ที่อ่านได้: 2182 ms
Emulator - Intel (Android 2.3.7, API 10)
Java: เวลาทั้งหมด (5 รัน): 2992 ms, รวมไฟล์ที่อ่านได้: 3591 ms
C #: เวลารวมทั้งหมด (5 วิ่ง): 2049 ms, รวมไฟล์ที่อ่านได้: 2257 ms
Emulator - Arm (Android 4.0.4, API 15)
Java: เวลาทั้งหมด (5 รัน): 41751 ms, รวมไฟล์ที่อ่านได้: 43866 ms
C #: เวลารวมทั้งหมด (5 การวิ่ง): 44136 ms, รวมการอ่านไฟล์: 45109 ms
การอภิปรายสั้น ๆ
รหัสทดสอบของฉันมีการแยกวิเคราะห์ข้อความเป็นส่วนใหญ่การแทนที่และการค้นหา Regex อาจเป็นรหัสอื่น ๆ (เช่นการดำเนินการเป็นตัวเลขมากกว่า) ผลลัพธ์จะแตกต่างกัน ในอุปกรณ์ทั้งหมดที่มีโปรเซสเซอร์ ARM, Java ทำได้ดีกว่ารหัส Xamarin C # ความแตกต่างที่ใหญ่ที่สุดอยู่ภายใต้ Android 2.3 ซึ่งรหัส C # ทำงานที่ประมาณ 70% ของความเร็ว Java
บนตัวเลียนแบบ Intel (ด้วยเทคโนโลยี Intel HAX ตัวเลียนแบบทำงานในโหมด virt รวดเร็ว) รหัส Xamarin C # จะรันโค้ดตัวอย่างของฉันเร็วกว่า Java - เร็วขึ้นประมาณ 1.35 เท่า บางทีโค้ดและไลบรารีเครื่องเสมือนของ Mono นั้นได้รับการปรับให้เหมาะสมกับ Intel มากกว่า ARM หรือไม่?
แก้ไข 8 กรกฎาคม 2013
ฉันเพิ่งติดตั้งตัวจำลอง Genymotion Android ซึ่งทำงานใน Oracle VirtualBox และอีกครั้งอันนี้ใช้หน่วยประมวลผล Intel ดั้งเดิมไม่ใช่การจำลองหน่วยประมวลผล ARM เช่นเดียวกับ Intel HAX emulator, C # ทำงานที่นี่เร็วกว่ามาก นี่คือผลลัพธ์ของฉัน:
เครื่องมือจำลองจีโนม - Intel (Android 4.1.1, API 16)
Java: เวลาทั้งหมด (5 รัน): 2069 ms, รวมไฟล์ที่อ่านได้: 2248 ms
C #: เวลารวมทั้งหมด (5 วิ่ง): 1543 ms, รวมไฟล์ที่อ่านได้: 1642 ms
ฉันสังเกตเห็นว่ามีการอัพเดท Xamarin.Android beta รุ่น 4.7.11 พร้อมด้วยบันทึกประจำรุ่นที่กล่าวถึงการเปลี่ยนแปลงบางอย่างในรันไทม์ Mono เช่นกัน ตัดสินใจที่จะทดสอบอุปกรณ์ ARM อย่างรวดเร็วและแปลกใจใหญ่ - ปรับปรุงหมายเลข C #:
BN Nook XD +, ARM (Android 4.0)
Java: เวลาทั้งหมด (5 รัน): 8103 ms, รวมไฟล์ที่อ่านได้: 8569 ms
C #: เวลารวมทั้งหมด (5 วิ่ง): 7951 ms, รวมไฟล์อ่าน: 8161 ms
ว้าว! ตอนนี้ C # ดีกว่า Java ใช่ไหม ตัดสินใจที่จะทดสอบซ้ำบน Galaxy Note 2 ของฉัน:
Samsung Galaxy Note 2 - ARM (Android 4.1.1)
Java: เวลารวมทั้งหมด (5 วิ่ง): 9675 ms, โดยมีการอ่านไฟล์ทั้งหมด: 10028 ms
C #: เวลารวมทั้งหมด (5 วิ่ง): 9911 ms, รวมไฟล์ที่อ่านได้: 10104 ms
ที่นี่ C # ดูเหมือนว่าจะช้าลงเล็กน้อยเท่านั้น แต่ตัวเลขเหล่านี้ทำให้ฉันหยุดชั่วคราว: ทำไมเวลานานกว่า Nook HD + ถึงแม้ว่า Note 2 จะมีโปรเซสเซอร์ที่เร็วกว่า? คำตอบ: โหมดประหยัดพลังงาน ในนุ๊กมันถูกปิดการใช้งานในหมายเหตุ 2 - เปิดใช้งาน ตัดสินใจที่จะทดสอบด้วยโหมดประหยัดพลังงานถูกปิดการใช้งาน (เช่นเดียวกับที่เปิดใช้งานและยัง จำกัด ความเร็วโปรเซสเซอร์):
Samsung Galaxy Note 2 - ARM (Android 4.1.1) ปิดการใช้งานการประหยัดพลังงาน
Java: เวลาทั้งหมด (5 รัน): 7153 ms, รวมไฟล์ที่อ่านได้: 7459 ms
C #: เวลารวมทั้งหมด (5 วิ่ง): 6906 ms, รวมการอ่านไฟล์: 7070 ms
ตอนนี้น่าแปลกใจที่ C # นั้นเร็วกว่า Java บนโปรเซสเซอร์ ARM เล็กน้อยเช่นกัน การปรับปรุงครั้งใหญ่!
แก้ไข 12 กรกฎาคม 2556
เราทุกคนรู้ว่าไม่มีอะไรเต้นรหัสพื้นเมืองสำหรับความเร็วและฉันไม่พอใจกับประสิทธิภาพของตัวแยกประโยคใน Java หรือ C # โดยเฉพาะอย่างยิ่งที่ฉันต้องปรับปรุงมัน (และทำให้ช้าลง) ตัดสินใจที่จะเขียนใหม่ใน C ++ นี่คือไฟล์เล็ก ๆ (เช่นชุดไฟล์ที่เล็กกว่าการทดสอบก่อนหน้านี้ด้วยเหตุผลอื่น ๆ ) เปรียบเทียบความเร็วของ native กับ Java บน Galaxy Note 2 ของฉันโดยที่โหมดประหยัดพลังงานถูกปิดใช้งาน:
Java: เวลาทั้งหมด (5 รัน): 3292 ms, โดยรวมไฟล์ที่อ่านได้: 3454 ms
เนี้ยบทั่วไป: เวลาทั้งหมด (5 วิ่ง): 537 มิลลิวินาทีโดยรวมการอ่านไฟล์: 657 มิลลิวินาที
แขนพื้นเมือง: ผลรวมทั้งหมด (5 รอบ): 458 มิลลิวินาที, รวมไฟล์ที่อ่านได้: 587 มิลลิวินาที
ดูเหมือนว่าสำหรับการทดสอบเฉพาะของฉันโค้ดเนทีฟคือเร็วกว่า Java 6-7 เท่า Caveat: ไม่สามารถใช้ std :: regex class บน Android ได้ดังนั้นจึงต้องเขียนกิจวัตรพิเศษของตัวเองเพื่อค้นหาการแบ่งย่อหน้าหรือแท็ก html การทดสอบเริ่มต้นของรหัสเดียวกันบนพีซีโดยใช้ regex นั้นเร็วกว่า Java ประมาณ 4 ถึง 5 เท่า
วุ้ย ปลุกความทรงจำใหม่ด้วยพอยน์เตอร์ char * หรือ wchar * อีกครั้งฉันก็อายุน้อยกว่า 20 ปีทันที! :)
แก้ไขวันที่ 15 กรกฎาคม 2556
(โปรดดูด้านล่างพร้อมการแก้ไขของ 7/30/2556 เพื่อผลลัพธ์ที่ดียิ่งขึ้นด้วย Dot42)
ฉันจัดการพอร์ตการทดสอบ C # ของฉันไปยัง Dot42 (รุ่น 1.0.1.71 เบต้า) ซึ่งเป็นแพลตฟอร์ม C # อีกอันสำหรับ Android ผลลัพธ์เบื้องต้นแสดงว่ารหัส Dot42 นั้นช้ากว่า Xamarin C # (v. 4.7.11) ประมาณ 3 เท่า (3 เท่า) บนตัวจำลอง Intel Android ปัญหาหนึ่งคือคลาส System.Text.RegularExpressions ใน Dot42 ไม่มีฟังก์ชัน Split () ที่ฉันใช้ในการทดสอบ Xamarin ดังนั้นฉันจึงใช้คลาส Java.Util.Regex แทนและ Java.Util.Regex.Pattern.Split () ดังนั้นในสถานที่นี้โดยเฉพาะในรหัสมีความแตกต่างเล็กน้อยนี้ ไม่ควรเป็นปัญหาใหญ่ แต่ Dot42 คอมไพล์กับโค้ด Dalvik (DEX) ดังนั้นจึงร่วมมือกับ Java บน Android แบบดั้งเดิมไม่ต้องการ interop ราคาแพงจาก C # ถึง Java เช่น Xamarin
สำหรับการเปรียบเทียบฉันยังทำการทดสอบบนอุปกรณ์ ARM - ที่นี่รหัส Dot42 คือ "เท่านั้น" 2x ช้ากว่า Xamarin C # นี่คือผลลัพธ์ของฉัน:
HTC Nexus One Android 2.3.7 (ARM)
Java: เวลาทั้งหมด (5 รัน): 12187 ms, รวมการอ่านไฟล์: 13200 ms
Xamarin C #: เวลารวมทั้งหมด (5 วิ่ง): 13935 ms, รวมการอ่านไฟล์: 14465 ms
Dot42 C #: เวลารวมทั้งหมด (5 วิ่ง): 26000 ms, รวมไฟล์ที่อ่านได้: 27168 ms
Samsung Galaxy Note 2, Android 4.1.1 (ARM)
Java: เวลารวมทั้งหมด (5 วิ่ง): 6895 ms, โดยมีการอ่านไฟล์ทั้งหมด: 7275 ms
Xamarin C #: เวลารวมทั้งหมด (5 วิ่ง): 6466 ms, รวมการอ่านไฟล์: 6720 ms
Dot42 C #: เวลารวมทั้งหมด (5 วิ่ง): 11185 ms พร้อมกับอ่านไฟล์ทั้งหมด: 11843 ms
Intel emulator, Android 4.2 (x86)
Java: เวลาทั้งหมด (5 รัน): 2389 ms, รวมไฟล์ที่อ่านได้: 2770 ms
Xamarin C #: เวลารวมทั้งหมด (5 วิ่ง): 1748 ms, รวมไฟล์อ่านทั้งหมด: 1933 ms
Dot42 C #: เวลารวมทั้งหมด (5 วิ่ง): 5150 ms, รวมไฟล์ที่อ่านได้: 5459 ms
สำหรับฉันมันน่าสนใจที่จะทราบว่า Xamarin C # นั้นเร็วกว่า Java เล็กน้อยบนอุปกรณ์ ARM รุ่นใหม่และช้ากว่า Nexus One รุ่นเก่าเล็กน้อย หากใครต้องการที่จะทำการทดสอบเหล่านี้เช่นกันโปรดแจ้งให้เราทราบและฉันจะอัปเดตแหล่งข้อมูลบน GitHub มันจะน่าสนใจเป็นพิเศษหากเห็นผลลัพธ์จากอุปกรณ์ Android จริงที่มีโปรเซสเซอร์ Intel
อัพเดท 7/26/2013
เพียงอัปเดตด่วนรวบรวมใหม่โดยแอพเบนช์มาร์คมาตรฐานด้วย Xamarin.Android 4.8 และอัปเดต dot42 1.0.1.72 ที่เผยแพร่ในวันนี้ - ไม่มีการเปลี่ยนแปลงที่สำคัญจากผลลัพธ์ที่รายงานก่อนหน้านี้
อัพเดท 7/30/2556 - ผลลัพธ์ที่ดีกว่าสำหรับ dot42
ทดสอบ Dot42 อีกครั้งกับพอร์ตของ Robert (จากผู้ผลิต dot42) ของโค้ด Java ของฉันไปยัง C # ใน C # พอร์ตของฉันเสร็จสิ้นในตอนแรกสำหรับ Xamarin ฉันแทนที่คลาส Java ดั้งเดิมบางตัวเช่น ListArray ด้วย List class native เป็น C # เป็นต้น Robert ไม่ได้มีซอร์สโค้ด Dot42 ของฉันดังนั้นเขาจึงย้ายพอร์ตอีกครั้งจาก Java และใช้คลาส Java ดั้งเดิมใน สถานที่ดังกล่าวซึ่งเป็นประโยชน์ต่อ Dot42 ฉันคิดว่าเพราะมันทำงานใน Dalvik VM เช่น Java และไม่ใช่ใน Mono เช่น Xamarin ตอนนี้ผลลัพธ์ของ Dot42 นั้นดีกว่ามาก นี่คือบันทึกจากการทดสอบของฉัน:
7/30/2013 - การทดสอบ Dot42 พร้อมคลาส Java เพิ่มเติมใน Dot42 C #
Intel emulator, Android 4.2
Dot42 รหัสของ Greg โดยใช้ StringBuilder.Replace () (ใน Xamarin):
เวลารวมทั้งหมด (5 รอบ): 3646 มิลลิวินาที, รวมไฟล์ที่อ่านได้: 3830 มิลลิวินาทีDot42, รหัสของ Greg โดยใช้ String แทนที่ () (เช่นเดียวกับใน Java และ Robert's code):
ผลรวมทั้งหมด (5 รอบการทำงาน): 3027 ms, อ่านไฟล์ได้ทั้งหมด: 3206 msDot42, รหัสโรเบิร์ต:
ระยะเวลาทั้งหมด (5 รอบ): 1781 มิลลิวินาที, รวมการอ่านไฟล์: 1999 มิลลิวินาทีXamarin:
เวลารวมทั้งหมด (5 วิ่ง): 1373 มิลลิวินาทีโดยรวมการอ่านไฟล์: 1505 มิลลิวินาทีJava:
เวลาทั้งหมด (5 รัน): 1841 มิลลิวินาที, รวมไฟล์ที่อ่านได้: 2044 มิลลิวินาทีARM, Samsung Galaxy Note 2, ประหยัดพลังงาน, Android 4.1.1
Dot42 รหัสของ Greg โดยใช้ StringBuilder.Replace () (ใน Xamarin):
เวลาทั้งหมด (5 วิ่ง): 10875 ms, รวมไฟล์ที่อ่านทั้งหมด: 11280 msDot42, รหัสของ Greg โดยใช้ String แทนที่ () (เช่นเดียวกับใน Java และ Robert's code):
ผลรวมทั้งหมด (5 รอบการทำงาน): 9710 ms, โดยมีค่าการอ่านไฟล์ทั้งหมด: 10097 msDot42, รหัสโรเบิร์ต:
เวลารวมทั้งหมด (5 รอบ): 6279 มิลลิวินาที, รวมไฟล์ที่อ่านได้: 6622 มิลลิวินาทีXamarin:
เวลารวมทั้งหมด (5 วิ่ง): 6201 ms, รวมการอ่านไฟล์: 6476 msJava:
เวลาทั้งหมด (5 รัน): 7141 ms, รวมไฟล์ที่อ่านได้: 7479 ms
ฉันยังคิดว่า Dot42 มีทางที่จะไปได้อีกนาน การมีคลาสเหมือน Java (เช่น ArrayList) และประสิทธิภาพที่ดีจะทำให้การย้ายรหัสจาก Java เป็น C # ง่ายขึ้นเล็กน้อย อย่างไรก็ตามนี่คือสิ่งที่ฉันไม่น่าจะทำมาก ฉันอยากจะใช้รหัส C # ที่มีอยู่ (ไลบรารี ฯลฯ ) ที่มีอยู่ซึ่งจะใช้คลาส C # ดั้งเดิม (เช่นรายการ) และจะทำงานช้าลงด้วยรหัส dot42 ปัจจุบันและดีมากกับ Xamarin
เกร็ก