.NET跨平台实践:Linux .Net Core自宿主应用程序瘦身记
一,.NET Core 自宿主应用程序个头很大
发布.NET Core应用程序有两个方式,一种是“便携式”,一种是“自宿主式”。便携式发布时,目标程序不带.net core运行环境,所以“个头”很小,可能只有几十K几百K字节,但是它需要用户的目标系统上安装.NET CORE 框架;自宿主式发布出来的程序,自带运行时和框架类库,自成一体,不需要客户机安装.NET CORE环境,部署简单方便。
看看一个简单的“Hello World!” 控制台程序有多大:
修改 csproj文件,添加目标系统:
用 dotnet publish -r:linux-x64 针对linux平台发布,得到目标文件(夹),现在看看大小:
这个Hello World 控制台程序的目标文件,总大小达到了62.2 MB!
二,为什么.net core自宿主程序这么大
原因有二,一是为了能在目标系统上 “独立” 运行,自宿主程序必须自带运行时,这无可厚非,二是不管是用 dotnet publish命令行发布还是用VS发布,它们都会不分青红皂白地把.net core类库整个发布到目标程序中,这正是使目标程序变大变肥的主要原因。
下面是发布后的部分文件列表,可以看出,很多的dll与这个hello world 程序毫无关系!
三,给 Linux .Net Core 自宿主应用程序瘦身
从前边的分析可以看出,自宿主应用程序之所有“肥大”,是因为有太多的无关的类库或Native so库造成的,只要清理掉它们,瘦身的目标就达到了。
1,将发布的程序全部上传到Linux系统的某个文件夹,然后运行 chmod +x coretest,给coretest赋与可执行权限。(我写的这个hello word程序名叫“coretest”)。
2,用 ./coretest 把程序运行起来:
不要按键,让程序不要退出。
3,查出这个进程的PID:
再加一个终端,用 ps -ef | grep coretest 查出这个进程的PID号
4,列出进程关联文件:
用 sudo lsof -p PID号,列出指定进程调用/引用的文件,从列表中找出属于这个core程序依赖的类库和core Navite函数库:
特点:路径都指向这个core程序所在的文件夹。
下图是列表的一部分:
从列表中,可以看出,本 coretest 程序,相关的文件有如下三类14个文件:
1)coretes加载程序和程序集:
coretest
coretest.dll
2)依赖的.net 框架程序集:
System.Runtime.dll
System.Console.dll
System.Threading.dll
System.Runtime.Extensions.dll
System.Collections.dll
3)运行时函数库:
libclrjit.so
libcoreclr.so
libhostpolicy.so
libhostfxr.so
System.Native.so
System.Globalization.Native.so
System.Private.CoreLib.dll
5,修改依赖文件 coretest.deps.json,对依赖行配置文件瘦身:
打开 coretest.deps.json文件,你会发现所有的依赖库都在其中,重要的是49行开始的“runtime.linux-x64.Microsoft.NETCore.App/2.0.0”的runtimes和native两个节点,共有173个依赖项,与我们测试出来的14个依赖,整整多了150多个,对于这个具体的程序而言,这150多个依赖都是多余的,这些多余的,都得删除!
删除后,deps.json一下子清爽了:
6,测试依赖配置文件是否正确:
再次用 ./coretest 运行本程序,检查依赖项是否正确。当按任意键退出程序时,出现了下边的错误。
原来,在Console.ReadKey返回时,会调用另一个dll,而之前用lsof时,没有程序没有执行到这一步,所以没有看到有这个依赖,这个依赖被误删了。所以,得重新加到deps.json文件中。
再次测试,程序已经完全正常。
7,根据瘦身后的依赖关系,删除无关文件:
要点,需要保留依赖列表文件coretest.deps.json和运行时配置文件coretest.runtimeconfig.json。
8,再次测试程序运行情况:
运行 ./coretest,发现出了一个问题:
差一个native 函数库,怎么办?简单,从windows发布目录中,上传到Linux的这个程序文件夹中。
再次运行,一帆风顺,瘦身工作正式完成!
现在看看这个程序,共计还有多少文件:
哈哈,现在只有19个文件!比如之前的近180个文件,这个”身“瘦得厉害吧,简直是一身清爽呀!
瘦身后,这个程序所有文件从62.2M变成了24.3m,打包压缩后,只有8.62M。
附记:
有的朋友可能会说,还是有点大呀,一个hello world就有19个文件24m大小,如果我司开发一个功能完整的商业应用会不会大得吓人?其实,我可以告诉你:
一,这19个文件已经具备了.net core的关键功能,你开发更大的商业应用,不外乎再多引用了几个dll而已,能再大多少!
二,这个程序是自带了运行环境的,它自成一体,独立运行,不需要麻烦你和你的客户或运维人员在linux上安装安装一大堆东西,配置一大堆东西!
三,正因为这个程序可以独立运行,那么,如果在Docker中,对docker镜像的体积影响可以忽略,比如那个动不动就数百M的镜像,你选什么?
.NET跨平台实践:Linux .Net Core自宿主应用程序瘦身记的更多相关文章
- 一个更好用的.NET Core程序瘦身器,减小程序尺寸到1/3
一.为什么要开发.NET Core程序瘦身器? .NET Core具有[剪裁未使用的代码]的功能,但是由于它是使用静态分析来实现的,因此它的剪裁效果并不是最优的.它有如下两个缺点: 不支持Window ...
- Linux .Net Core
Linux .Net Core自宿主应用程序瘦身记 一,.NET Core 自宿主应用程序个头有点大 发布.NET Core应用程序有两个方式,一种是“便携式”,一种是“自宿主式”.便携式发布时,目标 ...
- NET Core 2.0 微服务跨平台实践
NET Core 2.0 微服务跨平台实践 相关博文: Ubuntu 简单安装 Docker Mac OS.Ubuntu 安装及使用 Consul Consul 服务注册与服务发现 Fabio 安装和 ...
- .NET跨平台实践:.NetCore、.Net5/6 Linux守护进程设计
之前,我写过两篇关于用C#开发Linux守护进程的技术文章,分别是<.NET跨平台实践:用C#开发Linux守护进程>和<.NET跨平台实践:再谈用C#开发Linux守护进程 - 完 ...
- .net core 跨平台实践
本人采用Ubuntu 14.04 来实现.net core 的跨平台实践. 首先安装Ubuntu14.04系统.安装细节问百度. 1..net core console程序的跨平台 首先新建一个con ...
- .NET跨平台实践:再谈用C#开发Linux守护进程
Linux守护进程是Linux的后台服务进程,相当于Windows服务进程,对于为Linux开发服务程序的朋友来说,Linux守护进程相关技术是必不可少的,因为这个技术不仅仅是开发守护进程,还可以拓展 ...
- .NET跨平台实践:再谈用C#开发Linux守护进程 — 完整篇
Linux守护进程是Linux的后台服务进程,相当于Windows服务,对于为Linux开发服务程序的朋友来说,Linux守护进程相关技术是必不可少的,因为这个技术不仅仅是为了开发守护进程,还可以拓展 ...
- Ubuntu & Docker & Consul & Fabio & ASP.NET Core 2.0 微服务跨平台实践
相关博文: Ubuntu 简单安装 Docker Mac OS.Ubuntu 安装及使用 Consul Consul 服务注册与服务发现 Fabio 安装和简单使用 阅读目录: Docker 运行 C ...
- Docker & Consul & Fabio & ASP.NET Core 2.0 微服务跨平台实践
相关博文: Ubuntu 简单安装 Docker Mac OS.Ubuntu 安装及使用 Consul Consul 服务注册与服务发现 Fabio 安装和简单使用 阅读目录: Docker 运行 C ...
随机推荐
- .NetCore~Json代替了Xml
回到目录 在进行.netCore时代后,最大的变化就是对Json的使用更加主动,基本代替了之前的XML,像一些用户配置,系统配置,包包配置等都是基于json的,而web.config这个文件基本变成一 ...
- spring boot 拦截器添加
@Configuration public class WebMvcConfig extends WebMvcConfigurerAdapter { @Autowired private XxxInt ...
- 利用base64函数,对文件进行转码加密
设计此种编码是为了使二进制数据可以通过非纯 8-bit 的传输层传输,例如电子邮件的内容就是通过base64转码后传输的.Base64-encoded后, 数据要比原始数据多占用 33% 左右的空间. ...
- Jenkins中的一些问题解决(~~不断更新~~)
请使用ctrl+F,查询页面中你需要查找的错误信息(注意空格的输入) 1.错误"error fetching remote repo origin" 本地有多个sshkey,导致构 ...
- Java 9 揭秘(17. Reactive Streams)
Tips 做一个终身学习的人. 在本章中,主要介绍以下内容: 什么是流(stream) 响应式流(Reactive Streams)的倡议是什么,以及规范和Java API 响应式流在JDK 中的AP ...
- java 基础知识及Servlet基础
- 电脑只能上QQ,不能上网浏览网站怎么解决
这个问题通常是因为网络的DNS解析出错引起的.QQ一类的聊天软件有自动的网络解析,不需要DNS便可以使用,而一般的浏览器是需要DNS解析来访问网页的.所谓DNS,即域名服务器(Domain Name ...
- 用u盘启动计算机
上次只是做好了u盘启动盘,但是并没有说怎么安装系统.接下来说一下怎么装系统.链接:怎么把系统装进u盘(ultraiso) 电脑经常要用到u盘启动.设置u盘启动在bios设置里面进行设置.下面就来讲解一 ...
- setInterval()的时间参数无法随参数的变化而变化
2017-04-18 写了个随机抽奖的小案例,打算随机跳动十次,每次变化的时间越来越长,也就是跳动的速度越来越慢,结果发现setInterval的时间参数并不会随着变化. <!--案例的结构如下 ...
- 四、什么是vuex
一.关于vuex刚开始学习的时候对于里面的很多名词有很陌生.很难接受这个定义,下面这个链接很好很简单通俗的解释了什么是vuex 我喜欢的vuex网址:https://zhuanlan.zhihu.co ...