আমি একটি হ্যালো ওয়ার্ল্ড গো প্রোগ্রামটি মেনে চললাম যা আমার লিনাক্স মেশিনে দেশীয় নির্বাহযোগ্য able তবে আমি হ্যালো ওয়ার্ল্ড গো প্রোগ্রামের আকারটি দেখে অবাক হয়েছি, এটি ছিল 1.9MB!
কেন এটি এত সহজ প্রোগ্রামের এক্সিকিউটেবল এত বিশাল?
আমি একটি হ্যালো ওয়ার্ল্ড গো প্রোগ্রামটি মেনে চললাম যা আমার লিনাক্স মেশিনে দেশীয় নির্বাহযোগ্য able তবে আমি হ্যালো ওয়ার্ল্ড গো প্রোগ্রামের আকারটি দেখে অবাক হয়েছি, এটি ছিল 1.9MB!
কেন এটি এত সহজ প্রোগ্রামের এক্সিকিউটেবল এত বিশাল?
dotnet publish -r win-x64 -p:publishsinglefile=true -p:publishreadytorun=true -p:publishtrimmed=true
প্রায় M 26MB এর একটি বাইনারি ফাইল উত্পন্ন করে!
উত্তর:
এই সঠিক প্রশ্নটি অফিসিয়াল এফএকিউতে উপস্থিত হয়: আমার তুচ্ছ প্রোগ্রামটি এত বড় বাইনারি কেন?
উত্তরটি উদ্ধৃত করে:
জিসি টুল শৃঙ্খল (ইন linkers
5l
,6l
এবং8l
) স্ট্যাটিক লিঙ্ক না। সমস্ত গোটা বাইনারিগুলির মধ্যে ডায়নামিক ধরণের চেক, প্রতিবিম্ব এবং এমনকি প্যানিক-টাইম স্ট্যাক ট্রেস সমর্থন করার জন্য প্রয়োজনীয় রান-টাইম তথ্যের পাশাপাশি গো রান-টাইম অন্তর্ভুক্ত থাকে।একটি সাধারণ সি "হ্যালো, ওয়ার্ল্ড" প্রোগ্রামটি লিনাক্সে জিসিসি ব্যবহার করে স্ট্যাটিক্যালি সংকলিত এবং সংযুক্ত এবং এর বাস্তবায়ন সহ প্রায় 750 কেবি হয়
printf
। সমতুল্য গো প্রোগ্রামটিfmt.Printf
প্রায় 1.9 মেগাবাইটের কাছাকাছি হয় তবে এতে আরও শক্তিশালী রান-টাইম সমর্থন এবং টাইপ তথ্য অন্তর্ভুক্ত রয়েছে।
সুতরাং আপনার হ্যালো ওয়ার্ল্ডের নেটিভ এক্সিকিউটেবল 1.9 এমবি কারণ এটিতে রানটাইম রয়েছে যা আবর্জনা সংগ্রহ, প্রতিচ্ছবি এবং অন্যান্য অনেকগুলি বৈশিষ্ট্য সরবরাহ করে (যা আপনার প্রোগ্রামটি সম্ভবত ব্যবহার না করে তবে এটি সেখানে রয়েছে)। এবং fmt
আপনি যে প্যাকেজটি প্রবন্ধটি মুদ্রণ করতে ব্যবহার করেছিলেন তার বাস্তবায়ন "Hello World"
(প্লাস এর নির্ভরতা)।
এখন নিম্নলিখিতটি ব্যবহার করে দেখুন: fmt.Println("Hello World! Again")
আপনার প্রোগ্রামে আরও একটি লাইন যুক্ত করুন এবং এটি আবার সংকলন করুন। ফলাফলটি 2x 1.9MB হবে না, তবে এখনও মাত্র 1.9 মেগাবাইট! হ্যাঁ, কারণ ব্যবহৃত সমস্ত লাইব্রেরি ( fmt
এবং এর নির্ভরতা) এবং রানটাইম ইতিমধ্যে এক্সিকিউটেবলের সাথে যুক্ত করা হয়েছে (এবং তাই আপনি কেবল যুক্ত করেছেন এমন দ্বিতীয় পাঠ্য মুদ্রণের জন্য আরও কয়েকটি বাইট যুক্ত করা হবে)।
নিম্নলিখিত প্রোগ্রাম বিবেচনা করুন:
package main
import "fmt"
func main() {
fmt.Println("Hello World!")
}
যদি আমি এটি আমার লিনাক্স এএমডি 64 মেশিনে (Go 1.9) তৈরি করি তবে:
$ go build
$ ls -la helloworld
-rwxr-xr-x 1 janf group 2029206 Sep 11 16:58 helloworld
আমি এআ বাইনারি পাই যা প্রায় 2 এমবি আকারের।
এর কারণ (যা অন্যান্য উত্তরে ব্যাখ্যা করা হয়েছে) হ'ল আমরা "এফএমটি" প্যাকেজটি ব্যবহার করছি যা বেশ বড়, তবে বাইনারিটিও ছিনিয়ে নেওয়া হয়নি এবং এর অর্থ প্রতীক টেবিলটি এখনও আছে। আমরা যদি পরিবর্তে বাইনারি ফালা করতে কম্পাইলারকে নির্দেশ করি তবে এটি অনেক ছোট হয়ে যাবে:
$ go build -ldflags "-s -w"
$ ls -la helloworld
-rwxr-xr-x 1 janf group 1323616 Sep 11 17:01 helloworld
তবে, আমরা যদি এফএমটি.প্রিন্টলন এর পরিবর্তে বিল্টিন ফাংশন মুদ্রণটি ব্যবহার করার জন্য প্রোগ্রামটি পুনরায় লিখন করি:
package main
func main() {
print("Hello World!\n")
}
এবং তারপরে এটি সংকলন করুন:
$ go build -ldflags "-s -w"
$ ls -la helloworld
-rwxr-xr-x 1 janf group 714176 Sep 11 17:06 helloworld
আমরা একটি এমনকি আরও ছোট বাইনারি সঙ্গে শেষ। এটি যতটা ছোট আমরা ইউপিএক্স-প্যাকিংয়ের মতো কৌশল অবলম্বন না করে এটি পেতে পারি, তাই গো-রানটাইমের ওভারহেড প্রায় 700 কেবি হয়।
লক্ষ্য করুন বাইনারি আকার ইস্যু দ্বারা ট্র্যাক করা হয় ইস্যু 6853 সালে golang / Go প্রকল্পের ।
উদাহরণস্বরূপ, a26c01a (Go 1.4 এর জন্য) প্রতিশ্রুতিবদ্ধ হ্যালো ওয়ার্ল্ডকে 70 কেবি দ্বারা কাটা :
কারণ আমরা সেই নামগুলি প্রতীক টেবিলটিতে লিখি না।
সংকলক, এসেম্বলার, লিঙ্কার এবং 1.5 এর রানটাইম বিবেচনা করে পুরোপুরি গোতে থাকবে, আপনি আরও অপ্টিমাইজেশন আশা করতে পারেন।
২০১ 2016 Go 1.7 আপডেট করুন: এটি অনুকূলিত করা হয়েছে: " ছোট যান 1.7 বাইনারি " দেখুন।
তবে এই দিনটি (এপ্রিল 2019), সবচেয়ে বেশি জায়গা নেয় runtime.pclntab
।
দেখুন " আমার যান এক্সিকিউটেবল ফাইলের তাই যান বৃহৎ? সাইজ কল্পনা থেকে D3 ব্যবহার এক্সেকিউটেবল কেন থেকে" রাফায়েল 'kena' Poss ।
এটি খুব ভাল নথিবদ্ধ নয় তবে গো উত্স কোড থেকে এই মন্তব্যটি এর উদ্দেশ্যটির পরামর্শ দেয়:
// A LineTable is a data structure mapping program counters to line numbers.
এই ডেটা স্ট্রাকচারের উদ্দেশ্য হ'ল রান রানটাইম সিস্টেমটিকে ক্র্যাশের সময় বা
runtime.GetStack
API এর মাধ্যমে অভ্যন্তরীণ অনুরোধের ভিত্তিতে বর্ণনামূলক স্ট্যাকের ট্রেস তৈরি করতে সক্ষম করা ।সুতরাং এটি দরকারী মনে হয়। তবে এত বড় কেন?
উপরের লিঙ্কযুক্ত উত্স ফাইলটিতে লুকানো https://golang.org/s/go12symtab URL একটি নথিতে পুনঃনির্দেশ করে যা Go 1.0 এবং 1.2 এর মধ্যে কী ঘটেছিল তা ব্যাখ্যা করে। প্যারাফ্রেজ করতে:
1.2 এর আগে, গো লিঙ্কার একটি সংকুচিত লাইন টেবিল নির্গত করছিল, এবং প্রোগ্রামটি রান-টাইমে সূচনা করার সময় এটি সঙ্কুচিত করবে।
Go 1.2 এ, এক্সিকিউটেবল ফাইলের লাইন টেবিলটিকে পূর্ব-প্রসারিত করার জন্য সিদ্ধান্ত নেওয়া হয়েছিল এটির চূড়ান্ত বিন্যাসে রান-টাইমে সরাসরি ব্যবহারের জন্য উপযুক্ত, কোনও অতিরিক্ত সংক্ষেপণ পদক্ষেপ ছাড়াই।
অন্য কথায়, গো দল প্রাথমিককরণের সময় সংরক্ষণের জন্য এক্সিকিউটেবল ফাইলগুলি আরও বড় করার সিদ্ধান্ত নিয়েছে।
এছাড়াও, ডাটা স্ট্রাকচারের দিকে তাকালে, এটি প্রদর্শিত হয় যে সংকলিত বাইনারিগুলিতে এর সামগ্রিক আকারটি প্রতিটি ফাংশনটি কত বড় সেগুলি ছাড়াও প্রোগ্রামের ফাংশনের সংখ্যার তুলনায় সুপার-লিনিয়ার।