-
Notifications
You must be signed in to change notification settings - Fork 32
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Memory overflows cannot be caught #226
Comments
I've been digging into Go issues/proposals related to OOM but it looks like there's no way to tell if allocation succeeds without OOM for sure. We'd be better off just setting a sensible $ scryer-prolog
?- current_prolog_flag(max_arity, X).
X = 1023. |
The limited arity is not the best feature of Scryer. SWI's arity is unbounded too. And just replace |
I see. We should be able to mitigate the risk by limiting Why don't we let it crash, call it a limitation of this processor, and ask users to call |
You can always resort to that at least for standard conformity. For that matter, you can even claim
Limiting Well, it is up to you to decide which way you want to go. |
Instead of allocating a huge chunk of memory right away, we can gradually allocate a large enough chunk for the arguments that are actually referred. In Also, I implemented a sparse list as well. So, it can handle @UWN Do you think this will help in the cases of such overflows? $ go version
go version go1.19.2 darwin/arm64
$ git checkout sparse-compounds
Already on 'sparse-compounds'
Your branch is up to date with 'origin/sparse-compounds'.
$ go install github.com/ichiban/prolog/cmd/1pl
$ $(go env GOPATH)/bin/1pl
Top level for ichiban/prolog (devel)
This is for testing purposes only!
See https://github.com/ichiban/prolog for more details.
Type Ctrl-C or 'halt.' to exit.
?- length(_,E), N is 2^E, writeq(N),nl, catch(functor(F,f,N), Error, true), nonv
ar(Error).
1
2
4
8
16
32
64
128
256
512
1024
2048
4096
8192
16384
32768
65536
131072
262144
524288
1048576
2097152
4194304
8388608
16777216
33554432
67108864
134217728
268435456
536870912
1073741824
2147483648
4294967296
8589934592
17179869184
34359738368
68719476736
137438953472
274877906944
549755813888
1099511627776
2199023255552
4398046511104
8796093022208
17592186044416
35184372088832
70368744177664
140737488355328
281474976710656
562949953421312
1125899906842624
2251799813685248
4503599627370496
9007199254740992
18014398509481984
36028797018963968
72057594037927936
144115188075855872
288230376151711744
576460752303423488
1152921504606846976
2305843009213693952
4611686018427387904
2022/12/24 11:46:07 error(evaluation_error(int_overflow),is/2)
?- |
Replace |
With $ $(go env GOPATH)/bin/1pl
Top level for ichiban/prolog (devel)
This is for testing purposes only!
See https://github.com/ichiban/prolog for more details.
Type Ctrl-C or 'halt.' to exit.
?- length(_,E), N is 2^E, writeq(N),nl, catch(length(L,N), Error, true), nonvar(
Error).
1
2
4
8
16
32
64
128
256
512
1024
2048
4096
8192
16384
32768
65536
131072
262144
524288
1048576
2097152
4194304
8388608
16777216
33554432
67108864
134217728
268435456
536870912
1073741824
2147483648
4294967296
8589934592
17179869184
34359738368
68719476736
137438953472
274877906944
549755813888
1099511627776
2199023255552
4398046511104
8796093022208
17592186044416
35184372088832
70368744177664
140737488355328
281474976710656
562949953421312
1125899906842624
2251799813685248
4503599627370496
9007199254740992
18014398509481984
36028797018963968
72057594037927936
144115188075855872
288230376151711744
576460752303423488
1152921504606846976
2305843009213693952
4611686018427387904
2022/12/26 09:44:27 error(evaluation_error(int_overflow),is/2)
?- |
I don't see your point at all: It seems you are adding quite some complexity to your implementation for handling extremely rare cases. What would be much more helpful (and that was my motivation to give these examples) is to signal actual resource errors such that they can be caught and recovered. Just add |
Can any of existing implementations handle these queries and raise As far as I know, when there's no enough memory, OSs overcommit memory and return unusable memory chunks on |
SICStus and SWI. For SICStus, you have to |
Thank you for the examples. I think our implementation is more like SICStus except Go runtime doesn't let us handle the case of Go has a soft memory limit so I'm going to limit allocation of large chunks of memory to respect the limit. |
You cannot Another way to (partially) address this problem is to provide some mechanism to limit the number of inferences. This helps, at least for the typical cases of non-termination beginners make. |
You can, but Go runtime immediately I'm preparing a fix to respect Go's builtin soft memory limit in #279. You can set the limit with an environment variable $ GOMEMLIMIT=500MiB $(go env GOPATH)/bin/1pl
Top level for ichiban/prolog (devel)
This is for testing purposes only!
See https://github.com/ichiban/prolog for more details.
Type Ctrl-C or 'halt.' to exit.
?- length(_,E), N is 2^E, writeq(N),nl, catch(functor(F,f,N), Error, true), nonv
ar(Error).
1
2
4
8
16
32
64
128
256
512
1024
2048
4096
8192
16384
32768
65536
131072
262144
524288
1048576
2097152
4194304
8388608
16777216
E = 24,
Error = error(resource_error(memory),functor/3),
F = _16780056,
N = 16777216 When combined with
|
Merged the fix and released as $ go install github.com/ichiban/prolog/cmd/1pl@latest
go: downloading github.com/ichiban/prolog v0.15.1
$ GOMEMLIMIT=500MiB $(go env GOPATH)/bin/1pl
Top level for ichiban/prolog v0.15.1
This is for testing purposes only!
See https://github.com/ichiban/prolog for more details.
Type Ctrl-C or 'halt.' to exit.
?- length(_,E), N is 2^E, writeq(N),nl, catch(functor(F,f,N), Error, true), nonv
ar(Error).
1
2
4
8
16
32
64
128
256
512
1024
2048
4096
8192
16384
32768
65536
131072
262144
524288
1048576
2097152
4194304
8388608
16777216
E = 24,
Error = error(resource_error(memory),functor/3),
F = _16780056,
N = 16777216.
?- length(_,E), N is 2^E, writeq(N),nl, catch(length(L,N), Error, true), nonvar(
Error).
1
2
4
8
16
32
64
128
256
512
1024
2048
4096
8192
16384
32768
65536
131072
262144
524288
1048576
2097152
4194304
8388608
16777216
E = 24,
Error = error(resource_error(memory),length/2),
L = _33559888,
N = 16777216.
?- |
Here is a case where this limit is not respected:
|
This is because the memory overflow detection currently implemented can only detect obvious cases such as Since append([], L, L).
append([X|L1], L2, [X|L3]) :- append(L1, L2, L3). Maybe we should implement another layer of memory overflow detection for tiny memory allocations which detects overflows after allocating a tiny object and exceeding the soft memory limit. |
There is no need to have very precise overflow detection. It could be performed every nth inference only. |
What is really nice is that you have chosen
current_prolog_flag(max_arity, unbounded)
!Expected: Error = error(resource_error(memory), _Imp_def).
The text was updated successfully, but these errors were encountered: