Tell me more ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

Hello friends. I am using the following code to run an operation on a .dat file, which is working fine. The .dat file can be treated as a text file. My main concern is how to improve execution time when you have to run a for loop on 25 Mb of data.

$file_name='grid_10min_sunp.dat';

$handle = fopen($file_name, "r");

$lat1=13.86082;
$lan1=100.50509;

 $lat_lon_sunshines = make_sunshine_dict($file_name);


// echo '<pre>';
 //print_r($lat_lon_sunshines);
  //echo count($lat_lon_sunshines);

$closest = 500;
for($c=0;$c<count($lat_lon_sunshines);$c++)
{

//echo $c;  //echo $c;
$lat2=$lat_lon_sunshines[$c]['lat'];
 $lan2=$lat_lon_sunshines[$c]['lan'];
$sunshines=$lat_lon_sunshines[$c]['sunshine'];
//print_r($sunshines);die;
//die;
 $lat_diff = abs(round((float)($lat1), 4)-$lat2);

if ($lat_diff < $closest)
{
    $diff = $lat_diff +  abs(round((float)($lan1), 4)-$lan2); 

     if($diff < $closest)
     {
              $closest = $diff;
            $sunshinesfinal=$sunshines;
     }      
}
$sunshines='';

}
//echo 'sumit';
 print_r($sunshinesfinal);die;

function make_sunshine_dict($file_name)
{

 $sunshines_dict = array();     

  $f = file_get_contents($file_name);

  $handle = fopen($file_name, "r");




  /* for($kkk=0;$kkk<100;$kkk++)
   {    

   $buffer = fgets($handle);*/

  while($buffer = fgets($handle))
  {


 // print_r($buffer);die;
  $tok = strtok($buffer, " \n\t");

   $lat=$tok;

   $latArray[]=$tok;

  //$lat=round(float(values[0]), 4)

 //print_r($buffer);



 // print_r($tok);

   $tok = strtok(" \n\t");

   $months = '';

   $months = array();

    //print_r($tok);die;
   for ($k = 0; $tok !== false; $k+=1) 
   {

   if($k==0)
   {
   $lan=$tok;
   $lanArray[]=$tok;
   }

   if($k!=0)
   {
  /// echo $tok;
        $months[] = $tok ;
         "month $k : ".$months[$k]."<br>";

   }

    $tok = strtok(" \n\t");
    }


    /*echo $lat;
    echo '<br>';
    echo $lang;
    echo '<br>';
    print_r($months);*/


    //$data=new stdClass();
    /*$data->sunshine[]->lat=$lat;
    $data->sunshine[]->lan=$lang;*/

    $data[$kkk]['lat']=$lat;
    $data[$kkk]['lan']=$lan;
    //$sunshines=array();

    foreach($months as $m=>$sunshine)
    {


         $sunshines=array();
          $sumD = 0;

        // $iteration= ($m+1)*30+1;

          $iteration= 31;

          for($n=1;$n<=$iteration;$n++)
          {
              $J = ($m+1)*$n; 



             $P = asin(.39795*cos(.2163108 + 2*atan(.9671396*tan(.00860*($J-186)))));



          $value=(sin(0.8333*pi/180) + sin($lat*pi/180)*sin($P))/(cos($lat*pi/180)*cos($P));

            /* $value ? ($value > 1 and 1) : $value;

             $value ? ($value < -1 and -1): $value;*/


          $D = 24 - ((24/pi) * acos($value));



           $sumD = $sumD + $D;

             }

                $sunshinesdata=(($sumD/30)*(float)($sunshine)*.01);




          //echo '<pre>';

          //print_r($sunshines);die;


           $data[$kkk]['sunshine'][$m]=$sunshinesdata; 

          $sunshines='';
    }
    //echo '<pre>';
    //print_r($data);

    }
 //die;
return $data;

}

