首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >F# NativePtr.stackalloc意外堆栈溢出

F# NativePtr.stackalloc意外堆栈溢出
EN

Stack Overflow用户
提问于 2016-02-18 02:36:22
回答 1查看 216关注 0票数 2

仍在进行F#性能测试,并试图使基于堆栈的数组正常工作。有关更多背景信息,请参见此处:f# NativePtr.stackalloc in Struct Constructor

据我所知,每个函数调用都应该在堆栈中得到自己的框架。然后,通过将堆栈指针向后移动,返回时释放此内存。但是,下面的内容会导致堆栈溢出错误--不确定为什么在函数中执行堆栈溢出。

有趣的是,这只发生在发布模式,而不是调试模式。

我相信dotnet中的标准堆栈大小是1MB,而且我没有调整我的堆栈大小。我希望分配8192个ints (32768字节)不会破坏堆栈。

代码语言:javascript
复制
#nowarn "9"

module File1 =

    open Microsoft.FSharp.NativeInterop
    open System
    open System.Diagnostics    

    let test () =
        let stackAlloc x =
            let mutable ints:nativeptr<int> = NativePtr.stackalloc x
            ()

        let size = 8192            
        let reps = 10000
        let clock = Stopwatch()
        clock.Start()
        for i = 1 to reps do            
            stackAlloc size
        let elapsed = clock.Elapsed.TotalMilliseconds
        let description = "NativePtr.stackalloc"
        Console.WriteLine("{0} ({1} ints, {2} reps): {3:#,##0.####}ms", description, size, reps, elapsed)

    [<EntryPoint>]
    let main argv = 
        printfn "%A" argv
        test ()
        Console.ReadKey() |> ignore
        0

在使用ILSpy进行反编译后更新,正如费奥多·索伊金建议的那样,我们可以看到,在优化过程中已经发生了内衬。有点酷,也有点吓人!

代码语言:javascript
复制
using Microsoft.FSharp.Core;
using System;
using System.Diagnostics;
using System.IO;

[CompilationMapping(SourceConstructFlags.Module)]
public static class File1
{
    public unsafe static void test()
    {
        Stopwatch clock = new Stopwatch();
        clock.Start();
        for (int i = 1; i < 10001; i++)
        {
            IntPtr intPtr = stackalloc byte[8192 * sizeof(int)];
        }
        double elapsed = clock.Elapsed.TotalMilliseconds;
        Console.WriteLine("{0} ({1} ints, {2} reps): {3:#,##0.####}ms", "NativePtr.stackalloc", 8192, 10000, elapsed);
    }

    [EntryPoint]
    public static int main(string[] argv)
    {
        PrintfFormat<FSharpFunc<string[], Unit>, TextWriter, Unit, Unit> format = new PrintfFormat<FSharpFunc<string[], Unit>, TextWriter, Unit, Unit, string[]>("%A");
        PrintfModule.PrintFormatLineToTextWriter<FSharpFunc<string[], Unit>>(Console.Out, format).Invoke(argv);
        File1.File1.test();
        ConsoleKeyInfo consoleKeyInfo = Console.ReadKey();
        return 0;
    }
}

此外,还可注意以下几点:

http://www.hanselman.com/blog/ReleaseISNOTDebug64bitOptimizationsAndCMethodInliningInReleaseBuildCallStacks.aspx

此外,还可以使用属性来调整优化:

https://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.methodimploptions(v=vs.110).aspx?cs-save-lang=1&cs-lang=fsharp#code-snippet-1

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-02-18 03:35:29

如果您的stackAlloc函数是内联的,从而导致stackalloc发生在test的框架内,这就会发生这种情况。这也解释了为什么只能在发行版中发生这种情况:内联是一种优化,在调试中执行的力度要比发行版小得多。

要确认这一点,我将尝试查看使用ILSpy生成的代码。

为什么首先需要使用堆栈分配的数组?这看起来就像唐纳德·克努斯警告我们的那样。:-)

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35471757

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档