我试图弄清楚C#编译器如何处理尾调用.
(答案:他们不是.但是64位JIT会做TCE(尾部呼叫消除).限制适用.)
所以我使用递归调用编写了一个小测试,它打印了在StackOverflowException杀死进程之前调用它的次数.
class Program
{
static void Main(string[] args)
{
Rec();
}
static int sz = 0;
static Random r = new Random();
static void Rec()
{
sz++;
//uncomment for faster, more imprecise runs
//if (sz % 100 == 0)
{
//some code to keep this method from being inlined
var zz = r.Next();
Console.Write("{0} Random: {1}\r", sz, zz);
}
//uncommenting this stops TCE from happening
//else
//{
// Console.Write("{0}\r", sz); …Run Code Online (Sandbox Code Playgroud) 可能重复:
Visual Studio"任何CPU"目标
我注意到在VS中编译C#代码时,通常有编译32/64位系统的选项,还有一个用于编译任何cpu的选项.
这两个选项有什么区别?选择任何CPU只能编译为中间字节代码,而第一个选项编译为机器代码(这听起来不太可能)?或者是其他东西?
刚刚安装了Visual Studio 11开发人员预览版.在编译指定了AnyCPU目标的托管(C#,VB)应用程序时,我在项目属性中看到一个名为"Prefer 32-bit"的新选项.这似乎不是类库的选项,只是顶级应用程序.
这个标志表示什么?
Any CPU - 首选32位选项有什么作用?
虽然我知道WinRT无法处理exe并且只能运行Windows应用商店应用,但StackOverflow上存在几个问题,它们提出同样的问题并且都引用了这个博客:
在.NET 4.5和Visual Studio 11中,奶酪已被移动.大多数.NET项目的默认设置是AnyCPU,但现在AnyCPU有多个含义.还有一个额外的子类型AnyCPU,"任何CPU 32位首选",这是新的默认值(总体而言,/ platform C#编译器交换机现在有五个选项:x86,Itanium,x64,anycpu和anycpu32bitpreferred ).使用AnyCPU的那种风格时,语义如下:
- 如果进程在32位Windows系统上运行,则它将以32位进程运行.IL被编译为x86机器代码.
- 如果进程在64位Windows系统上运行,则它将以32位进程运行.IL被编译为x86机器代码.
- 如果进程在ARM Windows系统上运行,则它将以32位进程运行.IL编译为ARM机器代码.
但是,购买Surface RT后,我创建了一个Hello World程序,将其设置为Any CPU,检查Prefer 32 Bit标志,编译并将其复制到Surface.当我运行该程序时,操作系统告诉我,它无法运行程序,我应该像任何x86/x64 exe一样关注市场.显示的确切消息是:"此应用程序无法在您的PC上运行.要查找此PC的应用程序,请打开Windows应用商店."
那么这实际上做了什么,是否可以在ARM上为Window RT编译Any CPU应用程序?
根据许多SO答案和这篇被广泛引用的博客文章,为所有选择了'prefer 32-bit'选项的'Any CPU'构建的.NET 4.5应用程序将在32位和64位上作为32位进程运行系统(与.NET 4.0及更早版本不同).换句话说,选择'prefer 32-bit'的x86和AnyCPU是等效的(忽略它是否可以在ARM上运行).
但是,我的测试表明,在64位系统上,"AnyCPU更喜欢32位"应用程序(我确认运行32位)可以分配比x86更多的内存.我编写了一个.NET 4.5 C#控制台应用程序,它在循环中分配10MB字节数组(当然保留引用)直到它遇到OutOfMemoryException,并在具有大量RAM的64位系统上运行它.当构建为x86时,它会分配大约1.2GB.构建为"任何CPU(更喜欢32位)"的相同代码最高可达1.5GB.
为什么不同?
我发誓微软"进化"的Visual Studio越多,整个过程就越无知.
我有一个带有3个类库的Windows服务.我进入了每个类库的属性,并将平台目标设置为x64.我对Windows服务以及我添加的测试控制台项目做了同样的事情来验证所有内容.
我可以在我的Windows 2008 R2 x64服务器上运行控制台应用程序,没有任何问题,但愚蠢的安装程序一直在轰炸并告诉我我的图像不好.我确实确保将安装程序的目标平台设置为x64.
我不知道这个愚蠢的事情会不会爆炸,并且非常感谢任何见解.我确实引用了其他的DLL,那些可能是x86,但我想如果主库已正确设置,事情会起作用......
c# windows-services visual-studio-2010 badimageformatexception
我正在使用BinarySerializer,它有一个非常大的(尽管不是很深)项目图.我有8GB的ram支持12Gig的交换,并且在序列化时我得到一个OutOfMemoryException,这是预期的(图表可能接近或超过2Gb).
然而,当我使用gcAllowVeryLargeObjects它并不是更好,我仍然得到相同的异常,我肯定在应该保留在内存中的东西(至少与交换).
有什么我可以做的来支持序列化这个/一种方法来获得相同的功能集,但可能会得到结果?
我的序列化代码没有什么特别之处:
public static byte[] Serialize(this object o)
{
var ms = new MemoryStream();
var bf = new BinaryFormatter();
bf.Serialize(ms, o);
ms.Position = 0;
return ms.ToArray();
}
Run Code Online (Sandbox Code Playgroud)
我正在序列化的对象包含自身包含数组等的项目数组,但完整的图形本身并不"大"(这是索引数据的结果,在源处,已经只有大约1GB的大小).
这不是由于GC碎片造成的(压缩大堆没有帮助).
我正在编写.NET在Windows Server 2016上运行的应用程序,这些应用程序会对大量文件的大量内容执行http操作.这可以大大加快下载过程,因为您可以并行下载它们.不幸的是,一旦下载它们,将它们全部重新组合在一起需要相当长的时间.
有2-4k个文件需要组合.这将运行的服务器有很多内存,靠近800GB.我认为使用MemoryStreams存储下载的部分直到它们可以顺序写入磁盘是有意义的,但我只能2.5GB在出现System.OutOfMemoryException错误之前消耗大约内存.服务器有数百GB可用,我无法弄清楚如何使用它们.
假设在 x64 Windows 机器上使用最新版本的 Visual Studio 和 C# 并分配大量数据。
果然,在使用默认构建设置(如下图为 VS 2019 Preview 2.1)进行编译时,当您的进程达到 4 GB 时,您将耗尽用户虚拟地址空间。这是意料之中的,这里讨论了原因。
例如,分配本身可以通过创建几百个简单数组来完成,每个数组包含几百万个int元素。
我想了解的是为什么Any CPU/Prefer 32-bit选择 被选为默认构建选项。我也注意到,2015年VS具有相同的默认设置过了,最有可能的每一个出来,因为VS 11,如所描述的版本在这里。
通常被问到的问题是“什么是 AnyCPU...?” 并且已经反复回答(1 2 3 4 5),对定位的优点简要地接触x86/ x64/ Any CPU + Prefer 32-bit。但我还没有找到一个明确的答案,为什么被Any CPU + Prefer 32-bit选为 VS 中的默认设置。
查看默认情况下反对为 x64 构建的原因:
int),实际情况并非如此。当然,对数组本身的引用将是双倍的(8 个字节而不是 4 个字节),但仅此而已。根据“Windows Internals”一书(内存管理章节),页表结构本身的 PFN 条目在 x86 和 x64 架构上都是 64 位宽,只是有 3 …我有一个 .NET 程序会抛出OutOfMemoryException. 异常已被处理,因为该Main函数具有以下结构:
public static int Main(string[] args)
{
try
{
...
}
catch (Exception exc)
{
Console.Error.WriteLine(exc);
return 1;
}
}
Run Code Online (Sandbox Code Playgroud)
现在我希望在抛出此异常时创建内存转储。为此,我使用以下命令:
procdump.exe -e 1 -f OutOfMemoryException -g -ma -w Log4Net2DB.exe
Run Code Online (Sandbox Code Playgroud)
但是,它不起作用:
PS D:\tmp> procdump.exe -e 1 -f OutOfMemoryException -g -ma -w Log4Net2DB.exe
ProcDump v7.0 - Writes process dump files
Copyright (C) 2009-2014 Mark Russinovich
Sysinternals - www.sysinternals.com
With contributions from Andrew Richards
Waiting for process named Log4Net2DB.exe...
Process: Log4Net2DB.exe (47712)
CPU threshold: n/a …Run Code Online (Sandbox Code Playgroud) 我总是绕过构建64位桌面应用程序的问题,因为我不知何故在我脑海里发现这不是一件容易的事情,而且我想我并不是真的理解解决方案"配置管理器"对话框,平台和配置.
无论如何,我只是尝试通过简单地将所有解决方案项目的平台更改为x64来转换现有应用程序,并且它有效.我唯一的问题是其中一个项目引用的C++ DLL,需要重建为x64.
所以我的问题(最后)是:为什么我只有C++ DLL的问题,但我的解决方案中的项目引用的许多.Net程序集DLL都没问题?
究竟是什么决定了我的应用程序是否构建为64位?我将所有解决方案的项目更改为"x64",但如果将它们保留为"任何CPU",它是否仍然有用,我只将WPF(启动)项目更改为"x64"?
编辑
所以最后我似乎只能将所有项目平台设置为"任何CPU"而不是"x64"(TFS服务器无法使用后者运行单元测试).甚至引用非托管64位DLL的项目也很满意(不确定原因).
诀窍是取消选中Prefer 32-bitWPF(启动)项目属性中的选项.构建的应用程序现在作为64位应用程序运行,并且TFS /单元测试运行愉快.