ทำไม GHC ถึงใหญ่ / ใหญ่


147

มีคำตอบง่ายๆ: ทำไม GHC ถึงมีขนาดใหญ่?

  • OCaml: 2MB
  • Python: 15MB
  • SBCL: 9MB
  • OpenJRE - 26MB
  • GHC: 113MB

ไม่สนใจในการประกาศเรื่อง "ทำไมฉันไม่ควรสนใจเรื่องขนาดถ้า Haskell เป็นเครื่องมือที่เหมาะสม"; นี่เป็นคำถามทางเทคนิค


1
คุณได้รับ 500MB นี้จากที่ไหน GHC ของฉันไม่มีขนาดใหญ่
จาค็อบ

ถ้าคุณไม่นับทั้งหมดของห้องสมุดฉันเดา ...
จาค็อบ

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

20
อาจเราควรเปรียบเทียบแอปเปิ้ลกับแอปเปิ้ลและส้มกับส้ม JRE เป็นรันไทม์ไม่ใช่ชุดนักพัฒนา บันเดิลซอร์ส OpenJDK 7, 82 MB ( download.java.net/openjdk/jdk7 ) เทียบกับบันเดิลซอร์ส GHC 7, 23 MB ( haskell.org/ghc/download_ghc_7_0_1 ) ตอนนี้รันไทม์: openjdk-6-jre-headless บน Ubuntu, 77 MB ที่ยังไม่บีบอัดกับ Haskell helloworld เชื่อมโยงกับรันไทม์ <1 MB
sastanin

วันนี้ฉันอยากรู้เกี่ยวกับขนาดตอนนี้ 2014 ดูเหมือนว่าข้อโต้แย้งยังคงมีอยู่ ฉันพบ URLS: 1.GHC haskell.org/ghc/download_ghc_7_8_3 ; 2.OpenJCK packages.ubuntu.com/precise/openjdk-7-jdk
AnneTheAgile

คำตอบ:


187

มันค่อนข้างโง่จริง ๆ ห้องสมุดทุกแห่งที่มาพร้อมกับ GHC นั้นมีให้ใน4 รสชาติไม่น้อยกว่า:

  • คงที่
  • พลวัต
  • ประวัติ
  • GHCi

รุ่น GHCi เป็นเพียงรุ่นคงที่เชื่อมโยงกันใน.oไฟล์เดียว อีกสามรุ่นมีชุดของไฟล์อินเตอร์เฟซ ( .hiไฟล์) ของตัวเองเช่นกัน ดูเหมือนว่ารุ่นที่ทำโปรไฟล์จะมีขนาดประมาณสองเท่าของเวอร์ชันที่ไม่ได้ทำโปรไฟล์ (ซึ่งค่อนข้างน่าสงสัยฉันควรพิจารณาสาเหตุที่เป็นเช่นนั้น)

โปรดจำไว้ว่าGHC เป็นห้องสมุดดังนั้นคุณจะได้รับสำเนา GHC 4 ชุด ไม่เพียงแค่นั้น แต่ GHC ไบนารีเองนั้นมีการเชื่อมโยงแบบคงที่ดังนั้นนั่นคือ GHC 5 สำเนา

เราเพิ่งสร้างมันขึ้นมาเพื่อให้ GHCi สามารถใช้.aไฟล์คงที่ได้ นั่นจะช่วยให้เราสามารถกำจัดหนึ่งในรสชาติเหล่านี้ ในระยะยาวเราควรเชื่อมโยง GHC แบบไดนามิก แต่นั่นเป็นการเปลี่ยนแปลงที่ยิ่งใหญ่กว่าเพราะนั่นจะทำให้การเชื่อมโยงแบบไดนามิกเป็นค่าเริ่มต้น - ไม่เหมือนกับ C ด้วย GHC คุณต้องตัดสินใจล่วงหน้าว่าจะเชื่อมโยงแบบไดนามิกหรือไม่ และเราต้องการการเปลี่ยนแปลงเพิ่มเติม (เช่น Cabal และระบบบรรจุภัณฑ์รวมถึงสิ่งอื่น ๆ ) ก่อนหน้านี้มันใช้งานได้จริง


16
และที่นี่ฉันคิดว่ามันเป็นตรรกะทั้งหมดที่ Haskell นำเสนอ: การประเมินผลที่ขี้เกียจ, การอนุมานประเภท ฯลฯ
mcandre

