0

I have a Symfony function that need a lot of optimization. This function compares a question with all it's answers to calculate a mark for each answer. Problem is each question has around 1000 answer. Each exam has up to 60 questions. All question fields and reponse fields are boolean. Question and reponses are objects. How can I do to make this faster and consumes less memory ?

public function correctionReponseTest($question)
{
    $reponses = $question->getReponses();
    if ($question->getMultipleChoices())
        $bareme = $this->_em->getRepository(Bareme::class)
            ->findOneBy(['nom' => 'QCM']);
    else
        $bareme = $this->_em->getRepository(Bareme::class)
            ->findOneBy(['nom' => 'QCS']);

    $item1V = $question->getItem1Vrai();
    $item2V = $question->getItem2Vrai();
    $item3V = $question->getItem3Vrai();
    $item4V = $question->getItem4Vrai();
    $item5V = $question->getItem5Vrai();
    $item1A = $question->getItem1Annule();
    $item2A = $question->getItem2Annule();
    $item3A = $question->getItem3Annule();
    $item4A = $question->getItem4Annule();
    $item5A = $question->getItem5Annule();


    foreach ($reponses as $reponse) {
        $repA = $reponse->getA();
        $repB = $reponse->getB();
        $repC = $reponse->getC();
        $repD = $reponse->getD();
        $repE = $reponse->getE();
        $repAv = $reponse->getAv();
        $repBv = $reponse->getBv();
        $repCv = $reponse->getCv();
        $repDv = $reponse->getDv();
        $repEv = $reponse->getEv();
        $repV = $reponse->getV();
        if (!$reponse || ($repA == null && $repAv == null && $repB == null &&
                $repBv == null && $repC == null && $repCv == null &&
                $repD == null && $repDv == null && $repE == null &&
                $repEv == null && $repV == null)
        ) {
            $nbBonnesReponses = 0;
        } 
        else {
            if ($repV) {
                $nbBonnesReponses =
                    (($item1V == $repAv) || ($item1A))
                    + (($item2V == $repBv) || ($item2A))
                    + (($item3V == $repCv) || ($item3A))
                    + (($item4V == $repDv) || ($item4A))
                    + (($item5V == $repEv) || ($item5A));
            } 
            else {
                $nbBonnesReponses =
                    (($item1V == $repA) || ($item1A))
                    + (($item2V == $repB) || ($item2A))
                    + (($item3V == $repC) || ($item3A))
                    + (($item4V == $repD) || ($item4A))
                    + (($item5V == $repE) || ($item5A));
            }
        }
        $reponse->setNote($bareme->getScore($nbBonnesReponses));
        $this->_em->flush();
    }
}

QC table structure :

CREATE TABLE `qc` (
`id` int(11) NOT NULL,
`ordre` int(11) DEFAULT NULL,
`titre` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`enonce` longtext COLLATE utf8_unicode_ci,
`item1` longtext COLLATE utf8_unicode_ci,
`item2` longtext COLLATE utf8_unicode_ci,
`item3` longtext COLLATE utf8_unicode_ci,
`item4` longtext COLLATE utf8_unicode_ci,
`item5` longtext COLLATE utf8_unicode_ci,
`corrige_item1` longtext COLLATE utf8_unicode_ci,
`corrige_item2` longtext COLLATE utf8_unicode_ci,
`corrige_item3` longtext COLLATE utf8_unicode_ci,
`corrige_item4` longtext COLLATE utf8_unicode_ci,
`corrige_item5` longtext COLLATE utf8_unicode_ci,
`item1_vrai` tinyint(1) DEFAULT NULL,
`item2_vrai` tinyint(1) DEFAULT NULL,
`item3_vrai` tinyint(1) DEFAULT NULL,
`item4_vrai` tinyint(1) DEFAULT NULL,
`item5_vrai` tinyint(1) DEFAULT NULL,
`multiple_choices` tinyint(1) DEFAULT NULL,
`inclu` tinyint(1) DEFAULT NULL,
`donnees` longtext COLLATE utf8_unicode_ci,
`item1_Annule` tinyint(1) DEFAULT NULL,
`item2_Annule` tinyint(1) DEFAULT NULL,
`item3_Annule` tinyint(1) DEFAULT NULL,
`item4_Annule` tinyint(1) DEFAULT NULL,
`item5_Annule` tinyint(1) DEFAULT NULL,
`qcPere` int(11) DEFAULT NULL,
`id_colle` int(11) DEFAULT NULL,
`id_tuteur` int(11) DEFAULT NULL,
`coefficient` decimal(10,2) DEFAULT '1.00'
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
4
  • just thoughts. I would expect to see arrays used more. i.e. $questionItem[$itemIdx] = $question->getItemVrai($itemIdx);. However, I would need to see the database table structure, some sample table data and expected output. I suspect that the information that should be stored as rows is being stored as columns. I suspect that the code can have a lot of the hard-coded variable names removed and still be easy to understand. Commented Feb 8, 2017 at 14:55
  • Actually, you are right. I already thought of creating an Item entity. I even tried once but I have 2 problems with that : - I want my Question entity to have only 5 Items Entity for now and I don't know how to set the limit, create each Question with its 5 Items easily and to set a specific order for these Items. - I'm afraid of the performance hurt of multiplying entities especially when all the calculation is already taking a lot of time. I updated my question with table structure. Commented Feb 8, 2017 at 16:33
  • 1
    I would suggest that you always try the simplest 'natural relation' with SQL and this is row for repeated items not columns. imo, you don't have anywhere near enough data to cause performance issues on a desktop pc. Commented Feb 8, 2017 at 16:46
  • Ok then I'll try that. I also think it's a better idea. Commented Feb 8, 2017 at 17:00

1 Answer 1

1

Calling flush will commit changes to db. Since you do not retrieve any new information from db while doing the loop (?), you dont have to run flush() until after the loop.

So move flush() outside of the loop.

Sign up to request clarification or add additional context in comments.

1 Comment

I moved flush outside the loop and it's already working better. Thanks a lot

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.