- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我很惊讶地发现,即使是一个简单的程序,例如:
print_string "Hello world !\n";
当通过 ocamlopt
使用一些相当激进的选项(使用 musl
)静态编译为 native 代码时,在我的系统上仍约为 190KB 左右。
$ ocamlopt.opt -compact -verbose -o helloworld \
-ccopt -static \
-ccopt -s \
-ccopt -ffunction-sections \
-ccopt -fdata-sections \
-ccopt -Wl \
-ccopt -gc-sections \
-ccopt -fno-stack-protector \
helloworld.ml && { ./helloworld ; du -h helloworld; }
+ as -o 'helloworld.o' '/tmp/camlasm759655.s'
+ as -o '/tmp/camlstartupfc4271.o' '/tmp/camlstartup5a7610.s'
+ musl-gcc -Os -o 'helloworld' '-L/home/vaab/.opam/4.02.3+musl+static/lib/ocaml' -static -s -ffunction-sections -fdata-sections -Wl -gc-sections -fno-stack-protector '/tmp/camlstartupfc4271.o' '/home/vaab/.opam/4.02.3+musl+static/lib/ocaml/std_exit.o' 'helloworld.o' '/home/vaab/.opam/4.02.3+musl+static/lib/ocaml/stdlib.a' '/home/vaab/.opam/4.02.3+musl+static/lib/ocaml/libasmrun.a' -static -lm
Hello world !
196K helloworld
如何从 ocamlopt 获取最小的二进制文件?
190KB
的大小对于像当今的限制(物联网、android、alpine VM...)这样的简单程序来说太大了,并且与简单的 C 程序(大约 6KB)相比效果不佳,或者直接编码 ASM 并进行调整以获得可能大约 150B 的工作二进制文件)。我天真地认为我可以简单地放弃 C 来编写简单的静态程序来完成一些琐碎的事情,编译后我会得到一些简单的汇编代码,这些代码的大小与等效的 C 程序相比不会那么大。那可能吗 ?
我认为我理解的内容:
当删除 gcc 的 -s
以获取有关二进制文件中剩余内容的一些提示时,我可以注意到很多 ocaml
符号,而且我还读到了一些ocamlrun
的环境变量 are meant to be interpreted even in this form 。就好像 ocamlopt
所谓的“ native 编译”是将程序的 ocamlrun
和非 native 字节码
打包到一个文件中,然后进行编译它可执行。不完全是我所期望的。我显然错过了一些重要的事情。但如果是这样的话,我会感兴趣为什么它不像我预期的那样。
编译为 native 代码的其他语言也有同样的问题:让一些天真的用户(如我自己)遇到大致相同的问题:
我还使用 Haskell 进行了测试,在不进行调整的情况下,所有语言编译器都会为“hello world”程序生成超过 700KB 的二进制文件(调整之前的 Ocaml 也是如此)。
最佳答案
您的问题非常广泛,我不确定它是否符合 Stackoverflow 的格式。它值得彻底discussion 。
A size of 190KB is way too much for a simple program like that in today's constraints (iot, android, alpine VM...), and compares badly with simple C program (around ~6KB, or directly coding ASM and tweaking things to get a working binary that could be around 150B)
首先,这不是一个公平的比较。如今,已编译的 C 二进制文件是一个工件,远非独立的二进制文件。它应该更像是框架中的插件。因此,如果您想计算给定的二进制文件实际使用了多少字节,我们将计算加载程序、shell、libc 库以及整个 Linux 或 Windows 内核的大小 - 它们总共构成了应用程序的运行时。
与 Java 或 Common Lisp 不同,OCaml 对通用 C 运行时非常友好,并尝试重用其大部分功能。但 OCaml 仍然带有自己的运行时,其中最大(也是最重要的部分)是垃圾收集器。运行时间并不是很大(大约 30 KLOC),但仍然增加了重量。由于 OCaml 使用静态链接,每个 OCaml 程序都会有一个它的副本。
因此,C 二进制文件具有显着的优势,因为它们通常在 C 运行时已经可用的系统中运行(因此通常将其排除在等式之外)。然而,有些系统根本没有 C 运行时,只有 OCaml 运行时,请参阅 Mirage例如。在此类系统中,OCaml 二进制文件更为有利。另一个例子是OCaPic项目中(在调整编译器和运行时之后),他们设法将 OCaml 运行时和程序装入 64Kb Flash(阅读paper,它对二进制大小非常有洞察力)。
How to get the smallest binary from ocamlopt?
当确实需要最小化大小时,请使用 Mirage Unikernels 或实现您自己的运行时。对于一般情况,请使用 strip
和 upx
。 (例如,使用 upx --best
我能够将示例的二进制大小减少到 50K,无需任何其他技巧)。如果性能不太重要,那么您可以使用字节码,它通常比机器代码小。因此,您只需支付一次费用(运行时费用约为 200k),并且为每个程序支付几个字节(例如,您的 helloworld 为 200 字节)。
此外,不要创建许多小的二进制文件,而是创建一个二进制文件。在您的特定示例中,helloworld 编译单元的大小在字节码中为 200 字节,在机器代码中为 700 字节。剩下的 50k 是启动线束,应该只包含一次。此外,由于 OCaml 支持运行时动态链接,因此您可以轻松创建一个加载器,在需要时加载模块。在这种情况下,二进制文件将变得非常小(数百字节)。
It is as if what ocamlopt calls "native compilation" is about packing ocamlrun and the not-native bytecode of your program in one file and make it executable. Not exactly what I would have expected. I obviously missed some important point. But if that is the case, I'll be interested why it isn't as I expected.
不不,这是完全错误的。 native 编译是指将程序编译为机器代码,无论是 x86、ARM 还是其他。运行时是用 C 编写的,编译为机器代码,并且也是链接的。 OCaml 标准库主要是用 OCaml 编写的,也编译为机器代码,也链接为二进制文件(仅使用那些模块,OCaml 静态链接非常高效,前提是将程序拆分为模块(编译单元)相当好)。
关于OCAMLRUNPARAM
环境变量,它只是一个参数化运行时行为的环境变量,主要是垃圾收集器的参数。
关于compilation - 如何获得最小的 ocamlopt 编译的 native 二进制文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58028824/
今天我在一个 Java 应用程序中看到了几种不同的加载文件的方法。 文件:/ 文件:// 文件:/// 这三个 URL 开头有什么区别?使用它们的首选方式是什么? 非常感谢 斯特凡 最佳答案 file
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引起辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the he
我有一个 javascript 文件,并且在该方法中有一个“测试”方法,我喜欢调用 C# 函数。 c# 函数与 javascript 文件不在同一文件中。 它位于 .cs 文件中。那么我该如何管理 j
需要检查我使用的文件/目录的权限 //filePath = path of file/directory access denied by user ( in windows ) File fil
我在一个目录中有很多 java 文件,我想在我的 Intellij 项目中使用它。但是我不想每次开始一个新项目时都将 java 文件复制到我的项目中。 我知道我可以在 Visual Studio 和
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 这个问题似乎不是关于 a specific programming problem, a software
我有 3 个组件的 Twig 文件: 文件 1: {# content-here #} 文件 2: {{ title-here }} {# content-here #}
我得到了 mod_ldap.c 和 mod_authnz_ldap.c 文件。我需要使用 Linux 命令的 mod_ldap.so 和 mod_authnz_ldap.so 文件。 最佳答案 从 c
我想使用PIE在我的项目中使用 IE7。 但是我不明白的是,我只能在网络服务器上使用 .htc 文件吗? 我可以在没有网络服务器的情况下通过浏览器加载的本地页面中使用它吗? 我在 PIE 的文档中看到
我在 CI 管道中考虑这一点,我应该首先构建和测试我的应用程序,结果应该是一个 docker 镜像。 我想知道使用构建环境在构建服务器上构建然后运行测试是否更常见。也许为此使用构建脚本。最后只需将 j
using namespace std; struct WebSites { string siteName; int rank; string getSiteName() {
我是 Linux 新手,目前正在尝试使用 ginkgo USB-CAN 接口(interface) 的 API 编程功能。为了使用 C++ 对 API 进行编程,他们提供了库文件,其中包含三个带有 .
我刚学C语言,在实现一个程序时遇到了问题将 test.txt 文件作为程序的输入。 test.txt 文件的内容是: 1 30 30 40 50 60 2 40 30 50 60 60 3 30 20
如何连接两个tcpdump文件,使一个流量在文件中出现一个接一个?具体来说,我想“乘以”一个 tcpdump 文件,这样所有的 session 将一个接一个地按顺序重复几次。 最佳答案 mergeca
我有一个名为 input.MP4 的文件,它已损坏。它来自闭路电视摄像机。我什么都试过了,ffmpeg , VLC 转换,没有运气。但是,我使用了 mediainfo和 exiftool并提取以下信息
我想做什么? 我想提取 ISO 文件并编辑其中的文件,然后将其重新打包回 ISO 文件。 (正如你已经读过的) 我为什么要这样做? 我想开始修改 PSP ISO,为此我必须使用游戏资源、 Assets
给定一个 gzip 文件 Z,如果我将其解压缩为 Z',有什么办法可以重新压缩它以恢复完全相同的 gzip 文件 Z?在粗略阅读了 DEFLATE 格式后,我猜不会,因为任何给定的文件都可能在 DEF
我必须从数据库向我的邮件 ID 发送一封带有附件的邮件。 EXEC msdb.dbo.sp_send_dbmail @profile_name = 'Adventure Works Admin
我有一个大的 M4B 文件和一个 CUE 文件。我想将其拆分为多个 M4B 文件,或将其拆分为多个 MP3 文件(以前首选)。 我想在命令行中执行此操作(OS X,但如果需要可以使用 Linux),而
快速提问。我有一个没有实现文件的类的项目。 然后在 AppDelegate 我有: #import "AppDelegate.h" #import "SomeClass.h" @interface A
我是一名优秀的程序员,十分优秀!