jruizgit / rules

Durable Rules Engine
MIT License
1.14k stars 207 forks source link

Get error code: 303 with a large rule set #312

Open zhangyj2003 opened 4 years ago

zhangyj2003 commented 4 years ago

Hi, First, thanks for sharing this project. I first come across this project when I was trying to find a js implementation of forward-chaining rules engine. I really liked it. It is really fast, and it has a very straightforward api. I used this engine in my project. It worked great when the rule set is relatively small. After I added about 500 rules, it started to fail. There is no output from the engine. After some digging, I further narrowed it down. With 483 rules, it started to get error code: 303. With 482 rules, it worked just fine.

/home/van/.nvm/versions/node/v12.11.1/bin/node /home/van/Documents/test/test.js
/home/van/Documents/test/node_modules/durable/libjs/durableEngine.js:305
            return handleResult(r.assertFact(handle, json), json);
                                  ^

Error: Could not assert events, error code: 303
    at that.assertFact (/home/van/Documents/test/node_modules/durable/libjs/durableEngine.js:305:35)
    at handleFunction (/home/van/Documents/test/node_modules/durable/libjs/durableEngine.js:901:33)
    at Object.that.assert (/home/van/Documents/test/node_modules/durable/libjs/durableEngine.js:938:20)
    at Object.assert (/home/van/Documents/test/node_modules/durable/libjs/durable.js:1923:26)
    at Object.<anonymous> (/home/van/Documents/test/test.js:4457:3)
    at Module._compile (internal/modules/cjs/loader.js:945:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:962:10)
    at Module.load (internal/modules/cjs/loader.js:798:32)
    at Function.Module._load (internal/modules/cjs/loader.js:711:12)
    at Function.Module.runMain (internal/modules/cjs/loader.js:1014:10)

Process finished with exit code 1

From the source code, the 303 is defined in rules.h as follows: #define ERR_MAX_STACK_SIZE 303 My knee-jerk reaction is to increase the MAX_STACK_SIZE as defined in events.c. But I still got the same error code. Further investigation showed that the error code is returned by handleAlpha() defined in events.c. Specifically, at line 1697:

                            if (match) {
                                if (top == MAX_STACK_SIZE) {
                                    return ERR_MAX_STACK_SIZE;
                                }

Looking back the outer loop at 1671, since increasing the MAX_STACK_SIZE did not help.: for (entry = currentProperty->hash & HASH_MASK; nextHashset[entry] != 0; entry = (entry + 1) % NEXT_BUCKET_LENGTH) {

With some additional debugging on the looping variable "entry", it shows that it actually reached the limit of NEXT_BUCKET_LENGTH (current defined as 512 in rules.h) and actually started to roll back. Looks like NEXT_BUCKET_LENGTH is the real limiting factor in this case.

In my project, the total number of rules is projected to be around 1000 to 2000. I am not sure if we should linearly increase NEXT_BUCKET_LENGTH. But for the moment, I increased the NEXT_BUCKET_LENGTH to 2048.

After the change, the engine works for my test case, which is attached here (the file name will need to be changed). test.js.txt

My question is how many rules can the engine handle with default settings? What are the implications in increasing NEXT_BUCKET_LENGTH? Can we increase the NEXT_BUCKET_LENGTH or related settings so the engine can handle more rules? In this way, I don't have to have my custom fork.

Thanks again. It is an amazing project.

jiqi

jruizgit commented 4 years ago

Hi, thanks for asking the question. The max number of rules under a single ruleset is limited to MAX_BUCKET_LENGTH (512 right now). Increasing the MAX_BUCKET_LENGTH size means increasing the size of the trie for Alpha nodes. I need to run the benchmarks to get a better understanding of the impact on rules evaluation performance and memory footprint. I will post back on this issue with my findings.