jexx;10930053 wrote:This works but is VERY slow.. presumably as it has to check each $user against each $id..
Unlikely. And the below shows why. But, while I will show how you can get around the minor difference with and without comparison, this mainly deals with excessive amounts of data. And in my opinion, having 1M or 100k options in a select box is not a good idea.
So, let's start with avoiding the if check, and then we can move on to see what really might screw up performance
$numberOfUsers = 10000;
$user = rand(1, $numberOfUsers);
$ids = array();
for ($i = 1; $i <= $numberOfUsers; ++$i) {
$ids[] = $i;
}
$sel = 'selected="selected"';
echo '<select>';
$start = microtime(true);
$max = count($ids);
for ($i = 1; $i < $user; ++$i) {
echo "<option value=\"$i/>$i</option>";
}
echo "<option selected=\"selected\" value=\"$user/>$user</option>";
for ($i = $user + 1; $i <= $numberOfUsers; ++$i) {
echo "<option value=\"$i/>$i</option>";
}
echo '</select><br/>';
$end = microtime(true);
$diff = $end - $start;
echo 'Preselected user from set of '.$numberOfUsers.': ' . $diff . ' seconds<br/><br/>';
The above runs just as fast as the code to create a select box without selecting a specific option.
But, the difference between your old code and not preselecting anything is only about 7-10%. Not necessarily acceptable, but I didn't get the impression that this is the performance loss you are talking about.
$numberOfUsers = 10000;
$user = rand(1, $numberOfUsers);
$ids = array();
for ($i = 1; $i <= $numberOfUsers; ++$i) {
$ids[] = $i;
}
$sel = 'selected="selected"';
echo '<select>';
$start = microtime(true);
for ($i = 0; $i < count($ids); ++$i) {
echo '<option value="'.$i.'"';
if ($user === $i)
echo ' selected="selected"';
echo "/>$i</option>";
}
$end = microtime(true);
echo '</select><br/>';
$diff = $end - $start;
echo 'Preselected user in: ' . $diff . ' seconds<br/><br/>';
echo '<select>';
$start = microtime(true);
for ($i = 0; $i < count($ids); ++$i) {
echo '<option value="'.$i."\"/>$i</option>";
}
$end = microtime(true);
$diff2 = $end - $start;
echo '</select><br/>';
echo 'Without preselection in: ' . $diff2 . ' seconds<br/><br/>';
$ratio = $diff / $diff2;
echo "diff takes $ratio times longer than diff2";
However, as you change $numberOfUsers from 100 to 1000 to 10000, the increase in time is, as expected, a factor of 10 for each step. As you go from 10k to 100k users, the increase is a factor of 100! So, trying to find out why...
$start = microtime(true);
ob_start();
$max = count($ids);
for ($i = 1; $i <= $max; ++$i) {
echo '<option value="'.$i.'"';
if ($user === $i)
echo ' selected="selected"';
echo "/>$i</option>";
}
// do everything as before, but never actually send output for options to browser
ob_end_clean();
$end = microtime(true);
And we're down to a time increase at a factor of 10 again.
So, what happens when executing the same code in the terminal?
1M: 8.1199219226837 seconds
100k: 1.2817740440369 seconds
10k: 0.11685013771057 seconds
So, it looks fine in the terminal. One last check
$max = count($ids);
for ($i = 1; $i <= $max; ++$i) {
echo '<option value="'.$i.'"';
if ($user === $i)
echo ' selected="selected"';
echo "/>$i</option>";
}
// Calculate the time the above took without actually sending anything to the browser first.
$end = microtime(true);
// And then send the output.
ob_end_flush();
Sure enough, we're down to 0.5 seconds for 100k options, and the time increase factor correlates with the increase in number of options again.
My GUESS is that the webserver puts the script on hold until it has caught up with sending data. I'd appreciate it if anyone can tell me what really is happening.
Another possibly slow part is pulling all those ids from a non indexed db.