views:

53

answers:

0

I'm currently trying to optimize a "bottleneck" function that is called really ofen in an application.

In the application in question, options can be selected. But some options can be restricted by other. For example, when option "A" is selected, it restricts the selection of option "B".

These restriction links are saved to a table which have this structure:

option_restrictions
    option_code_1    varchar(20)
    option_code_2    varchar(20)

Also some options are options packages. For exemple, option "Fruit" consist of the package of option "Apple", "Orange", "Kiwi".

Those are defined this way in the table:

option_packages
    option_code        varchar(20)
    option_included    varchar(20)

Currently the "bottleneck" function do this:

  1. Check if 2 specified options restricts each other.
  2. If not, it checks if option 1 is an option package and if so, retreive all of it's options and check if any is restricted by option 2.
  3. If not, it checks if option 2 is an option package and if so, retreive all of it's options and check if any is restricted by option 1.
  4. If not it returns false (no restriction).

Here is the actual code I'm trying to optimize:

//Returns true if options restricts each other, false otherwise
function restriction($option_1, $option_2) {
    global $conn;

    //Pass 1 check is each option restrict themselves
    $sql_restriction = "select * from option_restrictions where (option_code_1 = '".$option_1."' or option_code_1 = '".$option_2."') and (option_code_2 = '".$option_1."' or option_code_2 = '".$option_2."')";
    $res_restriction = mysql_query($sql_restriction, $conn);
    if (mysql_num_rows($res_restriction)>0) {
        log_action('End restriction(' . $option_1 . ', ' . $option_2 . ')');
        return true;
    } else {
        //Pass 2 check if option 1 is a package and if so test it's options against option 2
        $sql_option_1_composante = "select * from option_packages where option_code = '".$option_1."'";
        $res_option_1_composante = mysql_query($sql_option_1_composante, $conn);
        if (mysql_num_rows($res_option_1_composante)>0) {
            while ($option_1_composante = mysql_fetch_array($res_option_1_composante)) {
                if (restriction($option_1_composante["option_included"], $option_2)) {
                    return true;
                }
            }
        }
        //Pass 3 check if option 2 is a package and if so test it's options against option 1
        $sql_option_2_composante = "select * from option_packages where option_code = '".$option_2."'";
        $res_option_2_composante = mysql_query($sql_option_2_composante, $conn);
        if (mysql_num_rows($res_option_2_composante)>0) {
            while ($option_2_composante = mysql_fetch_array($res_option_2_composante)) {
                if (restriction($option_2_composante["option_included"], $option_1)) {
                    return true;
                }
            }
        }
    }

    return false;
}

The recursive calls/loops are killing the system ATM... For a single page load this function can be called over 15,000 times which lead to page load of 30secs/4mins!

I'm trying to optimize as much as I can. I've tryed to merge pass 2 and 3 together and to remove the recursive call... Any ideas welcome!

FYI, I know this is maybe not the best design but this function is part of a leviathan system I have no control over nor the ressources/time to change ATM.