maths / moodle-qtype_stack

Stack question type for Moodle
GNU General Public License v3.0
140 stars 148 forks source link

maximum of variables #853

Closed paulschwarz-htw closed 5 months ago

paulschwarz-htw commented 2 years ago

Hello,

with the help of a student i created an complex exercise (see attachment). We wrote it in an editor and wanted to import it to moodle.

When trying to open the preview, there occurs an error: "Diese Seite funktioniert nicht. moodle.htw-berlin.de kann diese Anfrage momentan nicht verarbeiten. HTTP ERROR 500"

So i tried to implement this whole exercise with the moodle-editor by filling every prt by copy+paste the source-code.

It works fine, but at some point the error 500 occurs again.

So i called the moodle-admin and he looked at the error-log and told me that there is a problem with the max_input_vars. It is set to 1000.

So my question is: can the problem be solved by just setting that limit to a higher number? Are there any restrictions?

Another solution would probably simplifying this monster.

Thank you Paul

Brennweite (FF) (v3_beta)_Gerry.txt

aharjula commented 2 years ago

Hi, I am not aware of any limits inside of STACK that would not allow you to have an arbitrarily large number of PRTs or nodes in them. However, at some point, the evaluation times (mainly just the transfer times for all the logic and its results) will become too long, and one needs to think about splitting things into separate questions. Personally, I think that going past 50 PRTS and 50 inputs is probably going too far, but as long as it works for you, all is fine.

That limit is actually something that Moodle mentions in their documentation. So I would recommend just raising it to 5k.

paulschwarz-htw commented 2 years ago

We will try. Thank you.

paulschwarz-htw commented 2 years ago

We changed the max variables to 5000 but the error still occurs.

When trying to copy the text of prt66 into prt66 in question_BW and saving afterwards, our STACK-system crashes with no errorlog. Makes it hard to find a solution.

Any suggestions?

question_BW.txt prt66.txt

sehomer commented 1 year ago

Hello,

I am member of the moodle team on Pauls school. We raised the max input vars to the recommended 5k. Afterwards the a different error occurs - the php memory limit was exceeded. We raised it in to steps, my colleague will provide details here.

It only works with a raised limit to 512mb, but we hesitate to raise it on our productive site.

@aharjula stated, that going past 50 PRTS and inputs is too far :D Paul uses about 90. Raising limits may help authoring this questions but we expect failures when a certain number of students are running tests using these questions.

Best regards Sebastian

sangwinc commented 1 year ago

Sebastian,

90 PRTs was certainly way more than I ever imagined. I have to confess I'm horrified and bewildered at the prospect of having to maintain such a monster sized question!

Honestly, there will always be limits on size and complexity. Is there really no educational way this material could be split into sub-sections? Each having its own question?

I'm not trying to stifle ambition or innovation, but this sounds quite extreme. I'd certainly like to find out more though. Could you email me at Edinburgh and I'd be happy to chat about these questions.

Chris

sehomer commented 1 year ago

Hi Chris,

That's what I tell Paul since years :D

Edit: He promised to split his questions.

Best regards Sebastian

aharjula commented 1 year ago

