PHP Skript Speed Optimieren

O

omaliesschen

Gast
Hi,

ich überarbeite derzeit ein paar Seiten (kleines Messageboard) in der Hoffnung die Performance zu verbessern was bisher rechtanständig funktioniert. Vll. findet ja jemand noch ein paar Optimierungsmöglichkeiten.

Die urls werden evtl. noch verkürzt. index.php?c=id,site; explode($_GET['c']);

Code:
<?php 

try{

    /*          */

     class topic_details{

      public $prc_topic_arr;
      public $prc_post_arr;
      public $prc_topic_reader;
      public $prc_topic_warnings = false;

      function convert_all($in){

        return nl2br(bb_decode(htmlentities(convert($in), ENT_QUOTES, 'UTF-8')));

      }

      function post_array($r,$c,$os){

          $this->prc_post_arr[] = array(
            'user_id'            => $r[1],
            'user_name'          => san($r[4]),
            'user_avatar'        => empty($r[5]) ? '/img/icon_set/default-user.jpg' : san($r[5]),
            'user_num_posts'     => $r[7],
            'user_signature'     => empty($r[6]) ? '' : $this->{'convert_all'}($r[6]),
            'user_reg_date'      => date('m.M.Y',$r[8]),
            'user_online_status' => $os,
            'post_date'          => get_time_ago($r[2]),
            'post_internal_id'   => $r[0],
            'post_external_id'   => $c,
            'post_text'          => $this->{'convert_all'}($r[3]),
            'owned_by_reader'    => $r[1] == $this->prc_topic_reader['id'] ? true : false
          );

      }

    }

    // topic object
    $prc_topic = new topic_details;
    // log object
    $logging   = new log;

    /* Create Sitenavigation */
    $site_array = array(
      '/index.php?se=[...]'     => 'Search', 
      '/index.php?cat=list.all' => 'Categories', 
      '/index.php'.$prc_topic->prc_topic_arr['topic_cat_url'].'' => $prc_topic->prc_topic_arr['topic_cat_name'], 
      '/index.php?c=true&cnum=1&cid='.$prc_topic->prc_topic_arr['topic_id'].'' => $prc_topic->prc_topic_arr['topic_title']
      );

    /* query news data */
    $sth = $dbh->prepare('SELECT t.id, t.rubric, t.title, t.date, t.tags, t.count_comments, t.count_likes, t.count_views, a.id, c.rubrics, a.privatefolder, a.a_name 
                          FROM news t, authors a, rubrics c 
                          WHERE t.id = ? AND t.disabled IS NOT NULL AND a.id = t.author AND c.id = t.rubric');
    $sth->execute(array((int)$_GET['cid']));
    $r = $sth->fetch();
    if( $r === false ){ die( header('Location: /index.php?whoopsie=404' ) ); }

    $prc_topic->prc_topic_reader = array(
      'id'             => isset($_SESSION['UID']) ? $_SESSION['UID'] : 'guest', 
      'topic_operator' => $r[8] == $_SESSION['UID'] || $authtype->authtype == 'Administrator' ? true : false
      );

    $prc_topic->prc_topic_arr = array(
      'topic_id'           => $r[0],
      'topic_cat_id'       => $r[1],
      'topic_cat_name'     => san($r[9]),
      'topic_cat_url'      => '?cnum=1&amp;ql='.$r[1],
      'topic_title'        => san($r[2]),
      'topic_date'         => date('j.m.Y, H:i',$r[3]),
      'topic_tags'         => empty($r[4]) ? false : explode(",", san($r[4])),
      'topic_num_comments' => $r[5],
      'topic_num_likes'    => $r[6],
      'topic_num_views'    => $r[7],
      'topic_creator'      => $r[8],
      'topic_creator_name' => san($r[11]),
      'topic_folder'       => san($r[10]),
      'topic_site'         => isset($_GET['cnum']) ? (int)$_GET['cnum'] : 1,
      'topic_link'         => '?c=true&cnum='.(int)$_GET['cnum'].'&cid='.$r[0]
      );

    $_SESSION['topicid']  = $prc_topic->prc_topic_arr['topic_id'];
    $_SESSION['backlink'] = $prc_topic->prc_topic_arr['topic_link'];

    /* todo */
    $sth = $dbh->prepare('SELECT count(*) FROM control_poll WHERE article_id = ? AND views = \'true\' AND ip = ?');
    $sth->execute(array($prc_topic->prc_topic_arr['topic_id'],$logging->ip));
    $r = $sth->fetch();

    if( $r[0] == 0 ) {
      $sth = $dbh->prepare('UPDATE news SET count_views = count_views + 1 WHERE id = ? ');
      $sth->execute(array($prc_topic->prc_topic_arr['topic_id']));
      $sth = $dbh->prepare('INSERT INTO control_poll VALUES (?,?,?,?,?,?,?,?)');
      $sth->execute(array('auto',$prc_topic->prc_topic_arr['topic_id'],'true','none','none','none',$logging->ip,$prc_topic->prc_topic_reader['id']));
    }

    if( $authtype->authtenticated === true ){
      /* Check if current User liked this article within his session */
      $sth = $dbh->prepare('SELECT COUNT(*) FROM control_poll WHERE article_id = ? AND likes = \'true\' AND session = ?');
      $sth->execute(array($prc_topic->prc_topic_arr['topic_id'], $prc_topic->prc_topic_reader['id']));
      $r = $sth->fetch();

      /* Create a no-func button if liked */
      $likeButton = $r[0] > 0 ? '<button type="button"  class="btr" name="Liked" id="Liked">I Liked</button>' 
      : '<button type="button" class="btr" name="LikeSubmit" id="LikeSubmit" value="'.$prc_topic->prc_topic_arr['topic_id'].'" onclick="like(this.value)">Like</button>';
      $choice     = '<a id="toRoot" class="ply">Reply</a>';
    }

    else{
      $likeButton = '<button type="button" name="Liked" id="Liked" class="btr">Login to like</button>';
      $choice     = '<a id="toRoot" class="ply">Login to submit a comment</a>';
    }

    /* Create Taglist */
    if( $prc_topic->prc_topic_arr['topic_tags'] !== false ){
      $taglist = '';
      foreach($prc_topic->prc_topic_arr['topic_tags'] as $value){ $taglist .= "<a href='/index.php?cnum=1&amp;q=".urlencode(san($value))."'>".san($value)."</a>,&nbsp;"; }
      $taglist = substr($taglist, 0, -7);
    }

    else{ $taglist = '<span style=\'font-size: 0.9em;\'>No tags associated with this topic</span>'; }


  /* 
  $fullpath = "../files/users/".$prc_topic->prc_topic_arr['topic_folder']."/topics/".$prc_topic->prc_topic_arr['topic_id']."/";
  if(!is_dir($fullpath)){ mkdir($fullpath , 0750, true); }
  $directory = dir($fullpath);
  while ( (FALSE !== ($item = $directory->read())) && ( ! isset($directory_not_empty))){
    if ($item != '.' && $item != '..'){ $directory_not_empty = true; }
  }
  $directory->close();
  */

}

catch (PDOException $p) { 

  header( 'Location: /e/handler.php?exception=4' );

}

?>


<!-- Start HTML Output -->
<div class="tableTD">
<div id='fx-1' class='tableTD'>

<!-- comments topic-->
<div id='commentsContainer' >


<?php $current_site->{'generate_nav'}($site_array); ?>

<!-- print tags -->
<div id='generic-tags'><a>Tagged with: </a><?php echo $taglist; ?></div>
<div id='stats_news'>
<a>Discussion started by <?php echo $prc_topic->prc_topic_arr['topic_creator_name']; ?>, <?php echo $prc_topic->prc_topic_arr['topic_date']; ?>. </a><br />
<a class='st-1'><?php echo $prc_topic->prc_topic_arr['topic_num_comments']; ?></a>&nbsp;comments&nbsp;
<a class='st-1'><?php echo $prc_topic->prc_topic_arr['topic_num_views']; ?></a>&nbsp;views&nbsp;
<a id="t-likes" class='st-1'><?php echo $prc_topic->prc_topic_arr['topic_num_likes']; ?></a>&nbsp;likes&nbsp;
</div>


<!-- create Filetree -->
<?php
/*
if ( $directory_not_empty ){         
echo '<div id=\'expandable-file-list\'><div class="g-10">';
require '/var/inc/file_tree_functions.php.inc';
createDir($fullpath, $prc_topic->prc_topic_reader['topic_operator'], $prc_topic->prc_topic_arr['topic_link']);
echo "</div></div>";
}
*/
?>


<?php 

/* delete message */
if( isset($_SESSION['deleted']) ){ $prc_topic->prc_topic_warnings = "<span class='del-1'>Comment successfully deleted</span>"; unset($_SESSION['deleted']); }
/* time limitation */
if( isset($_SESSION['ttw']) ){ $prc_topic->prc_topic_warnings = "<span class='del-1'>Our system requires a 1 second duration between each comment</span>"; unset($_SESSION['ttw']); }

/* number of pages with comments */
$ceil = ceil( $prc_topic->prc_topic_arr['topic_num_comments'] / 20 );
$total_pages = $ceil <= 0 ? 1 : $ceil;

// page navigation
$site = &$prc_topic->prc_topic_arr['topic_site'];

if( $site > $total_pages || $site == 0 ){ $site = 1; }

/* set query limit */
$start_from = ($site-1) * 20;
$string     = "LIMIT ".(int)$start_from.", 20" ;
$msg_count = 0;

/* query posts and check if user is online */
$is_on = $dbh->prepare('SELECT count(*) FROM v_counter WHERE ip = ?');
$sth   = $dbh->prepare('SELECT c.id,c.author, c.date, c.message, a.a_name, a.avatar,a.signature,a.count_pub,a.registeredon
                        FROM comments c, authors a 
                        WHERE c.article_id = ? 
                        AND a.id = c.author 
                        AND c.flag_deleted IS NOT NULL 
                        ORDER BY c.id '.$string);

$sth->execute(array($prc_topic->prc_topic_arr['topic_id']));

foreach($sth as $row){ 

  $is_on->execute(array($row[1]));
  $r = $is_on->fetch();
  $os = $r[0] > 0 ? 'on' : 'off';
  ++$msg_count;
  $cmsg = $msg_count+$start_from;
  $prc_topic->{'post_array'}($row,$cmsg,$os);

}

/* page navigation 1,2,3, [...] */
$newGet = 1;
$pagelist = '';

for($i=1;$i<=$total_pages;++$i){

  $urlB = '?c=true&amp;cnum='.$newGet.'&amp;cid='.$prc_topic->prc_topic_arr['topic_id'];
  /* highlight selected page */
  if( $newGet == $site ){ $pagelist .= "<a class='openComment act'>".$newGet."</a>"; }
  /* else normal font */
  else{ $pagelist .= "<a class='openComment' href='index.php".$urlB."'>".$newGet."</a>"; }
  ++$newGet;

}

/*  Display Navigation Buttons  */
$bp = $site == 1 ? "" : "<a href='index.php?c=true&amp;cnum=".($site - 1)."&amp;cid=".$prc_topic->prc_topic_arr['topic_id']."' class='openComment'>Previous</a>";
$bn = $site == $total_pages ? "" : "<a class='openComment' href='index.php?c=true&amp;cnum=".($site + 1)."&amp;cid=".$prc_topic->prc_topic_arr['topic_id']."'>Next</a>";
if($prc_topic->prc_topic_warnings){echo $prc_topic->prc_topic_warnings;}
?>


<div class='pageswitcher'>
<form action="index.php" method="get" style="display: inline; margin-left: 8px; float: left; position: relative; top: 3px;">
  <label class="page_switch">
Jump to page:
<input type="hidden" name="c" value="true">
<input type="hidden" name="cid" value="<?php echo $prc_topic->prc_topic_arr['topic_id'];?>">
<input type="text" size="4" name="cnum" style="border: 1px solid rgb(204, 204, 204);">
</label>
<input class="openComment sw" type="submit" value="Go" >
</form>
<a class="ps"><?php echo $site."&nbsp;/&nbsp;".$total_pages; ?></a>
<span><?php echo $ifpages.$bp.$pagelist.$bn; ?></span>
</div>


<div id="post_wrap">
<?php foreach ( $prc_topic->prc_post_arr as $key ) : ?>

<div id="post-<?php echo $key['post_internal_id']; ?>" class="c-listings">
<div class="c-20">
<ul class="socket">
<li class="u_avatar"><a class="back-link" href="/index.php?a=<?php echo $key['user_id']; ?>"><img src="<?php echo $key['user_avatar']; ?>"></a></li>
<li>Posts: <?php echo $key['user_num_posts']; ?></li>
<li>Member since:</li>
<li><?php echo $key['user_reg_date']; ?></li>
<li><a href="/index.php?load=msg&amp;call=compose&amp;to=<?php echo urlencode($key['user_name']); ?>" >Send PM</a></li>
</ul>
</div>  
<div class="box-wrap">
<div class="box-top">
<b><a href="#post-<?php echo $key['post_internal_id']; ?>">#<?php echo $key['post_external_id']; ?></a></b>
<span class="box-top-inner">
<a href="/index.php?a=<?php echo $key['user_id']; ?>"><?php echo $key['user_name']; ?></a><img class="socket" src="/img/icon_set/user-<?php echo $key['user_online_status']; ?>line.png" >
<b><?php echo $key['post_date']; ?></b>
</span>
</div>
<div class="box-content">
<div class="box-content-inner">
<div class="box-content-text"><?php echo $key['post_text']; ?><p class="def_sig"><?php echo $key['user_signature']; ?></p></div>
</div>
<div class="c-22">

<?php if($authtype->authtype == 'Administrator') : ?>
<form style="float:right;" method="post" action="/scripts/news/topicoptions/post_delete.php"><button name="del" type="submit" class="openComment" value="<?php echo $key['post_internal_id']; ?>">Delete</button></form>
<?php endif; ?>

<?php if($key['owned_by_reader'] || $authtype->authtype == 'Administrator') : ?>
<a href="/index.php?msgedit=<?php echo $prc_topic->prc_topic_arr['topic_id'].'.'.$key['post_internal_id'].'.'.$prc_topic->prc_topic_arr['topic_cat_id'].'.'.$prc_topic->prc_topic_arr['topic_site']; ?>" id="editmsg" class="openComment edit" >Edit</a>
<?php endif; ?>

<?php if($authtype->authtenticated === true) : ?>
<button type="button" class="openComment ply" >Reply</button><button type="button" class="openComment ply" value="1" >Quote</button>
<?php endif; ?>


</div>
</div>
</div>
<br clear="all" />
</div>

<?php endforeach; ?>
</div>




<div class='pageswitcher'>
<form action="index.php" method="get" style="display: inline; margin-left: 8px; float: left; position: relative; top: 3px;">
<label class="page_switch">
Jump to page:
<input type="hidden" name="c" value="true">
<input type="hidden" name="cid" value="<?php echo $prc_topic->prc_topic_arr['topic_id'];?>">
<input type="text" size="4" name="cnum" style="border: 1px solid rgb(204, 204, 204);">
</label>
<input class="openComment sw" type="submit" value="Go" >
</form>
<a class="ps"><?php echo $site."&nbsp;/&nbsp;".$total_pages; ?></a>
<span><?php echo $ifpages.$bp.$pagelist.$bn; ?></span>
</div>


</div>
</div>
</div>
Ergänzung ()

Kann man das noch irgendwie left joinen bzw. wäre es sinnvoll?

Code:
$user_is_on = $dbh->prepare('SELECT count(*) FROM v_counter WHERE user_id = ?');

$sth   = $dbh->prepare('SELECT c.id,c.author, c.date, c.message, a.a_name, a.avatar,a.signature,a.count_pub,a.registeredon
                        FROM comments c, authors a 
                        WHERE c.article_id = ? 
                        AND a.id = c.author 
                        AND c.flag_deleted IS NOT NULL 
                        ORDER BY c.id '.$string);
 
Am leichtesten wäre es einfach die Datenbanken auf eine SSD zu speichern.
Der Unterschied ist unbeschreiblich. Die Querys (egal wie Komplex) werde alle extrem "geboosted".
 
Ein SSD RAID ist eingeplant.

Funktioniert:
Code:
SELECT c.id, c.author, c.date, c.message, a.id, a.a_name, a.avatar,a.signature,a.count_pub,a.registeredon, v.ip

FROM comments c, authors a 

LEFT JOIN v_counter v

ON v.ip = a.id

WHERE c.article_id = '12557'

AND a.id = c.author 

AND c.flag_deleted IS NOT NULL 

ORDER BY c.id
 
Sollte soweit alles richtig eingestellt sein.

Aktuell versuch ich folgende zwei queries zusammenzufügen ohne mich in bad practice zu verlieren:

Code:
$sth = $dbh->prepare('SELECT count(*) FROM control_poll WHERE article_id = ? AND views = \'true\' AND ip = ?');
$sth = $dbh->prepare('SELECT count(*) FROM control_poll WHERE article_id = ? AND likes = \'true\' AND session = ?');

Es wird pro User/Gast und pro Artikel eine Zeile angelegt. Dort wird dann viewed auf true gesetzt und likes ebenfalls sofern geliked wurde.

Die views laufen pro IP, likes per UserID.

Es müsste etwas sein wie:
Code:
SELECT * FROM xy WHERE article_id = abc AS PFLICHT! (AND ip = x or session = y )

Wie setzt man das um?


PS: Der zuvor gepostete join:

Showing rows 0 - 29 ( 45 total, Query took 0.0016 sec) [id: 1776 - 1833]


Edit:
Ich glaub das zusammenlegen könnte ein logisches Problem geben. Würde dennoch gerne wissen wie man ein Select mit einem Pflichfeld und mehreren Optionalen ORs durchführt. Konnte nichts finden.
 
Zuletzt bearbeitet:
Du könntest innerhalb der Datenbank ein paar Byte sparen und deinem Indexer die Arbeit leichter machen, wenn du Boolean-Werte entweder als TINYINT(1) oder als CHAR(1) speicherst. Wozu "true" und "false" als String schreiben, wenn es ne 1 und ne 0 (oder NULL) auch tun?

ORs sind in der Logik doch immer ziemlich optional. Im Zweifel musst du geschickt klammern. Bei so etwas hilft es, sich eine kleine Logiktabelle zu zeichnen und zu gucken, bei welchen Eingaben deine Ausgabe "wahr" wird. Daraus kannst du dann deine logische Verknüpfung ableiten, z.B. unter Zuhilfenahme einer Karnaugh-Tafel.
 
Wie wärs mit:
Code:
select sum(likes),sum(views) from control_poll where article_id=?
weil m.W. MySQL true und false mit 1 und 0 belegt und dadurch aufsummierbar sein müssten.

Bzgl. Speed:
Was läuft denn langsam?
Solange alles unter 0,01 s liegt, ist das nicht so einfach festzustellen.
Die impliziten Joins (select froma a,b,c where ...) können sehr langsam werden, wenn die Datenbank nicht versteht, was du eigentlich wolltest, da wäre es guter Stil, wenn du da joins verwendest.
 
Laut KCachegrind sind z.b folgende includes sehr langsam:

Code:
class log {
    public $agent;
    public $ip;
    public $time;
    public $referer;
    public $hbyadrr;
    public function __construct() {
        $this->agent   = $_SERVER['HTTP_USER_AGENT'];
        $this->ip      = $_SERVER['REMOTE_ADDR'];
        $this->referer = $_SERVER['HTTP_REFERER'];
        $this->time    = time();
        $this->hbyadrr = gethostbyaddr($_SERVER['REMOTE_ADDR']);
    }
}
gethostbyaddr scheint sehr langsam zu sein.


Code:
<?
try {

    require '/var/inc/dbconnect.php.inc';
    $logging = new log;
    $max = 300; 

    if ( isset($_SESSION['UID']) ) {

        $logging->ip = $_SESSION['UID'];
        $sth = $dbh->prepare('UPDATE authors 
                                            SET last_action = ? 
                                            WHERE id = ?'
        );
        $sth->execute(array($logging->time,$logging->ip));

    }

    $sth = $dbh->prepare('INSERT INTO v_counter 
                                         VALUES(:ip, :time) 
                                         ON DUPLICATE KEY 
                                         UPDATE time = :time; ');
    $sth->bindParam ( ':time', $logging->time );  
    $sth->bindParam ( ':ip', $logging->ip );  
    $sth->execute();

    $tmc = $logging->time-$max;
    $sth = $dbh->prepare('DELETE FROM v_counter WHERE time < ?');
    $sth->execute(array($tmc));
    $g = 0;$m = 0;
    $str = '';

    $sth   = $dbh->prepare('SELECT v.ip, a.a_name 
                                           FROM v_counter v 
                                           LEFT OUTER JOIN authors a 
                                           ON v.ip = a.id');
    $sth->execute();

    foreach ($sth as $value) {

    	if ( $value[1] == NULL ) { ++$g; } 
    	else {

            ++$m;
            $str .= '<a class="back-link" href=\'/index.php?a='.$value[0].'\'>'.san($value[1]).'</a>';

    	}

    }

}

catch (PDOException $p) { 

    header( 'Location: /e/handler.php?exception=4' );


}  
?>
Ergänzung ()

Weitaus schneller ohne Logobject:

Code:
<?
try {

    require '/var/inc/dbconnect.php.inc';
    $max = 300; 
    $time = time();

    if ( isset($_SESSION['UID']) ) {

        $ip = $_SESSION['UID'];
        $sth = $dbh->prepare('UPDATE authors 
                              SET last_action = ? 
                              WHERE id = ?');
        $sth->execute(array($time,$ip));

    }

    else{ $ip = $_SERVER['REMOTE_ADDR']; }

    $sth = $dbh->prepare('INSERT INTO v_counter 
                          VALUES(:ip, :time) 
                          ON DUPLICATE KEY 
                          UPDATE time = :time; ');
    $sth->bindParam ( ':time', $time );  
    $sth->bindParam ( ':ip', $ip );  
    $sth->execute();

    $tmc = $time-$max;
    $sth = $dbh->prepare('DELETE FROM v_counter WHERE time < ?');
    $sth->execute(array($tmc));
    $g = 0;$m = 0;
    $strV = '';

    $sth   = $dbh->prepare('SELECT v.ip, a.a_name 
                            FROM v_counter v 
                            LEFT OUTER JOIN authors a 
                            ON v.ip = a.id');
    $sth->execute();

    foreach ($sth as $value) {

        if ( $value[1] == NULL ) { ++$g; } 

    	else {

            ++$m;
    		$strV .= '<a class="back-link" href=\'/index.php?a='.$value[0].'\'>'.san($value[1]).'</a>';
    	}

    }

}

catch (PDOException $p) { 

    header( 'Location: /e/handler.php?exception=4' );


}  
?>
 
Zuletzt bearbeitet:
Includes kosten doch normalerweise nicht sehr viel Zeit, selbst dann nicht, wenn man die Arbeit dem Autoloader überlässt. Wenn ich überlege, welche Hundertschaften an Dateien z.B. Magento per Autoload an 3 verschiedenen Orten sucht und lädt...
Wenn es da wirklich zu (nennenswerten) Verzögerungen kommt, dann ist eher am Server was mit den IO-Zeiten krumm.

Was für eine Hard- und Softwareumgebung hast du hier?
In welchem Modus läuft PHP? suPHP, mod_php, fcgid, fastcgi...
In welchem Modus läuft der Apache? mpm_prefork, mpm_itk, mpm_worker,...
Nutzt du einen OpCode-Cache wie APC? Wenn nicht (z.B. weil es bei suPHP unmöglich ist), dann wundert michs gar nicht, dass dein Code bei Inlcudes lahmt.
 
ich denke mal eher er hat die Ausgabe fehlinterpretiert: Das ein Großteil der Zeit in einer Datei verbraten wird (!= include) und dann eben spezieller der gethostbyaddr-Aufruf, der eben erst einen Lookup machen muss.
 
Richtig,
der Aufruf von
Code:
gethostbyaddr
scheint ggf. eine gewissen Zeit zu benötigen.

Es werden dazu wohl ggf. mehrere DNS-Abfragen durchgeführt.

Schau dir doch mal diese gepostete Lösung an.
Vielleicht könnte es das Problem schon entschärfen.

Ein anderer Lösungansatz wäre, das Ergebnis der Funktion eine gewisse Zeit lang zu cachen.
z.B. sollte sich der Hostnamen zu einer (ggf. dynamisch zugewiesenen) IP innerhalb einer Session nicht ändern.

Wenn auch das nicht hilft, kannst du den Aufruf für den Seiten-Aufbau erstmal ausklammern
und dann im Nachhinein z.B. per AJAX durchführen, ohne die Seite zu blockieren.
 
Das die Ausführungszeit des Skripts und nicht das include gemeint ist sollte klar sein.

Ich nutz überhaupt keinen Apache. Lighttpd mit fastcgi.


Hatte den Zend Opcache gerade getestet und es endet mit einem Internal Server error. Genaue Ursache noch unbekannt.

(mod_fastcgi.c.2568) unexpected end-of-file (perhaps the fastcgi process died): pid: 20258 socket: unix:/tmp/php-fastcgi.socket-3
(mod_fastcgi.c.3356) response not received, request sent: 799 on socket: unix:/tmp/php-fastcgi.socket-3 for /index.php?, closing connection


Hardware ist etwas eingestaubt. P4 Dual core, 2gb Ram, alte HDD.


Edit: Querycache und vergleichbares ist eingerichtet.

GetHostbyAdress wurde entfernt und kommt nur noch beim Login/Anmeldung zum Einsatz. Wird auf der Seite sowieso nicht genutzt, außer eben bei Logins etc.
Ergänzung ()

Hancock schrieb:
Wie wärs mit:
Code:
select sum(likes),sum(views) from control_poll where article_id=?
weil m.W. MySQL true und false mit 1 und 0 belegt und dadurch aufsummierbar sein müssten.

Bzgl. Speed:
Was läuft denn langsam?
Solange alles unter 0,01 s liegt, ist das nicht so einfach festzustellen.
Die impliziten Joins (select froma a,b,c where ...) können sehr langsam werden, wenn die Datenbank nicht versteht, was du eigentlich wolltest, da wäre es guter Stil, wenn du da joins verwendest.


Die Tabelle wurde auf int umgestellt. Die impliziten Joins sind bisschen nervig, speziell wenn sie komplexer werden.
Ergänzung ()

Durch umstellen der Tabelle ist zumindest etwas Ordnung reingekommen und ein primary key:


Neuer Code:
Code:
    $action_key = isset($_SESSION['UID']) ? $_SESSION['UID'].':'.$prc_topic->prc_topic_arr['topic_id'] : $logging->ip.':'.$prc_topic->prc_topic_arr['topic_id'];
    $sth = $dbh->prepare('SELECT views,likes FROM topic_user_actions WHERE id = ?');
    $sth->execute(array($action_key));
    $r = $sth->fetch();

    if( $r === false) {
      $sth = $dbh->prepare('UPDATE news SET count_views = count_views + 1 WHERE id = ? ');
      $sth->execute(array($prc_topic->prc_topic_arr['topic_id']));
      $sth = $dbh->prepare('INSERT INTO topic_user_actions VALUES ( ?, 1, 0, 0, 0 )');
      $sth->execute(array($action_key));
    }

    if( $authtype->authtenticated == true ){
      $likeButton = $r[1] > 0 ? '<button type="button" class="btr" id="Liked">I Liked</button>' 
      : '<button type="button" class="btr" name="LikeSubmit" id="LikeSubmit" value="'.$prc_topic->prc_topic_arr['topic_id'].'" onclick="like(this.value)">Like</button>';
      $choice     = '<a id="toRoot" class="ply">Reply</a>';
    }
    else{
      $likeButton = '';
      $choice     = '';
    }

Alt:
Code:
 /* todo */
$sth = $dbh->prepare('SELECT count(*) FROM control_poll WHERE article_id = ? AND views = \'true\' AND ip = ?');
$sth->execute(array($prc_topic->prc_topic_arr['topic_id'],$logging->ip));
$r = $sth->fetch();
 
if( $r[0] == 0 ) {
$sth = $dbh->prepare('UPDATE news SET count_views = count_views + 1 WHERE id = ? ');
$sth->execute(array($prc_topic->prc_topic_arr['topic_id']));
$sth = $dbh->prepare('INSERT INTO control_poll VALUES (?,?,?,?,?,?,?,?)');
$sth->execute(array('auto',$prc_topic->prc_topic_arr['topic_id'],'true','none','none','none',$logging->ip,$prc_topic->prc_topic_reader['id']));
}
 
if( $authtype->authtenticated === true ){
/* Check if current User liked this article within his session */
$sth = $dbh->prepare('SELECT COUNT(*) FROM control_poll WHERE article_id = ? AND likes = \'true\' AND session = ?');
$sth->execute(array($prc_topic->prc_topic_arr['topic_id'], $prc_topic->prc_topic_reader['id']));
$r = $sth->fetch();
 
/* Create a no-func button if liked */
$likeButton = $r[0] > 0 ? '<button type="button" class="btr" name="Liked" id="Liked">I Liked</button>'
: '<button type="button" class="btr" name="LikeSubmit" id="LikeSubmit" value="'.$prc_topic->prc_topic_arr['topic_id'].'" onclick="like(this.value)">Like</button>';
$choice = '<a id="toRoot" class="ply">Reply</a>';
}
 
else{
$likeButton = '<button type="button" name="Liked" id="Liked" class="btr">Login to like</button>';
$choice = '<a id="toRoot" class="ply">Login to submit a comment</a>';
}



Gibt es einen Weg über INSERT IGNORE einen return Wert zu erhalten? Success, failed? Das wäre in dem Fall vll. eine gute Lösung.
 
Zuletzt bearbeitet:
Hi,

insert ignore produziert keinen Fehler.

Mittlerweile teste ich php 5.5 mit Zend Opcache. Kanns sein dass sich da was verändert hat? Die php5-cgi binary liegt jetzt irgendwo in /usr/local/bin/php-cgi und nicht mehr in usr/bin.

Zusätzliche Module liegen usr/local/lib/php/extensions/no-debug-non-zts-20121212

Wirkliche Unterschiede in der Performance seh ich derzeit noch nicht.
 
Vielleicht aber insert ohne ignore?
Laut http://stackoverflow.com/questions/1661863/pdo-mysql-how-to-know-if-insert-was-successful sollte das gehen.

Aber:
Bisher hast du uns immer noch nicht gesagt, was denn jetzt wirklich langsam ist.

Grobe Richtlinie:
Benchen: solange du nicht weißt, was mindestens die Hälfte der Performance frisst, lohnt es sich gar nicht erst, wirklich anzufangen.
Ne Möglichkeit um rasuzufinden, obs PHP oder MySQL ist, was so langsam ist:
getrusage in Verbindung mit microtime (setzt Linux voraus).
 
So langsam ist es nicht. Es könnte nur etwas schneller sein.

Das Skript macht mehr als die Hälfte der Zeit aus:


Lässt sich vermuten dass es am vielen Schreiben liegt und in dem Fall die Hardware einfach zu alt ist.

Die langsamste Seite braucht ohne den Nutzercounter ~0.005s.
Mit Nutzercounter um die 0.07s - 0.09s

( bei einem Nutzer )


Code:
<?
try {

    require '/var/inc/dbconnect.php.inc';
    $max = 300; 
    $time = time();

    if ( isset($_SESSION['UID']) ) {

        $ip = $_SESSION['UID'];
        $sth = $dbh->prepare('UPDATE authors 
                              SET last_action = ? 
                              WHERE id = ?');
        $sth->execute(array($time,$ip));

    }

    else{ $ip = $_SERVER['REMOTE_ADDR']; }

    $sth = $dbh->prepare('INSERT INTO v_counter 
                          VALUES(:ip, :time) 
                          ON DUPLICATE KEY 
                          UPDATE time = :time ');
    $sth->bindParam ( ':time', $time );  
    $sth->bindParam ( ':ip', $ip );  
    $sth->execute();

    $tmc = $time-$max;
    $sth = $dbh->prepare('DELETE FROM v_counter WHERE time < ?');
    $sth->execute(array($tmc));
    $g = 0;$m = 0;
    $str = '';

    $sth   = $dbh->prepare('SELECT v.ip, a.a_name 
                            FROM v_counter v 
                            LEFT OUTER JOIN authors a 
                            ON v.ip = a.id');
    $sth->execute();

    foreach ($sth as $value) {

        if ( $value[1] == NULL ) { ++$g; } 

    	else {

            ++$m;
    		$str .= '<a class="back-link" href=\'/index.php?a='.$value[0].'\'>'.san($value[1]).'</a>';
    	}

    }

}

catch (PDOException $p) { 

    header( 'Location: /e/handler.php?exception=4' );


}  
?>
 
Zuletzt bearbeitet:
Z. 29: Das wird langsam sein, sobald etwas mehr los ist (denk ich).

Klatsch mal im phpMyAdmin o.Ä. jeweils
Code:
explain select * FROM v_counter WHERE time < now()
Code:
explain SELECT v.ip, a.a_name 
FROM v_counter v 
LEFT OUTER JOIN authors a 
ON v.ip = a.id
rein und guck, ob ein Index möglich ist ("Possible index") und vielleicht auch verwendet wird.

Was machst du eigentlich in Z. 40 ff?
 
Explain hilft mir schon weiter. Danke.

Werde die Tabelle ändern.

Zeile 40: Sobald ein Name zum Eintrag IP (bei registrierten Nutzern wird anstelle der IP die NutzerID gespeichert.) gefunden wird wird ein Link zum Profil des Nutzers erstellt. Am Ende findet sich auf der Startseite eine Linkliste der aktiven Nutzer.

Dazu wird gezählt. Member++, Guest++,
 
Zuletzt bearbeitet:
Na ja, vor allem bin ich skeptisch, ob das foreach so funktioniert, wie du das willst.
Bei dem Gästezähler wäre eine Idee, diesen outer join in ein inner join umzuwandeln und die Gäste extra abzufragen.
Code:
select Count(*) as guests from v_counter where ip not in(select ip from authors)
Das dürfte dir etwas Bandbreite sparen (PHP<->MySQL), grad wenn viele Besucher unterwegs sind.
 
Zurück
Oben