4
ดังนั้น 113MB / 4 ~ = 28MB ยังคงใหญ่กว่า OpenJRE ... แต่การพิจารณา GHC เปรียบได้กับ OpenJDK ไม่ใช่แค่ JRE มันทำให้ฉันรู้สึกดีขึ้น
Earth Engine

1
ตอนนี้ฉันคิดว่า GHC ใช้การเชื่อมโยงแบบไดนามิกบางทีความคิดของ Dr. @Simon Marlow สำหรับการบีบอัดของสี่รสชาตินั้นใช้งานได้จริงหรือ อ้างอิง: 1. # 3658 (ลิงก์ GHCi แบบไดนามิก (และใช้ตัวเชื่อมโยงระบบ) บนแพลตฟอร์มที่รองรับ) - GHC ghc.haskell.org/trac/ghc/ticket/3658 ; 2. # 8266 (การลิงก์แบบไดนามิกบน Mac) - GHC ghc.haskell.org/trac/ghc/ticket/8266 ; 3. # 8376 (แบบปฏิบัติการได้คงที่ + GHC API (+ การเชื่อมโยงแบบไดนามิก?) ให้ Segfault) - GHC
AnneTheAgile

56

อาจเราควรเปรียบเทียบแอปเปิ้ลกับแอปเปิ้ลและส้มกับส้ม 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

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โปรดทราบมีวิธีการใหญ่ ดังนั้นคำตอบน่าจะเป็นการเชื่อมโยงแบบคงที่และการทำโปรไฟล์สำหรับไลบรารี่ทุกอัน


9

ฉันเดา - เชื่อมโยงคงที่มากมาย แต่ละห้องสมุดจะต้องเชื่อมโยงการพึ่งพาแบบคงที่ซึ่งจะต้องเชื่อมโยงแบบคงที่และเบา ๆ และนี่คือทั้งหมดที่รวบรวมบ่อยครั้งทั้งที่มีและไม่มีการทำโปรไฟล์และแม้จะไม่มีการทำโปรไฟล์ไบนารีก็จะไม่ถูกแยกออกและเก็บข้อมูลดีบักเกอร์จำนวนมาก


2
ฉันอาจจะไม่รังเกียจถ้า GHC เปลี่ยนเป็นโปรแกรมทั้งหมดคอมไพล์เกือบทุกรูปแบบเหมือนกับ jhc มันอาจจะคอมไพล์เร็วขึ้นถ้ามันจะป้องกัน 'ld' จากการแลกเปลี่ยน
John L

8

เพราะมันรวมgccและกลุ่มของไลบรารีทั้งหมดจึงเชื่อมโยงแบบสแตติก

อย่างน้อยบน Windows


12
ไม่ไม่ได้อยู่ใน linux ขึ้นอยู่กับ gcc เท่านั้น เนื่องจาก windows ไม่มี gcc ใน "การกระจาย" ของมันจึงต้องมาพร้อมกับ ghc
comonad

5

นี่คือรายละเอียดขนาดไดเรกทอรีในกล่องของฉัน:

https://spreadsheets.google.com/ccc?key=0AveoXImmNnZ6dDlQeHY2MmxPcEYzYkpweEtDSS1fUlE&hl=en

ดูเหมือนว่าไดเรกทอรีที่ใหญ่ที่สุด (123 MB) เป็นไบนารีสำหรับการรวบรวมคอมไพเลอร์เอง เอกสารชั่งน้ำหนักอย่างน่าประหลาดใจ 65 MB อันดับสามคือ Cabal ที่ 41 MB

ไดเรกทอรี bin คือ 33 MB และฉันคิดว่ามีเพียงเซตย่อยของสิ่งที่จำเป็นในทางเทคนิคในการสร้างแอปพลิเคชัน Haskell


6
ให้ฉันเพิ่มบางอย่างลงในสิ่งนี้: ถ้าคุณใช้คอมไพเลอร์แบร์โบนแล้วตัดสิ่งที่ไม่จำเป็นออกไปอย่างแน่นอน (เช่นการสร้างคอมไพเลอร์ที่ไม่ได้กำไรแยกและอื่น ๆ ) คุณสามารถลงไปได้ประมาณ 5 MB แต่ลองเปรียบเทียบขนาดของคอมไพเลอร์กับ GCC (แก้ไขความคิดเห็นดังนั้นฉันต้องลบมัน ... ขอโทษ)
fuz

5

คำตอบสั้น ๆ ก็คือมันเป็นเพราะ 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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.