System.OutOfMemoryException for a tail recursive function
I have isolated the problematic code to this function (that uses ASP.NET's Membership class):
let dbctx = DBSchema.GetDataContext()
let rec h1 (is2_ : int) (ie2_ : int) : unit =
match is2_ >= ie2_ with
| true ->
let st2 = query {
for row in dbctx.Tbl_Students do
where (row.Id = is2_)
head}
let l2 =
Membership.FindUsersByEmail (st2.Email_address)
|> Seq.cast<_>
|> Seq.length
match l2 >= 1 with
| true ->
()
| false ->
Membership.CreateUser (st2.Email_address, password, st2.Email_address)
|> ignore
h1 (is2_ - 1) ie2_
| false ->
()
I am getting a System.OutOfMemoryException
after exactly 5626
iterations of h1
. But my system's memory consumption is only at 20 percent
. (I have a very powerful, 16 GB machine.)
Why should the above function overflow the stack? Is it not written tail recursively?
Thanks in advance for your help.
I don't think this is a tail-recursion issue -- if so, you'd be getting a StackOverflowException
instead of an OutOfMemoryException
. Note that even though you have 16GB of memory in your machine, the process your program is executing in may be limited to a smaller amount of memory. IIRC, it's 3GB for some combinations of .NET framework version and OS version -- this would explain why the process is crashing when you reach ~20% memory usage (20% of 16GB = 3.2GB).
I don't know how much it'll help, but you can simplify your code to avoid creating some unnecessary sequences:
let dbctx = DBSchema.GetDataContext()
let rec h1 (is2_ : int) (ie2_ : int) : unit =
if is2_ >= ie2_ then
let st2 = query {
for row in dbctx.Tbl_Students do
where (row.Id = is2_)
head }
let existingUsers = Membership.FindUsersByEmail st2.Email_address
if existingUsers.Count < 1 then
Membership.CreateUser (st2.Email_address, password, st2.Email_address)
|> ignore
h1 (is2_ - 1) ie2_
EDIT : Here's a link to a previous question with details about the CLR memory limitations for some versions of the .NET framework and OS versions: Is there a memory limit for a single .NET process
OutOfMemoryException
usually doesn't have anything to do with the amount of RAM you have. You get it at ~3 GB most likely because your code runs as a 32-bit process. But switching it to 64 bit will only solve your issue if you actually need that much memory and the exception is not caused by some bug.
上一篇: F#中的尾递归:堆栈溢出