what part of the spec makes the executable size so much larger than C/C++?

xuanbao · · 431 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>C and C++ are suitable for embedded computing, and widely used for that purpose, even on microcontrollers with vanishingly small amounts of RAM - such as 32 KB like on the ATmega32, an 8-bit microcontroller in very wide usage and costing $1-$2 in quantities of one. Certainly as you go up to 64 KB, 128 KB, 512 KB, there are lots and lots of people programming in C and C++.</p> <p>What is interesting is that when you look at the Go specification, it really doesn&#39;t say all that much. It&#39;s a small language. The biggest thing the specification references directly is all of UTF-8, which obviously includes many code points.</p> <p>What I am curious about is what else makes up that very large executable size?</p> <p>A &#34;hello world&#34; program takes up 1.3 MB and takes 930 KB of RAM, which is impressively small. But where does it all go? Unicode? Garbage collection code?</p> <p>It seems to me that the language itself is not that large so I&#39;m very curious about the size. The C specification is certainly larger.</p> <p>So I&#39;m curious about the breakdown? By the way these memory usages and compiled file sizes are very impressive. I&#39;m just curious what&#39;s in them.</p> <p>If you cut out Unicode, for example because the program did not need to do text-based IO at all, how much of that could you save? It seems to me the largest part of the spec.</p> <p>The reason Go might still be interesting, of course, is because it&#39;s such a small and &#34;correct&#34; language. It&#39;s possible to code it after a bit of experience with very high confidence regarding what it is doing....</p> <hr/>**评论:**<br/><br/>Sythe2o0: <pre><p>Go has a complex runtime to handle 1. Garbage Collection and 2. Goroutine scheduling. C&#39;s runtime is comparatively miniscule. There are certainly other factors but that&#39;s probably the most significant one.</p></pre>sin2pifx: <pre><p>Plus: the runtime is statically linked, if I&#39;m not mistaken.</p></pre>tscs37: <pre><p>correct.</p> <p>The runtime will statically link all dependencies of your project into the binary. Unused functions and types are stripped if it can be reasonably determined they are unused.</p> <p>The result is a binary which only really depends on the glibc (or another libc if you link against it) and has no other external dependencies in of itself.</p> <p>If you want to go all the way you can (IIRC) link the muslc statically against go binaries which enables them to run on any system with a linux kernel (provided the binary only uses syscalls the kernel understands).</p> <p>On the other hand this results in larger binaries where you can&#39;t easily patch out vulnerabilities in security dependencies. I do hope this will be solved by plugin systems and more open source.</p></pre>int32_t: <pre><p>No, a statically linked Go binary doesn&#39;t depends on libc.</p></pre>morth: <pre><p>But it has to be noted, if you import net or any package that in turn imports net, e.g. some crypto packages, you won&#39;t get a static binary by default. You have to set CGO_ENABLED=0 in the environment then. </p> <p>As I often build docker images with Go programs I end up setting that flag a lot. </p></pre>nickandross: <pre><p>Yeah. I personally like the feature because you don&#39;t need to include extra dll files with the exe (for Windows).</p></pre>bureX: <pre><blockquote> <p>C&#39;s runtime</p> </blockquote> <p>Is there one? (in microcontrollers)</p></pre>alercah: <pre><p>Not really.</p></pre>kisielk: <pre><p>There often is. On all but the simplest micro controllers you often have at least a malloc implementation and basic filehandle facilities to support printf etc. </p></pre>alercah: <pre><p>I think it comes down to a definition of what a &#39;runtime&#39; is exactly; probably not worth arguing about.</p></pre>the_birds_and_bees: <pre><p><a href="https://en.wikipedia.org/wiki/Crt0" rel="nofollow">https://en.wikipedia.org/wiki/Crt0</a></p></pre>WikiTextBot: <pre><p><strong>Crt0</strong></p> <p>crt0 (also known as c0) is a set of execution startup routines linked into a C program that performs any initialization work required before calling the program&#39;s main function. It generally takes the form of an object file called crt0.o, often written in assembly language, which is automatically included by the linker into every executable file it builds.</p> <p>crt0 contains the most basic parts of the runtime library. As such, the exact work it performs depends on the program&#39;s compiler, operating system and C standard library implementation.</p> <hr/> <p><sup>[</sup> <a href="https://www.reddit.com/message/compose?to=kittens_from_space" rel="nofollow"><sup>PM</sup></a> <sup>|</sup> <a href="https://reddit.com/message/compose?to=WikiTextBot&amp;message=Excludeme&amp;subject=Excludeme" rel="nofollow"><sup>Exclude</sup> <sup>me</sup></a> <sup>|</sup> <a href="https://np.reddit.com/r/golang/about/banned" rel="nofollow"><sup>Exclude</sup> <sup>from</sup> <sup>subreddit</sup></a> <sup>|</sup> <a href="https://np.reddit.com/r/WikiTextBot/wiki/index" rel="nofollow"><sup>FAQ</sup> <sup>/</sup> <sup>Information</sup></a> <sup>|</sup> <a href="https://github.com/kittenswolf/WikiTextBot" rel="nofollow"><sup>Source</sup></a> <sup>]</sup> <sup>Downvote</sup> <sup>to</sup> <sup>remove</sup> <sup>|</sup> <sup>v0.27</sup></p></pre>throwawaybeginr: <pre><p>thanks. do you (anyone here) think microcontrollers need concurrency? I realize it would not be full Go without, but full Go is orders of magnitude (1.5) too big for microcontrollers....</p></pre>qu33ksilver: <pre><p>Like always, be wise and choose the right tool for the job. IMHO - Go is not the right choice to write code for microcontrollers. Its C.</p></pre>samnardoni: <pre><p>The language spec size (for some definition of &#34;size&#34;) and a compilers binary output size have basically no correlation.</p> <p>In Go&#39;s case, it is the size it is because of the runtime included for garbage collection and scheduling.</p></pre>int32_t: <pre><p>Besides the &#39;rich&#39; runtime, there are some noticeable differences compared with typical C executables. For example, a Go executable includes a &#39;pcln&#39; section which usually accounts for the largest data section. I am not sure if it would be eliminated when it&#39;s built with &#39;-ldflags -s -w&#39;. Also, almost every function is padded with a sequence of &#39;0xc&#39; or &#39;INT $0x3&#39; to have 16-byte alignment, which would add ~10% extra size. The metadata for GC and reflection could have some contribution as well.</p></pre>cheemosabe: <pre><p>The requirement for reflection increases the size of binaries considerably. Information about types (like the names of struct fields) needs to be recorded. Also, the possibility of an exported function being called using reflection means that the linker can&#39;t strip out exported functions that are never statically called.</p></pre>jocull: <pre><p>That&#39;s a really interesting point I had never considered. Kind of hurts your tree shaking abilities.</p></pre>throwawaybeginr: <pre><p>very interesting also.</p></pre>earthboundkid: <pre><p>One difference between the Go compiler as written in C and the self hosted compiler is the C compiler only allocated, it never did any clean up because it assumed that it would die before it needed to do garbage collection. C can do tricks like that! It&#39;s hard to beat C in part because C can bring a gun (no memory deallocation!) to a knife fight (garbage collection). </p></pre>dchapes: <pre><p>If you have a similar scenario (short lived, lots of allocation but no need to free anything) you can either set <code>GOGC=off</code> in the environment or you can use <a href="https://golang.org/pkg/runtime/debug/#SetGCPercent" rel="nofollow"><code>SetGCPercent(-1)</code></a> at program start to disable Go&#39;s garbage collection. This (I think) only disables GC runs but doesn&#39;t remove the bookkeeping requirements on allocations.</p></pre>drvd: <pre><p>Link your so small C++ code statically and see how small the program really is.</p></pre>cafxx1985: <pre><p>Arduino is normally programmed in C++ish. IIRC a compiled hello world clocks in to a few hundred <strong>bytes</strong> (yes, bytes, not KBs).</p> <p>Obviously all code is statically compiled, since there&#39;s no OS.</p></pre>8lall0: <pre><p>Well, of course. No runtime, 8bit programming (less space occupied by instructions), no need to handle concurrency, it doesn&#39;t surprise me. Maybe go language itself can be useful on embedded stuff, but it will require a specific compiler.</p></pre>throwawaybeginr: <pre><p>as I said, there&#39;s physically 32-64-128 kb of ram on some popular microcontrollers :)</p></pre>gac_web: <pre><blockquote> <p>The reason Go might still be interesting, of course, is because it&#39;s such a small and &#34;correct&#34; language. It&#39;s possible to code it after a bit of experience with very high confidence regarding what it is doing....</p> </blockquote> <p>Go is neither small nor correct and is certainly not adapted for programming micro-controllers. Unsafe API cannot be relied upon to do stuff like pointer arithmetic. Go isn&#39;t a 0 cost abstraction language at all. So the &#34;correct&#34; moniker is ridiculous. &#34;small&#34; obviously does not apply either because it&#39;s bundle with a runtime. I don&#39;t understand why anybody would think programming micro-controllers with a garbage collected language is a good idea to begin with, it&#39;s a stupid idea. You have C if you don&#39;t like C++ so use it. You shouldn&#39;t need more than that for embed programming.</p></pre>throwawaybeginr: <pre><p>I meant small in terms of the language specification. And I meant correct in that the code does what was intended, the code isn&#39;t broken. (the programmer didn&#39;t add mistakes while writing it.)</p> <p>thanks for writing.</p></pre>ziutekgo: <pre><p>Spec is actually small but heavily relies on GC. This one thing is enough to exclude any language from the interest of most microcontroller programmers.</p> <p>Size of your simple &#34;hello world&#34; example is heavily affected by GC, type information (need by interfaces and reflection) and big fmt package which has huge dependences. If you have on mind the size of ELF file, add to account the debuging data that allows to print beautiful stack traces and much more.</p> <p>You can try Emgo language, which supposed to be something between lightweight Go and smart C. It strongly bends Spec but you still feel strong taste of Go.</p></pre>throwawaybeginr: <pre><p>thank you!</p></pre>shovelpost: <pre><p>Relevant <a href="https://www.youtube.com/watch?v=rFejpH_tAHM" rel="nofollow">video</a> showcasing how complex is Go behind the scenes just to offer this simplicity to the programmers.</p></pre>

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

431 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传