diff -urp modules.orig/comment/comment.module modules/comment/comment.module
--- modules.orig/comment/comment.module	2007-10-18 00:29:00.000000000 +0300
+++ modules/comment/comment.module	2007-10-18 22:26:09.000000000 +0300
@@ -931,6 +931,16 @@ function comment_links($comment, $return
 function comment_render($node, $cid = 0) {
   global $user;
 
+  // If this is an authenticated user who only has one role and cannot admin-
+  // ister comments, look for a cached copy of the comment, or in the case
+  // of $cid = 0, the whole tree of comments.
+  $cache_key = 0;
+  if (!user_access('administer comments') && count($user->roles) === 1 && in_array('authenticated user', $user->roles)) {
+    // Must accommodate pagination
+    $page = isset($_GET['page']) ? $_GET['page'] : '';
+    $cache_key = 'nid-'. $node->nid. '::cid-'. $cid. '::'. $page;
+  }
+
   $output = '';
 
   if (user_access('access comments')) {
@@ -945,77 +955,109 @@ function comment_render($node, $cid = 0)
     $comments_per_page = _comment_get_display_setting('comments_per_page');
 
     if ($cid) {
-      // Single comment view.
-      $query = 'SELECT c.cid, c.pid, c.nid, c.subject, c.comment, c.format, c.timestamp, c.name, c.mail, c.homepage, u.uid, u.name AS registered_name, u.picture, u.data, c.score, c.users, c.status FROM {comments} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.cid = %d';
-      $query_args = array($cid);
-      if (!user_access('administer comments')) {
-        $query .= ' AND c.status = %d';
-        $query_args[] = COMMENT_PUBLISHED;
-      }
-
-      $result = db_query($query, $query_args);
-
-      if ($comment = db_fetch_object($result)) {
-        $comment->name = $comment->uid ? $comment->registered_name : $comment->name;
-        $links = module_invoke_all('link', 'comment', $comment, 1);
-
-        foreach (module_implements('link_alter') as $module) {
-          $function = $module .'_link_alter';
-          $function($node, $links);
+      if ($cache_key) {
+        $cache = cache_get($cache_key, 'cache_comment');
+        $comment = unserialize($cache->data);
+      }
+
+      if (!$comment) {
+        // Single comment view.
+        $query = 'SELECT c.cid, c.pid, c.nid, c.subject, c.comment, c.format, c.timestamp, c.name, c.mail, c.homepage, u.uid, u.name AS registered_name, u.picture, u.data, c.score, c.users, c.status FROM {comments} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.cid = %d';
+        $query_args = array($cid);
+        if (!user_access('administer comments')) {
+          $query .= ' AND c.status = %d';
+          $query_args[] = COMMENT_PUBLISHED;
         }
 
+        $result = db_query($query, $query_args);
+
+        if ($comment = db_fetch_object($result)) {
+          $comment->name = $comment->uid ? $comment->registered_name : $comment->name;
+          $links = module_invoke_all('link', 'comment', $comment, 1);
+
+          foreach (module_implements('link_alter') as $module) {
+            $function = $module .'_link_alter';
+            $function($node, $links);
+          }
+        }
+      }
+
+      if ($comment) {
         $output .= theme('comment_view', $comment, $links);
       }
     }
     else {
-      // Multiple comment view
-      $query_count = 'SELECT COUNT(*) FROM {comments} WHERE nid = %d';
-      $query = 'SELECT c.cid as cid, c.pid, c.nid, c.subject, c.comment, c.format, c.timestamp, c.name, c.mail, c.homepage, u.uid, u.name AS registered_name, u.picture, u.data, c.score, c.users, c.thread, c.status FROM {comments} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.nid = %d';
-
-      $query_args = array($nid);
-      if (!user_access('administer comments')) {
-        $query .= ' AND c.status = %d';
-        $query_count .= ' AND status = %d';
-        $query_args[] = COMMENT_PUBLISHED;
-      }
-
-      if ($order == COMMENT_ORDER_NEWEST_FIRST) {
-        if ($mode == COMMENT_MODE_FLAT_COLLAPSED || $mode == COMMENT_MODE_FLAT_EXPANDED) {
-          $query .= ' ORDER BY c.timestamp DESC';
-        }
-        else {
-          $query .= ' ORDER BY c.thread DESC';
+      if ($cache_key) {
+        if ($cache = cache_get($cache_key, 'cache_comment')) {
+          $comments = unserialize($cache->data);
+          $comment_count = count($comments);
+
+          // Get the pager
+          $cache = cache_get($cache_key. '::pager', 'cache_comment');
+          $pager = $cache->data;
         }
       }
-      else if ($order == COMMENT_ORDER_OLDEST_FIRST) {
-        if ($mode == COMMENT_MODE_FLAT_COLLAPSED || $mode == COMMENT_MODE_FLAT_EXPANDED) {
-          $query .= ' ORDER BY c.timestamp';
+
+      if (empty($comments)) {
+        // Multiple comment view
+        $query_count = 'SELECT COUNT(*) FROM {comments} WHERE nid = %d';
+        $query = 'SELECT c.cid as cid, c.pid, c.nid, c.subject, c.comment, c.format, c.timestamp, c.name, c.mail, c.homepage, u.uid, u.name AS registered_name, u.picture, u.data, c.score, c.users, c.thread, c.status FROM {comments} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.nid = %d';
+
+        $query_args = array($nid);
+        if (!user_access('administer comments')) {
+          $query .= ' AND c.status = %d';
+          $query_count .= ' AND status = %d';
+          $query_args[] = COMMENT_PUBLISHED;
         }
-        else {
 
-          /*
-          ** See comment above. Analysis learns that this doesn't cost
-          ** too much. It scales much much better than having the whole
-          ** comment structure.
-          */
+        if ($order == COMMENT_ORDER_NEWEST_FIRST) {
+          if ($mode == COMMENT_MODE_FLAT_COLLAPSED || $mode == COMMENT_MODE_FLAT_EXPANDED) {
+            $query .= ' ORDER BY c.timestamp DESC';
+          }
+          else {
+            $query .= ' ORDER BY c.thread DESC';
+          }
+        }
+        else if ($order == COMMENT_ORDER_OLDEST_FIRST) {
+          if ($mode == COMMENT_MODE_FLAT_COLLAPSED || $mode == COMMENT_MODE_FLAT_EXPANDED) {
+            $query .= ' ORDER BY c.timestamp';
+          }
+          else {
+  
+            /*
+            ** See comment above. Analysis learns that this doesn't cost
+            ** too much. It scales much much better than having the whole
+            ** comment structure.
+            */
 
-          $query .= ' ORDER BY SUBSTRING(c.thread, 1, (LENGTH(c.thread) - 1))';
+            $query .= ' ORDER BY SUBSTRING(c.thread, 1, (LENGTH(c.thread) - 1))';
+          }
         }
+
+        // Start a form, for use with comment control.
+        $result = pager_query($query, $comments_per_page, 0, $query_count, $query_args);
+          $comment_count = db_num_rows($result);
       }
 
-      // Start a form, for use with comment control.
-      $result = pager_query($query, $comments_per_page, 0, $query_count, $query_args);
-      if (db_num_rows($result) && (variable_get('comment_controls', COMMENT_CONTROLS_HIDDEN) == COMMENT_CONTROLS_ABOVE || variable_get('comment_controls', COMMENT_CONTROLS_HIDDEN) == COMMENT_CONTROLS_ABOVE_BELOW)) {
+      if ($comment_count && (variable_get('comment_controls', COMMENT_CONTROLS_HIDDEN) == COMMENT_CONTROLS_ABOVE || variable_get('comment_controls', COMMENT_CONTROLS_HIDDEN) == COMMENT_CONTROLS_ABOVE_BELOW)) {
         $output .= drupal_get_form('comment_controls', $mode, $order, $comments_per_page);
       }
 
       $divs = 0;
       $last_depth = 0;
       drupal_add_css(drupal_get_path('module', 'comment') .'/comment.css');
-      while ($comment = db_fetch_object($result)) {
-        $comment = drupal_unpack($comment);
-        $comment->name = $comment->uid ? $comment->registered_name : $comment->name;
-        $comment->depth = count(explode('.', $comment->thread)) - 1;
+      if (empty($comments)) {
+        $comments = array();
+        while ($comment = db_fetch_object($result)) {
+          $comment = drupal_unpack($comment);
+          $comment->name = $comment->uid ? $comment->registered_name : $comment->name;
+          $comment->depth = count(explode('.', $comment->thread)) - 1;
+            $comments[] = $comment;
+          }
+        cache_set($cache_key, 'cache_comment', serialize($comments));
+      }
+
+      foreach ($comments as $comment) {
 
         if ($mode == COMMENT_MODE_THREADED_COLLAPSED || $mode == COMMENT_MODE_THREADED_EXPANDED) {
           if ($comment->depth > $last_depth) {
@@ -1048,9 +1090,14 @@ function comment_render($node, $cid = 0)
       for ($i = 0; $i < $divs; $i++) {
         $output .= '</div>';
       }
-      $output .= theme('pager', NULL, $comments_per_page, 0);
+      if (empty($pager)) {
+        $pager = theme('pager', NULL, $comments_per_page, 0);
+        cache_set($cache_key. '::pager', 'cache_comment', $pager);
+      }
+
+      $output .= $pager;
 
-      if (db_num_rows($result) && (variable_get('comment_controls', COMMENT_CONTROLS_HIDDEN) == COMMENT_CONTROLS_BELOW || variable_get('comment_controls', COMMENT_CONTROLS_HIDDEN) == COMMENT_CONTROLS_ABOVE_BELOW)) {
+      if ($comment_count && (variable_get('comment_controls', COMMENT_CONTROLS_HIDDEN) == COMMENT_CONTROLS_BELOW || variable_get('comment_controls', COMMENT_CONTROLS_HIDDEN) == COMMENT_CONTROLS_ABOVE_BELOW)) {
         $output .= drupal_get_form('comment_controls', $mode, $order, $comments_per_page);
       }
     }
diff -urp modules.orig/node/node.module modules/node/node.module
--- modules.orig/node/node.module	2007-09-30 02:41:28.000000000 +0300
+++ modules/node/node.module	2007-10-18 22:37:16.000000000 +0300
@@ -2463,7 +2463,7 @@ function node_page_default($arg = NULL) 
 /**
  * Menu callback; view a single node.
  */
-function node_page_view($node, $cid = NULL) {
+function node_page_view($node, $cid = 0) {
   drupal_set_title(check_plain($node->title));
   return node_show($node, $cid);
 }