The memory usage seems odd, but it could be that you are using one of the latter 4.3 versions of STACK that did rather expensive security validation, which used massive amounts of memory. You might want to upgrade to 4.4.1 and see if that would help (maybe try in a test environment so that you don't break too much), 4.4 replaced that style of validation with something else. Although the way it works, it might suffer from that many PRTs in different ways.

But I am sure that Chris can better figure out what is actually happening.

In any case, maintaining such monsters must be hard, and that is the primary version why one should not build such things. Nevertheless, we should always aim for the system to be able to deal with arbitrary numbers of things, but we can never get past the fact that more things will take more time no matter how small an amount of time singular things take. I wouldn't add a feature that blocks the creation of extra PRTs/inputs or anything else, but maybe we should start warning about that at some point.

paulschwarz-htw commented 1 year ago

Hi Chris, splitting in subquestions would be possible if there were global variables. I'm using STACK in the physics laboratory. Students do their measurements and note the results. Then they have to calculate sth. for analysis and afterwards they have to give the results and measurement erros in correct rounded numbers.

So i need to calculate myself the correct answer for each input from the measurement-inputs to verify if the student calculated correct.

It would be nice and handy to do the correct calculation one time and write it to global variables instead of doing the calculation in every prt.

jojoob commented 1 year ago

We raised it in to steps, my colleague will provide details here.

Some details for the sake of completeness: After we raised the max_input_vars to 5000 as it is recommended by the Moodle docs in generell we now face extreme memory consumption caused by the question. We experimented with raising PHP memory_limit to 512M (256M was still not enough). We just raised the memory_limit for the script that is causing the "allowed memory size exhausted" messages: Added ini_set('memory_limit', '512M'); at the beginning of the peg_parseIdentifierStart() function inside question/type/stack/stack/maximaparser/autogen/parser.mbstring.php. But this not something we want to do in our production environment actually.

The original error message is:

Allowed memory size of 134217728 bytes exhausted (tried to allocate 10485760 bytes) in /var/www/moodle/question/type/stack/stack/maximaparser/autogen/parser.mbstring.php on line 2358, referer: https://moodle.htw-berlin.de/question/question.php?returnurl=%2Fquestion%2Fedit.php%3Fcourseid%3D14826%26cat%3D242192%252C475960&courseid=14826&id=8189883&makecopy=1
sangwinc commented 1 year ago

It would be nice and handy to do the correct calculation one time and write it to global variables instead of doing the calculation in every prt.

Yes, this is a very interesting suggestion. It might be possible to have a "global feedback variables", the result of which are available to each PRT. The technical challenge is deciding what to do with invalid inputs. That's really the key feature of the design: we separate validity from correctness, and PRTs are only executed when all the associated inputs are valid. There are choices for when to execute "global feedback variables" but each has its on set of compromises, I think!

aharjula commented 1 year ago

Ok. So we have the LAB-question example that has been asked for at all the events Stateful or "STACK with state has been" demoed. Basically, a set of inputs that are asked for only once and stay static after that need to be shared between distinct logical parts of the set of questions. If they stayed static, i.e. we could ensure that they stayed static, testing for their features would be much simpler and would only need to be done once with the result stored in some "state". That state then being accessible by the latter subquestions. Problem is that in STACK there is no such thing as write-once inputs or input that can be toggled as read-only at some point, all of this needs to happen in some sort of scripting logic outside of STACK.

Basically, one could probably do this with the script-based "STACK with adaptive flow control" that @m-r-k has built and thus cut down the repetition in the PRTs. However, if the number of PRTs stays the same or grows further, that solution will still reach some limits. If Stateful had a publicly available editor (someday I will magically have time to build such), then it could provide means to push further as in it, we no longer evaluate all the PRTs that the question has, we only evaluate the ones present in the "scene"/subquestion and everything else comes from the state, with it the question could be divided to separate phases of smaller scale and evaluated much more efficiently.

Given that neither of those solutions is exactly easy even if available and transitioning to them might not be easy... I have to sketch out an alternative that requires some scripting but has been seen in the wild:

  1. The first question collects the data and does validation of the sensibility of the data. IT then generates feedback that contains a script payload.
  2. All other related questions exist on the same page and have a hidden input field (typically, it has an interesting name and the script above would target all inputs having such a name) that receives that payload from that script. The payload being the inputted data values, and maybe some pre-evaluated validity details.
  3. This solution requires that once the data has been correctly received, it cannot be modified further. Basically, the initial scripting must disable the inputs through which it was received.
  4. The questions receiving the data must include logic to keep their own inputs and possibly even the question hidden until the data has been received to the hidden input field.

That structure can also be used to build chains of questions, but it is a cumbersome way of doing this. However, it does simplify the handling of the separated questions.

Similarly, hidden inputs can be used as state inside the question:

  1. At the phase where the data gets validated, again validate it in the relevant PRT and add scripting to the feedback generated to stop modification once it is good enough, but in addition, also set some hidden inputs value to describe how good it is.
  2. In the PRTs that need to have that input data validated, use the value of the hidden input. Note that the value does not exist before the data has been submitted once, and a new request gets made as the hidden input needs to be passed through the browser.
  3. Basically, one must keep the parts of the question that rely on the data hidden or disabled until the hidden input has values that they can use. I.e. needs a mandatory scene switch of some sort.

None of these solutions really works if we need to keep the option of editing the original data open during the whole sequence of questions, but I have not heard that that is a common need.

And finally, like Chris said, common code shared by input is a problem, as earlier discussed in #763, the second, we need to deal with a block of code that relies on more than one input it needs to deal with the possibility of not all of them being valid. And that is a big problem. The closest to a solution I have ever come has been the idea of tying input validity to other inputs, i.e. an input not being valid if any of the inputs it ties to are not valid, but even that fails if these "validity sets" do not perfectly cover all the required inputs sets of all the places where things are used. In that model, one would be able to add preprocessing code that could be shared and tie it to such validity sets as long as the code only requires inputs belonging to the set, after all that the triggering of a PRT would no longer depend on the validity of the inputs the PRT requires it would now depend on those inputs validity sets and that could become a mess. Not to mention of the fun of having to design the authoring UI that connects blocks to specific "validity sets", especially if there are intersecting sets...

sangwinc commented 5 months ago

We're always going to hit limits on questions, but I don't see any outstanding actions for this issue.