มีคำตอบง่ายๆ: ทำไม GHC ถึงมีขนาดใหญ่?
- OCaml: 2MB
- Python: 15MB
- SBCL: 9MB
- OpenJRE - 26MB
- GHC: 113MB
ไม่สนใจในการประกาศเรื่อง "ทำไมฉันไม่ควรสนใจเรื่องขนาดถ้า Haskell เป็นเครื่องมือที่เหมาะสม"; นี่เป็นคำถามทางเทคนิค
มีคำตอบง่ายๆ: ทำไม GHC ถึงมีขนาดใหญ่?
ไม่สนใจในการประกาศเรื่อง "ทำไมฉันไม่ควรสนใจเรื่องขนาดถ้า Haskell เป็นเครื่องมือที่เหมาะสม"; นี่เป็นคำถามทางเทคนิค
คำตอบ:
มันค่อนข้างโง่จริง ๆ ห้องสมุดทุกแห่งที่มาพร้อมกับ GHC นั้นมีให้ใน4 รสชาติไม่น้อยกว่า:
รุ่น GHCi เป็นเพียงรุ่นคงที่เชื่อมโยงกันใน.o
ไฟล์เดียว อีกสามรุ่นมีชุดของไฟล์อินเตอร์เฟซ ( .hi
ไฟล์) ของตัวเองเช่นกัน ดูเหมือนว่ารุ่นที่ทำโปรไฟล์จะมีขนาดประมาณสองเท่าของเวอร์ชันที่ไม่ได้ทำโปรไฟล์ (ซึ่งค่อนข้างน่าสงสัยฉันควรพิจารณาสาเหตุที่เป็นเช่นนั้น)
โปรดจำไว้ว่าGHC เป็นห้องสมุดดังนั้นคุณจะได้รับสำเนา GHC 4 ชุด ไม่เพียงแค่นั้น แต่ GHC ไบนารีเองนั้นมีการเชื่อมโยงแบบคงที่ดังนั้นนั่นคือ GHC 5 สำเนา
เราเพิ่งสร้างมันขึ้นมาเพื่อให้ GHCi สามารถใช้.a
ไฟล์คงที่ได้ นั่นจะช่วยให้เราสามารถกำจัดหนึ่งในรสชาติเหล่านี้ ในระยะยาวเราควรเชื่อมโยง GHC แบบไดนามิก แต่นั่นเป็นการเปลี่ยนแปลงที่ยิ่งใหญ่กว่าเพราะนั่นจะทำให้การเชื่อมโยงแบบไดนามิกเป็นค่าเริ่มต้น - ไม่เหมือนกับ C ด้วย GHC คุณต้องตัดสินใจล่วงหน้าว่าจะเชื่อมโยงแบบไดนามิกหรือไม่ และเราต้องการการเปลี่ยนแปลงเพิ่มเติม (เช่น Cabal และระบบบรรจุภัณฑ์รวมถึงสิ่งอื่น ๆ ) ก่อนหน้านี้มันใช้งานได้จริง
อาจเราควรเปรียบเทียบแอปเปิ้ลกับแอปเปิ้ลและส้มกับส้ม JRE เป็นรันไทม์ไม่ใช่ชุดนักพัฒนา เราอาจเปรียบเทียบ: ขนาดซอร์สของชุดพัฒนาขนาดของชุดพัฒนาที่คอมไพล์และขนาดที่คอมไพล์ของรันไทม์ขั้นต่ำสุด
บันเดิลซอร์สของ OpenJDK 7 คือ 82 MB (download.java.net/openjdk/jdk7) กับบันเดิลซอร์ส GHC 7 ซึ่งเป็น 23 MB (haskell.org/ghc/download_ghc_7_0_1) GHC ไม่ใหญ่ที่นี่ ขนาดของรันไทม์: openjdk-6-jre-headless บน Ubuntu คือ 77 MB ที่ไม่บีบอัดกับ Haskell helloworld ซึ่งเชื่อมโยงกับรันไทม์ของมันคือ <1 MB GHC ไม่ใหญ่ที่นี่
ที่ GHC มีขนาดใหญ่ขนาดของชุดพัฒนาที่คอมไพล์คือ:
GHC นั้นใช้เวลา 270 MB และด้วยไลบรารีและยูทิลิตี้ทั้งหมดที่มารวมกันนั้นใช้เวลามากกว่า 500 MB และใช่มันมีจำนวนมากแม้จะมีไลบรารีพื้นฐานและเครื่องมือสร้าง / ผู้จัดการอ้างอิง แพลตฟอร์มการพัฒนา Java มีขนาดเล็กลง
GHC:
$ aptitude show ghc6 | grep Size
Uncompressed Size: 388M
กับ OpenJDK ด้วยการพึ่งพา:
$ aptitude show openjdk-6-jdk openjdk-6-jre openjdk-6-jre-headless ant maven2 ivy | grep Size
Uncompressed Size: 34.9M
Uncompressed Size: 905k
Uncompressed Size: 77.3M
Uncompressed Size: 1,585k
Uncompressed Size: 3,736k
Uncompressed Size: 991k
แต่มันยังมากกว่า 100 MB ไม่ใช่ 26 MB ตามที่คุณเขียน
สิ่งที่หนาใน ghc6 และ ghc6-prof คือ:
$ dpkg -L ghc6 | grep '\.a$' | xargs ls -1ks | sort -k 1 -n -r | head -3
57048 /usr/lib/ghc-6.12.1/ghc-6.12.1/libHSghc-6.12.1.a
22668 /usr/lib/ghc-6.12.1/Cabal-1.8.0.2/libHSCabal-1.8.0.2.a
21468 /usr/lib/ghc-6.12.1/base-4.2.0.0/libHSbase-4.2.0.0.a
$ dpkg -L ghc6-prof | grep '\.a$' | xargs ls -1ks | sort -k 1 -n -r | head -3
112596 /usr/lib/ghc-6.12.1/ghc-6.12.1/libHSghc-6.12.1_p.a
33536 /usr/lib/ghc-6.12.1/Cabal-1.8.0.2/libHSCabal-1.8.0.2_p.a
31724 /usr/lib/ghc-6.12.1/base-4.2.0.0/libHSbase-4.2.0.0_p.a
libHSghc-6.12.1_p.a
โปรดทราบมีวิธีการใหญ่ ดังนั้นคำตอบน่าจะเป็นการเชื่อมโยงแบบคงที่และการทำโปรไฟล์สำหรับไลบรารี่ทุกอัน
ฉันเดา - เชื่อมโยงคงที่มากมาย แต่ละห้องสมุดจะต้องเชื่อมโยงการพึ่งพาแบบคงที่ซึ่งจะต้องเชื่อมโยงแบบคงที่และเบา ๆ และนี่คือทั้งหมดที่รวบรวมบ่อยครั้งทั้งที่มีและไม่มีการทำโปรไฟล์และแม้จะไม่มีการทำโปรไฟล์ไบนารีก็จะไม่ถูกแยกออกและเก็บข้อมูลดีบักเกอร์จำนวนมาก
เพราะมันรวมgccและกลุ่มของไลบรารีทั้งหมดจึงเชื่อมโยงแบบสแตติก
อย่างน้อยบน Windows
นี่คือรายละเอียดขนาดไดเรกทอรีในกล่องของฉัน:
https://spreadsheets.google.com/ccc?key=0AveoXImmNnZ6dDlQeHY2MmxPcEYzYkpweEtDSS1fUlE&hl=en
ดูเหมือนว่าไดเรกทอรีที่ใหญ่ที่สุด (123 MB) เป็นไบนารีสำหรับการรวบรวมคอมไพเลอร์เอง เอกสารชั่งน้ำหนักอย่างน่าประหลาดใจ 65 MB อันดับสามคือ Cabal ที่ 41 MB
ไดเรกทอรี bin คือ 33 MB และฉันคิดว่ามีเพียงเซตย่อยของสิ่งที่จำเป็นในทางเทคนิคในการสร้างแอปพลิเคชัน Haskell
คำตอบสั้น ๆ ก็คือมันเป็นเพราะ executables ทั้งหมดมีการเชื่อมโยงแบบคงที่อาจมีข้อมูลการแก้ปัญหาในพวกเขาและห้องสมุดจะรวมอยู่ในหลายสำเนา สิ่งนี้ได้ถูกกล่าวถึงโดยผู้แสดงความคิดเห็นคนอื่น ๆ
การเชื่อมโยงแบบไดนามิกเป็นไปได้และจะลดขนาดลงอย่างมาก นี่คือตัวอย่างHello.hs
:
main = putStrLn "Hello world"
ฉันสร้างด้วย GHC 7.4.2 บน Windows
ghc --make -O2
ให้Hello.exe
ของ 1105Ks
วิ่งstrip
บนใบ 630K
ghc --make -O2 -dynamic
ให้ 40K
การปอกเปลือกจะทิ้งห่างเพียง 13K
มันขึ้นอยู่กับ 5 dll ที่มีขนาดรวม 9.2 MBs unstripped และ 5.7 MB stripped