使用PHP和MySQL的规划生成函数中的内存泄漏问题

rryofs0p  于 2023-10-15  发布在  PHP
关注(0)|答案(1)|浏览(122)

我在WordPress应用程序中执行特定的PHP函数时遇到了与内存泄漏相关的问题,该函数在两个日期之间生成计划,我希望获得有关如何解决此问题的指导。

功能

该函数旨在基于两个MySQL查询和后续结果处理来获取和生成规划数据。

验证码

下面是我的代码中似乎发生内存泄漏的部分:

while ($current_date <= new DateTime($end_date)) {
    
        // Convert the $current_date object to a string.
        // $current_date_string = $current_date->format('Y-m-d H:i:s');
        
        // Output the $current_date_string variable to the console.
        // debug_to_console('$current_date : ' . $current_date_string);

        if ($current_date->format('N') == $day_of_week) {  // Check if current date is the correct week_day
            
            // debug_to_console('$adjustment[$day_of_week] : ' . $adjustment[$day_of_week]);
            
            
            // Check if $day_of_week is included in $adjust_occurrence and there are remaining skips
            if (isset($adjust_occurrence[$day_of_week]) && $adjustment[$day_of_week] > 0) {
             debug_to_console('$adjustment[$day_of_week] : ' . $adjustment[$day_of_week]);
               $adjustment[$day_of_week]--;  // Decrement the adjustment count
                $current_date->add($interval);
                continue;  // move to the next while loop iteration
            }
            
            if( $current_date < $intervention_date) {
          
                // Move to the next day within the same week if it's not the correct week_day
                $current_date->add(new DateInterval('P1D'));
                continue;
            }else {
                  // Register it in the array if it is the relevant day and you don't have to skip
                    $new_repeat = clone $repeat;
                    $new_repeat->intervention_date = $current_date->format('Y-m-d');
                    $repeated_interventions_array[] = $new_repeat;
        
                    // Move to the next occurrence
                    $current_date->add($interval);
            }

          
        } else {
            // Move to the next day within the same week if it's not the correct week_day
            $current_date->add(new DateInterval('P1D'));
        }
    }
}

    // filter modified array 
    // ... your existing code up to the nested foreach loops ...

    
    // Your existing query to fetch modifications
    $modified_repeats = $wpdb->get_results($wpdb->prepare(
        "SELECT *
        FROM {$wpdb->prefix}intervention_modification_reference r 
        WHERE r.intervenant_name = %s",
        $intervenant_name
    ));
    // Create a map for quick lookup
    $intervention_map = [];
    foreach ($repeated_interventions_array as $key => $repeated_intervention) {
        $unique_key = $repeated_intervention->intervention_date . $repeated_intervention->start_time . $repeated_intervention->client . $repeated_intervention->intervenant_name;
        $intervention_map[$unique_key] = $key;
    }
    
    // Loop through the modified repeats
    foreach ($modified_repeats as $modified_repeat) {
        $unique_key = $modified_repeat->intervention_date . $modified_repeat->start_time . $modified_repeat->client . $modified_repeat->intervenant_name;
        if (isset($intervention_map[$unique_key])) {
            $key = $intervention_map[$unique_key];
            $repeated_interventions_array[$key]->intervention_date = $modified_repeat->update_intervention_date;
            $repeated_interventions_array[$key]->start_time = $modified_repeat->update_start_time;
            $repeated_interventions_array[$key]->duration_of_mission = $modified_repeat->update_duration_of_mission;
            $repeated_interventions_array[$key]->modification = $modified_repeat->modification;
            $repeated_interventions_array[$key]->mission_achieved = $modified_repeat->mission_achieved;
        }
    }

问题

在执行此函数时,内存使用量会显著增加,并且日志表明此功能中发生了内存泄漏。该函数处理两个主要的MySQL查询,并涉及多个循环,包括嵌套循环,用于日期计算和数据分配。

具体问题

  • 嵌套循环和日期对象操作可能是内存泄漏的潜在来源。
  • 对获取的MySQL数据进行内存管理,特别是在操作和将其分配给各种对象和数组时。
  • 循环中DateTime和DateInterval操作的优化和内存使用。

尝试的解决方案
为了解决这个问题,我尝试实现一个哈希解决方案,以最小化嵌套循环中数据查找操作的复杂性,希望它可以减轻内存泄漏。
方法
使用哈希表:我引入了哈希表(关联数组),旨在降低嵌套循环中查找操作的时间复杂度。
最小化嵌套循环:我尝试用哈希作为键直接访问元素来代替嵌套循环操作。
内存释放:在使用大型数组和变量后,解释性地取消它们的设置,以确保PHP的垃圾收集器删除它们以释放内存。
下面是一个简单的片段来展示我的方法:

```php
$hashTable = [];
foreach ($repeat_results as $repeat) {
    //... [other operations]
    $key = $repeat->intervention_date . '|' . $repeat->start_time;
    $hashTable[$key] = $repeat;
}

foreach ($modified_repeats as $modified_repeat) {
    $key = $modified_repeat->intervention_date . '|' . $modified_repeat->start_time;
    if (isset($hashTable[$key])) {
        // Perform operation
        $hashTable[$key]->intervention_date = $modified_repeat->update_intervention_date;
    

//... [other update operations]
}
}

结果
尽管有这些变化,内存泄漏问题仍然存在。虽然执行时间略有改善,但在较大的数据操作期间,该函数仍然会耗尽PHP内存。

问题

1.有人能在这段代码中找出任何潜在的内存泄漏源吗?

  1. PHP中是否有内存管理的最佳实践,特别是关于MySQL数据获取和处理,我可能会错过或可以更好地应用?
    1.如何优化嵌套循环和日期计算,使其更高效,占用内存更少?
    感谢您花时间阅读我的问题。我非常感谢任何指导、建议或资源,它们可以为我指明解决此内存泄漏问题的正确方向。
pzfprimi

pzfprimi1#

有两个明显的事情我可以看到。首先

while ($current_date <= new DateTime($end_date)) {

在while循环的每次迭代中创建一个新的DateTime对象(当条件被测试时)。使用类似这样的代码:

$end_datetime = new DateTime($end_date);
while ($current_date <= $end_datetime) {

第二,你有:

$current_date->add(new DateInterval('P1D'));

在你的循环。每一个都导致创建一个新的DateInterval对象。你应该在循环外生成它:

$one_day_interval = new DateInterval('P1D');

以及环路内部用途:

$current_date->add($one_day_interval)

相关问题