yieldRepeatIO creates memory leak when not using IO #1498
Replies: 4 comments 3 replies
-
|
Forgot to add, the problem with the code is that it halts on the first yieldRepeatIO and if we substitute for a normal yield then it halts on the second (duh, they are internally the same type) and it seems it accumulates memory until there is no more memory left but the program doesn't crash or I just haven't waited long enough. |
Beta Was this translation helpful? Give feedback.
-
|
You appear to be using IO, so not sure what the title means? The pipe only needs to yield, not yieldRepeat. Make sure you test in a Release build, as sometimes the debugging info can cause a the leak. If the leak remains then you can avoid it by manually implementing Applicative.Actions Finally, just lifting IO.pure may well cause an issue as the internal binding of IO may not bounce on the trampoline, so try it with file streaming, or some other real IO rather than already-evaluated IO. Let me know how you get on. |
Beta Was this translation helpful? Give feedback.
-
|
Sorry for not being clear, what I mean by "not using IO" is setting M to be StateT<S, IO> instead of IO. Also this is a problem that I originally enconterred with this code public static ProducerT<Socket, M, Unit> createServer(IPAddress address, int port) =>
from server in IO.lift(() =>
{
Socket server = new(
AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.IP
);
// This is only set to fix a small problem that the
// challenge has with opening and closing connections
// really quickly
server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
server.Bind(new IPEndPoint(address, port));
server.Listen(128);
return server;
})
from _1 in ProducerT.yieldRepeatIO<M, Socket>(
from client in IO.liftAsync(server.AcceptAsync)
from _ in IO.lift(() => Log.Information("New client"))
select client
)
select unit;The pure there is just to simplify the example. Also running it in Release doesn't make a change. Will come back later (or tomorrow) with the Actions override. |
Beta Was this translation helpful? Give feedback.
-
|
I tested with a bespoke public static K<Application, A> Actions<A>(IEnumerable<K<Application, A>> fas) =>
new Application<A>(
from s in StateT.get<IO, ApplicationState>()
from r in fas.Select(fa => fa.As().Run.Run(s)).Actions()
from _ in StateT.put<IO, ApplicationState>(r.State)
select r.Value);
The reason this worksIf you look at the source for The public static virtual K<F, A> Actions<A>(IEnumerable<K<F, A>> fas)
{
K<F, A>? ra = null;
foreach (var fa in fas)
{
ra = ra is null
? fa
: F.Action(ra, fa);
}
if(ra is null) throw Exceptions.SequenceEmpty;
return ra;
}That is a naive implementation that simply chains many Now that I have the |
Beta Was this translation helpful? Give feedback.

Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
As the title says. Here is a code that exemplifies this problem:
This is in the latest version (language v5-beta54)
The commented run is for IO, which if you substitue for M is going to work as expected.
Beta Was this translation helpful? Give feedback.
All reactions