There is no problem in the above code, except that the .dat file I am using is 25 Mb so you can understand it will take a long, long time to run the above script. How can I decrease the execution time? Can I use indexing or what? Please help

    // echo '<pre>';
     //print_r($lat_lon_sunshines);
      //echo count($lat_lon_sunshines);

    $closest = 500;
    for($c=0;$c<count($lat_lon_sunshines);$c++)
    {

    //echo $c;  //echo $c;
    $lat2=$lat_lon_sunshines[$c]['lat'];
     $lan2=$lat_lon_sunshines[$c]['lan'];
    $sunshines=$lat_lon_sunshines[$c]['sunshine'];
    //print_r($sunshines);die;
    //die;
     $lat_diff = abs(round((float)($lat1), 4)-$lat2);

    if ($lat_diff < $closest)
    {
        $diff = $lat_diff +  abs(round((float)($lan1), 4)-$lan2); 

         if($diff < $closest)
         {
                  $closest = $diff;
                $sunshinesfinal=$sunshines;
         }      
    }
    $sunshines='';

    }
    //echo 'sumit';
     print_r($sunshinesfinal);die;

    function make_sunshine_dict($file_name)
    {

     $sunshines_dict = array();     

      $f = file_get_contents($file_name);

      $handle = fopen($file_name, "r");




      /* for($kkk=0;$kkk<100;$kkk++)
       {    

       $buffer = fgets($handle);*/

      while($buffer = fgets($handle))
      {


     // print_r($buffer);die;
      $tok = strtok($buffer, " \n\t");

       $lat=$tok;

       $latArray[]=$tok;

      //$lat=round(float(values[0]), 4)

     //print_r($buffer);



     // print_r($tok);

       $tok = strtok(" \n\t");

       $months = '';

       $months = array();

        //print_r($tok);die;
       for ($k = 0; $tok !== false; $k+=1) 
       {

       if($k==0)
       {
       $lan=$tok;
       $lanArray[]=$tok;
       }

       if($k!=0)
       {
      /// echo $tok;
            $months[] = $tok ;
             "month $k : ".$months[$k]."<br>";

       }

        $tok = strtok(" \n\t");
        }


        /*echo $lat;
        echo '<br>';
        echo $lang;
        echo '<br>';
        print_r($months);*/


        //$data=new stdClass();
        /*$data->sunshine[]->lat=$lat;
        $data->sunshine[]->lan=$lang;*/

        $data[$kkk]['lat']=$lat;
        $data[$kkk]['lan']=$lan;
        //$sunshines=array();

        foreach($months as $m=>$sunshine)
        {


             $sunshines=array();
              $sumD = 0;

            // $iteration= ($m+1)*30+1;

              $iteration= 31;

              for($n=1;$n<=$iteration;$n++)
              {
                  $J = ($m+1)*$n; 



                 $P = asin(.39795*cos(.2163108 + 2*atan(.9671396*tan(.00860*($J-186)))));



              $value=(sin(0.8333*pi/180) + sin($lat*pi/180)*sin($P))/(cos($lat*pi/180)*cos($P));

                /* $value ? ($value > 1 and 1) : $value;

                 $value ? ($value < -1 and -1): $value;*/


              $D = 24 - ((24/pi) * acos($value));



               $sumD = $sumD + $D;

                 }

                    $sunshinesdata=(($sumD/30)*(float)($sunshine)*.01);




              //echo '<pre>';

              //print_r($sunshines);die;


               $data[$kkk]['sunshine'][$m]=$sunshinesdata; 

              $sunshines='';
        }
        //echo '<pre>';
        //print_r($data);

        }
     //die;
    return $data;

    }
share|improve this question

1 Answer

The first thing that comes to mind is that if you expect a lot of duplicate values you can cache. So, for example, in this loop:

for($n=1;$n<=$iteration;$n++) {
  $J = ($m+1)*$n; 
  $P = asin(.39795*cos(.2163108 + 2*atan(.9671396*tan(.00860*($J-186)))));
  $value=(sin(0.8333*pi/180) + sin($lat*pi/180)*sin($P))/(cos($lat*pi/180)*cos($P));
  $D = 24 - ((24/pi) * acos($value));
  $sumD = $sumD + $D;
}

You could do:

$P_cache = array();
for ($n=1; $n <= $iteration; $n++) {
  $J = ($m + 1) * $n;
  if (array_key_exists($J, $P_cache)) {
    $P = $P_cache[$J];
  } else {
    $P = asin(...);
    ...
  }
}

Doing this in a few places would trade-off memory for some performance gains. Also, since this is a site for code review, I'd also list a few points that could do with some improvement:

  • Variable names need to be more descriptive $J could be $location_index or anything more descriptive.
  • Use functions more take all those complex trigonometric computations and put them in a function. It will make your code cleaner and easier to review, and help us give you performance tips better.
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.