Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 6638053
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 25, 20262026-05-25T23:23:21+00:00 2026-05-25T23:23:21+00:00

I recently found a presentation about F# for Python programmers , and after watching

  • 0

I recently found a presentation about F# for Python programmers, and after watching it, I decided to implement a solution to the “ant puzzle” on my own.

There is an ant that can walk around on a planar grid. The ant can move one space at a time left, right, up or down. That is, from the cell (x, y) the ant can go to cells (x+1, y), (x-1, y), (x, y+1), and (x, y-1). Points where the sum of the digits of the x and y coordinates are greater than 25 are inaccessible to the ant. For example, the point (59,79) is inaccessible because 5 + 9 + 7 + 9 = 30, which is greater than 25. The question is: How many points can the ant access if it starts at (1000, 1000), including (1000, 1000) itself?

I implemented my solution in 30 lines of OCaml first, and tried it out:

$ ocamlopt -unsafe -rectypes -inline 1000 -o puzzle ant.ml
$ time ./puzzle
Points: 148848

real    0m0.143s
user    0m0.127s
sys     0m0.013s

Neat, my result is the same as that of leonardo’s implementation, in D and C++. Comparing to Leonardo’s C++ implementation, the OCaml version runs approx 2 times slower than C++. Which is OK, given that Leonardo used a queue to remove recursion.

I then translated the code to F# … and here’s what I got:

Thanassis@HOME /g/Tmp/ant.fsharp
$ /g/Program\ Files/FSharp-2.0.0.0/bin/fsc.exe ant.fs
Microsoft (R) F# 2.0 Compiler build 2.0.0.0
Copyright (c) Microsoft Corporation. All Rights Reserved.

Thanassis@HOME /g/Tmp/ant.fsharp
$ ./ant.exe

Process is terminated due to StackOverflowException.
Quit

Thanassis@HOME /g/Tmp/ant.fsharp
$ /g/Program\ Files/Microsoft\ F#/v4.0/Fsc.exe ant.fs
Microsoft (R) F# 2.0 Compiler build 4.0.30319.1
Copyright (c) Microsoft Corporation. All Rights Reserved.

Thanassis@HOME /g/Tmp/ant.fsharp
$ ./ant.exe

Process is terminated due to StackOverflowException

Stack overflow… with both versions of F# I have in my machine…
Out of curiosity, I then took the generated binary (ant.exe) and run it under Arch Linux/Mono:

$ mono -V | head -1
Mono JIT compiler version 2.10.5 (tarball Fri Sep  9 06:34:36 UTC 2011)

$ time mono ./ant.exe
Points: 148848

real    1m24.298s
user    0m0.567s
sys     0m0.027s

Surprisingly, it runs under Mono 2.10.5 (i.e. no stack overflow) – but it takes 84 seconds, i.e. 587 times slower than OCaml – oops.

So this program…

  • runs fine under OCaml
  • doesn’t work at all under .NET/F#
  • works, but is very slow, under Mono/F#.

Why?

EDIT: Weirdness continues – Using “–optimize+ –checked-” makes the problem disappear, but only under ArchLinux/Mono ; under Windows XP and Windows 7/64bit, even the optimized version of the binary stack overflows.

Final EDIT: I found out the answer myself – see below.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-25T23:23:21+00:00Added an answer on May 25, 2026 at 11:23 pm

    Executive summary:

    • I wrote a simple implementation of an algorithm… that wasn’t tail-recursive.
    • I compiled it with OCaml under Linux.
    • It worked fine, and finished in 0.14 seconds.

    It was then time to port to F#.

    • I translated the code (direct translation) to F#.
    • I compiled under Windows, and run it – I got a stack overflow.
    • I took the binary under Linux, and run it under Mono.
    • It worked, but run very slowly (84 seconds).

    I then posted to Stack Overflow – but some people decided to close the question (sigh).

    • I tried compiling with –optimize+ –checked-
    • The binary still stack overflowed under Windows…
    • …but run fine (and finished in 0.5 seconds) under Linux/Mono.

    It was time to check the stack size: Under Windows, another SO post pointed out that it is set by default to 1MB. Under Linux, “uname -s” and a compilation of a test program clearly showed that it is 8MB.

    This explained why the program worked under Linux and not under Windows (the program used more than 1MB of stack). It didn’t explain why the optimized version run so much better under Mono than the non-optimized one: 0.5 seconds vs 84 seconds (even though the –optimize+ appears to be set by default, see comment by Keith with “Expert F#” extract). Probably has to do with the garbage collector of Mono, which was somehow driven to extremes by the 1st version.

    The difference between Linux/OCaml and Linux/Mono/F# execution times (0.14 vs 0.5) is because of the simple way I measured it: “time ./binary …” measures the startup time as well, which is significant for Mono/.NET (well, significant for this simple little problem).

    Anyway, to solve this once and for all, I wrote a tail-recursive version – where the recursive call at the end of the function is transformed into a loop (and hence, no stack usage is necessary – at least in theory).

    The new version run fine under Windows as well, and finished in 0.5 seconds.

    So, moral of the story:

    • Beware of your stack usage, especially if you use lots of it and run under Windows. Use EDITBIN with the /STACK option to set your binaries to larger stack sizes, or better yet, write your code in a manner that doesn’t depend on using too much stack.
    • OCaml may be better at tail-recursion elimination than F# – or it’s garbage collector is doing a better job at this particular problem.
    • Don’t despair about …rude people closing your Stack Overflow questions, good people will counteract them in the end – if the questions are really good 🙂

    P.S. Some additional input from Dr. Jon Harrop:

    …you were just lucky that OCaml didn’t overflow as well.
    You already identified that actual stack sizes vary between platforms.
    Another facet of the same issue is that different language implementations
    eat stack space at different rates and have different performance
    characteristics in the presence of deep stacks. OCaml, Mono and .NET
    all use different data representations and GC algorithms that impact
    these results… (a) OCaml uses tagged integers to distinguish pointers,
    giving compact stack frames, and will traverse everything on the stack
    looking for pointers. The tagging essentially conveys just enough information
    for the OCaml run time to be able to traverse the heap (b) Mono treats words
    on the stack conservatively as pointers: if, as a pointer, a word would point
    into a heap-allocated block then that block is considered to be reachable.
    (c) I do not know .NET’s algorithm but I wouldn’t be surprised if it ate stack
    space faster and still traversed every word on the stack (it certainly
    suffers pathological performance from the GC if an unrelated thread has a
    deep stack!)… Moreover, your use of heap-allocated tuples means you’ll
    be filling the nursery generation (e.g. gen0) quickly and, therefore,
    causing the GC to traverse those deep stacks often…

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I recently found out about livecoding where someone will program something on the fly
I recently found an article online that told me about this: RewriteRule ^mock-up/([^/]+)/([^/]+) /mock-up/index.php?page=$1&section=$2
I recently found out about C# extension methods and wrote this one: /// <summary>
I recently found out about n-grams and the cool possibility to compare frequency of
I've recently found out about protocol buffers and was wondering if they could be
I only recently found out about URL rewriting , so I've still got a
I have recently found myself becoming more negative about EF and cannot help wondering
I recently found out about the awesomeness of the iTunes COM for Windows SDK.
I recently found that there is a command in Vim called compiler. You can
I recently found the add-on for Python called win32api. I am very pleased with

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.