        }
 Index: examples/introduction/introduction_ex2/run.sh
 ===================================================================
---- examples/introduction/introduction_ex2/run.sh	(revision 6270)
+--- examples/introduction/introduction_ex2/run.sh	(revision 6279)
 +++ examples/introduction/introduction_ex2/run.sh	(working copy)
 @@ -6,9 +6,9 @@
  

 options="eqn_sys.dat"
 run_example "$example_name" "$options"
 message_done_running "$example_name"
Index: include/systems/system.h
===================================================================
--- include/systems/system.h	(revision 6270)
+++ include/systems/system.h	(working copy)
@@ -1510,8 +1510,8 @@
    * Reads a vector for this System.
    * This method may safely be called on a distributed-memory mesh.
    */
-  void read_serialized_vector (Xdr& io,
-			       NumericVector<Number> &vec);
+  unsigned int read_serialized_vector (Xdr& io,
+				       NumericVector<Number> &vec);
 
   /**
    * Writes an output vector to the stream \p io for a set of \p DofObjects.
@@ -1536,8 +1536,8 @@
    * Writes a vector for this System.
    * This method may safely be called on a distributed-memory mesh.
    */
-  void write_serialized_vector (Xdr& io,
-				const NumericVector<Number> &vec) const;
+  unsigned int write_serialized_vector (Xdr& io,
+					const NumericVector<Number> &vec) const;
 
   /**
    * Function that initializes the system.
Index: src/systems/system_io.C
===================================================================
--- src/systems/system_io.C	(revision 6270)
+++ src/systems/system_io.C	(working copy)
@@ -475,6 +475,10 @@
    * ASCII output.  Thus this one section of code will read XDR or ASCII
    * files with no changes.
    */
+  PerfLog pl("IO Performance",false);
+  pl.push("read_parallel_data");
+  unsigned int total_read_size = 0;
+  
   libmesh_assert (io.reading());
   libmesh_assert (io.is_open());
 
@@ -514,6 +518,8 @@
   // for the ith system to disk
   io.data(io_buffer);
 
+  total_read_size += io_buffer.size();
+
   const unsigned int sys_num = this->number();
   const unsigned int n_vars  = this->_written_var_indices.size();
   libmesh_assert_less_equal (n_vars, this->n_vars());
@@ -590,6 +596,8 @@
 	  // for the ith system to disk
 	  io.data(io_buffer);
 
+	  total_read_size += io_buffer.size();
+
 	  // Loop over each non-SCALAR variable and each node, and read out the value.
           for (unsigned int data_var=0; data_var<n_vars; data_var++)
             {
@@ -644,6 +652,16 @@
           pos->second->close();
 	}
     }
+
+  const Real 
+    dt   = pl.get_elapsed_time(),
+    rate = total_read_size*sizeof(Number)/dt; 
+
+  std::cerr << "Read " << total_read_size << " \"Number\" values\n"
+	    << " Elapsed time = " << dt << '\n'
+	    << " Rate = " << rate/1.e6 << "(MB/sec)\n\n";
+
+  pl.pop("read_parallel_data");
 }
 
 
@@ -665,10 +683,15 @@
   parallel_only();
   std::string comment;
 
+  PerfLog pl("IO Performance",false);
+  pl.push("read_serialized_data");
+  unsigned int total_read_size = 0;
+
   // 10.)
   // Read the global solution vector
   {
-    this->read_serialized_vector(io, *this->solution);
+    total_read_size +=
+      this->read_serialized_vector(io, *this->solution);
 
     // get the comment
     if (libMesh::processor_id() == 0)
@@ -684,7 +707,8 @@
 
       for(; pos != this->_vectors.end(); ++pos)
         {
-	  this->read_serialized_vector(io, *pos->second);
+	  total_read_size +=
+	    this->read_serialized_vector(io, *pos->second);
 
 	  // get the comment
 	  if (libMesh::processor_id() == 0)
@@ -692,6 +716,16 @@
 
 	}
     }
+
+  const Real 
+    dt   = pl.get_elapsed_time(),
+    rate = total_read_size*sizeof(Number)/dt; 
+
+  std::cout << "Read " << total_read_size << " \"Number\" values\n"
+	    << " Elapsed time = " << dt << '\n'
+	    << " Rate = " << rate/1.e6 << "(MB/sec)\n\n";
+
+  pl.pop("read_serialized_data");
 }
 
 
@@ -894,7 +928,7 @@
 
 
 
-void System::read_serialized_vector (Xdr& io, NumericVector<Number>& vec)
+unsigned int System::read_serialized_vector (Xdr& io, NumericVector<Number>& vec)
 {
   parallel_only();
 
@@ -966,6 +1000,8 @@
   Parallel::sum (n_assigned_vals);
   libmesh_assert_equal_to (n_assigned_vals, vector_length);
 #endif
+
+  return vector_length;
 }
 
 
@@ -1408,6 +1444,10 @@
    * ASCII output.  Thus this one section of code will read XDR or ASCII
    * files with no changes.
    */
+  PerfLog pl("IO Performance",false);
+  pl.push("write_parallel_data");
+  unsigned int total_written_size = 0;
+  
   std::string comment;
 
   libmesh_assert (io.writing());
@@ -1504,6 +1544,8 @@
 
   io.data (io_buffer, comment.c_str());
 
+  total_written_size += io_buffer.size();
+
   // Only write additional vectors if wanted
   if (write_additional_data)
     {
@@ -1573,8 +1615,20 @@
 	  }
 
 	  io.data (io_buffer, comment.c_str());
+
+	  total_written_size += io_buffer.size();
 	}
     }
+
+  const Real 
+    dt   = pl.get_elapsed_time(),
+    rate = total_written_size*sizeof(Number)/dt; 
+
+  std::cerr << "Write " << total_written_size << " \"Number\" values\n"
+	    << " Elapsed time = " << dt << '\n'
+	    << " Rate = " << rate/1.e6 << "(MB/sec)\n\n";
+  
+  pl.pop("write_parallel_data");
 }
 
 
@@ -1598,7 +1652,12 @@
   parallel_only();
   std::string comment;
 
-  this->write_serialized_vector(io, *this->solution);
+  PerfLog pl("IO Performance",false);
+  pl.push("write_serialized_data");
+  unsigned int total_written_size = 0;
+  
+  total_written_size +=
+    this->write_serialized_vector(io, *this->solution);
 
   // set up the comment
   if (libMesh::processor_id() == 0)
@@ -1618,7 +1677,8 @@
 
       for(; pos != this->_vectors.end(); ++pos)
         {
-	  this->write_serialized_vector(io, *pos->second);
+	  total_written_size +=
+	    this->write_serialized_vector(io, *pos->second);
 
 	  // set up the comment
 	  if (libMesh::processor_id() == 0)
@@ -1632,6 +1692,16 @@
 	    }
 	}
     }
+
+  const Real 
+    dt   = pl.get_elapsed_time(),
+    rate = total_written_size*sizeof(Number)/dt; 
+
+  std::cout << "Write " << total_written_size << " \"Number\" values\n"
+	    << " Elapsed time = " << dt << '\n'
+	    << " Rate = " << rate/1.e6 << "(MB/sec)\n\n";
+  
+  pl.pop("write_serialized_data");
 }
 
 
@@ -1854,7 +1924,7 @@
 }
 
 
-void System::write_serialized_vector (Xdr& io, const NumericVector<Number>& vec) const
+unsigned int System::write_serialized_vector (Xdr& io, const NumericVector<Number>& vec) const
 {
   parallel_only();
 
@@ -1900,6 +1970,8 @@
 
   if (libMesh::processor_id() == 0)
     libmesh_assert_equal_to (written_length, vec_length);
+
+  return written_length;
 }
 
 } // namespace libMesh

Index: include/systems/system.h
===================================================================
--- include/systems/system.h	(revision 6279)
+++ include/systems/system.h	(working copy)
@@ -1104,6 +1104,13 @@
 			      const bool write_additional_data = true) const;
 
   /**
+   *
+   */
+  unsigned int write_serialized_vectors (Xdr &io,
+					 const std::vector<std::string> &names,
+					 const std::vector<NumericVector<Number>*> &vectors) const;
+     
+  /**
    * Writes additional data, namely vectors, for this System.
    * This method may safely be called on a distributed-memory mesh.
    * This method will create an individual file for each processor in the simulation
@@ -1510,8 +1517,8 @@
    * Reads a vector for this System.
    * This method may safely be called on a distributed-memory mesh.
    */
-  void read_serialized_vector (Xdr& io,
-			       NumericVector<Number> &vec);
+  unsigned int read_serialized_vector (Xdr& io,
+				       NumericVector<Number> &vec);
 
   /**
    * Writes an output vector to the stream \p io for a set of \p DofObjects.
@@ -1526,6 +1533,17 @@
 						     Xdr &io) const;
 
   /**
+   * Writes an output vector to the stream \p io for a set of \p DofObjects.
+   * This method uses blocked output and is safe to call on a distributed memory-mesh.
+   */
+  template <typename iterator_type>
+  unsigned int write_serialized_blocked_dof_objects (const NumericVector<Number> &vec,
+						     const unsigned int n_objects,
+						     const iterator_type begin,
+						     const iterator_type end,
+						     Xdr &io) const;
+
+  /**
    * Writes the SCALAR dofs associated with var to the stream \p io.
    */
   unsigned int write_SCALAR_dofs (const NumericVector<Number> &vec,
@@ -1536,8 +1554,8 @@
    * Writes a vector for this System.
    * This method may safely be called on a distributed-memory mesh.
    */
-  void write_serialized_vector (Xdr& io,
-				const NumericVector<Number> &vec) const;
+  unsigned int write_serialized_vector (Xdr& io,
+					const NumericVector<Number> &vec) const;
 
   /**
    * Function that initializes the system.
Index: src/systems/system_io.C
===================================================================
--- src/systems/system_io.C	(revision 6279)
+++ src/systems/system_io.C	(working copy)
@@ -475,6 +475,10 @@
    * ASCII output.  Thus this one section of code will read XDR or ASCII
    * files with no changes.
    */
+  PerfLog pl("IO Performance",false);
+  pl.push("read_parallel_data");
+  unsigned int total_read_size = 0;
+  
   libmesh_assert (io.reading());
   libmesh_assert (io.is_open());
 
@@ -514,6 +518,8 @@
   // for the ith system to disk
   io.data(io_buffer);
 
+  total_read_size += io_buffer.size();
+
   const unsigned int sys_num = this->number();
   const unsigned int n_vars  = this->_written_var_indices.size();
   libmesh_assert_less_equal (n_vars, this->n_vars());
@@ -590,6 +596,8 @@
 	  // for the ith system to disk
 	  io.data(io_buffer);
 
+	  total_read_size += io_buffer.size();
+
 	  // Loop over each non-SCALAR variable and each node, and read out the value.
           for (unsigned int data_var=0; data_var<n_vars; data_var++)
             {
@@ -644,6 +652,16 @@
           pos->second->close();
 	}
     }
+
+  const Real 
+    dt   = pl.get_elapsed_time(),
+    rate = total_read_size*sizeof(Number)/dt; 
+
+  std::cerr << "Read " << total_read_size << " \"Number\" values\n"
+	    << " Elapsed time = " << dt << '\n'
+	    << " Rate = " << rate/1.e6 << "(MB/sec)\n\n";
+
+  pl.pop("read_parallel_data");
 }
 
 
@@ -665,10 +683,15 @@
   parallel_only();
   std::string comment;
 
+  PerfLog pl("IO Performance",false);
+  pl.push("read_serialized_data");
+  unsigned int total_read_size = 0;
+
   // 10.)
   // Read the global solution vector
   {
-    this->read_serialized_vector(io, *this->solution);
+    total_read_size +=
+      this->read_serialized_vector(io, *this->solution);
 
     // get the comment
     if (libMesh::processor_id() == 0)
@@ -684,7 +707,8 @@
 
       for(; pos != this->_vectors.end(); ++pos)
         {
-	  this->read_serialized_vector(io, *pos->second);
+	  total_read_size +=
+	    this->read_serialized_vector(io, *pos->second);
 
 	  // get the comment
 	  if (libMesh::processor_id() == 0)
@@ -692,6 +716,16 @@
 
 	}
     }
+
+  const Real 
+    dt   = pl.get_elapsed_time(),
+    rate = total_read_size*sizeof(Number)/dt; 
+
+  std::cout << "Read " << total_read_size << " \"Number\" values\n"
+	    << " Elapsed time = " << dt << '\n'
+	    << " Rate = " << rate/1.e6 << "(MB/sec)\n\n";
+
+  pl.pop("read_serialized_data");
 }
 
 
@@ -894,7 +928,7 @@
 
 
 
-void System::read_serialized_vector (Xdr& io, NumericVector<Number>& vec)
+unsigned int System::read_serialized_vector (Xdr& io, NumericVector<Number>& vec)
 {
   parallel_only();
 
@@ -966,6 +1000,8 @@
   Parallel::sum (n_assigned_vals);
   libmesh_assert_equal_to (n_assigned_vals, vector_length);
 #endif
+
+  return vector_length;
 }
 
 
@@ -1408,6 +1444,10 @@
    * ASCII output.  Thus this one section of code will read XDR or ASCII
    * files with no changes.
    */
+  PerfLog pl("IO Performance",false);
+  pl.push("write_parallel_data");
+  unsigned int total_written_size = 0;
+  
   std::string comment;
 
   libmesh_assert (io.writing());
@@ -1504,6 +1544,8 @@
 
   io.data (io_buffer, comment.c_str());
 
+  total_written_size += io_buffer.size();
+
   // Only write additional vectors if wanted
   if (write_additional_data)
     {
@@ -1573,8 +1615,20 @@
 	  }
 
 	  io.data (io_buffer, comment.c_str());
+
+	  total_written_size += io_buffer.size();
 	}
     }
+
+  const Real 
+    dt   = pl.get_elapsed_time(),
+    rate = total_written_size*sizeof(Number)/dt; 
+
+  std::cerr << "Write " << total_written_size << " \"Number\" values\n"
+	    << " Elapsed time = " << dt << '\n'
+	    << " Rate = " << rate/1.e6 << "(MB/sec)\n\n";
+  
+  pl.pop("write_parallel_data");
 }
 
 
@@ -1598,7 +1652,12 @@
   parallel_only();
   std::string comment;
 
-  this->write_serialized_vector(io, *this->solution);
+  PerfLog pl("IO Performance",false);
+  pl.push("write_serialized_data");
+  unsigned int total_written_size = 0;
+  
+  total_written_size +=
+    this->write_serialized_vector(io, *this->solution);
 
   // set up the comment
   if (libMesh::processor_id() == 0)
@@ -1618,7 +1677,8 @@
 
       for(; pos != this->_vectors.end(); ++pos)
         {
-	  this->write_serialized_vector(io, *pos->second);
+	  total_written_size +=
+	    this->write_serialized_vector(io, *pos->second);
 
 	  // set up the comment
 	  if (libMesh::processor_id() == 0)
@@ -1632,6 +1692,43 @@
 	    }
 	}
     }
+
+  const Real 
+    dt   = pl.get_elapsed_time(),
+    rate = total_written_size*sizeof(Number)/dt; 
+
+  std::cout << "Write " << total_written_size << " \"Number\" values\n"
+	    << " Elapsed time = " << dt << '\n'
+	    << " Rate = " << rate/1.e6 << "(MB/sec)\n\n";
+  
+  pl.pop("write_serialized_data");
+
+  
+
+  
+  // test the new method
+  {
+    std::vector<std::string> names;
+    std::vector<NumericVector<Number>*> vectors_to_write;
+
+    names.push_back("Solution Vector");
+    vectors_to_write.push_back(this->solution.get());
+    
+    // Only write additional vectors if wanted
+    if (write_additional_data)
+      {
+	std::map<std::string, NumericVector<Number>* >::const_iterator
+	  pos = _vectors.begin();
+	
+	for(; pos != this->_vectors.end(); ++pos)
+	  {
+	    names.push_back("Additional Vector " + pos->first);
+	    vectors_to_write.push_back(pos->second);
+	  }
+      }
+
+    this->write_serialized_vectors (io, names, vectors_to_write);    
+  }
 }
 
 
@@ -1804,6 +1901,211 @@
   return written_length;
 }
 
+
+
+template <typename iterator_type>
+unsigned int System::write_serialized_blocked_dof_objects (const NumericVector<Number> &vec,
+							   const unsigned int n_objects,
+							   const iterator_type begin,
+							   const iterator_type end,
+							   Xdr &io) const
+{
+  const unsigned int
+    sys_num    = this->number(),
+    num_vars   = this->n_vars(),    
+    io_blksize = std::min(max_io_blksize, n_objects),
+    num_blks   = std::ceil(static_cast<double>(n_objects)/static_cast<double>(io_blksize));
+
+  std::cout << "io_blksize = "    << io_blksize
+	    << ", num_objects = " << n_objects
+	    << ", num_blks = "    << num_blks
+	    << std::endl;
+  
+  unsigned int written_length=0;                       // The numer of values written.  This will be returned
+
+  
+
+  std::vector<std::vector<unsigned int> > xfer_ids(num_blks);  // The global IDs and # of components for the local objects in all blocks
+  std::vector<std::vector<Number> >       xfer_vals(num_blks); // The raw values for the local objects in all blocks
+
+
+  // First pass - count the number of objects in each block
+  {
+    std::vector<unsigned int>
+      xfer_ids_size  (num_blks,0),
+      xfer_vals_size (num_blks,0);
+
+    for (iterator_type it=begin; it!=end; ++it)
+      {
+	const unsigned int
+	  id    = (*it)->id(),
+	  block = id/io_blksize;
+
+	libmesh_assert_less (block, num_blks);
+
+	//xfer_ids_size[block]  += 2;
+	//xfer_vals_size[block] += (*it)->n_comp(sys_num, var)
+      }
+  }
+
+  
+//   std::vector<unsigned int> xfer_ids;                  // The global IDs and # of components for the local objects in the current block
+//   std::vector<Number>       xfer_vals;                 // The raw values for the local objects in the current block
+//   std::vector<std::vector<unsigned int> >              // The global ID and # of components received from each processor
+//     recv_ids (libMesh::n_processors());                //  for the current block
+//   std::vector<std::vector<Number> >                    // The raw values received from each processor
+//     recv_vals(libMesh::n_processors());                //  for the current block
+//   std::vector<std::vector<Number>::iterator>           // The next value on each processor for the current block
+//     val_iters;
+//   val_iters.reserve(libMesh::n_processors());
+//   std::vector<unsigned int> &idx_map     = xfer_ids;   // map to traverse entry-wise rather than processor-wise (renamed for notational convenience)
+//   std::vector<Number>       &output_vals = xfer_vals;  // The output buffer for the current block (renamed for notational convenience)
+
+//   //---------------------------------
+//   // Collect the values for all objects
+//   unsigned int first_object=0, last_object=0;
+
+//   for (unsigned int blk=0; last_object<n_objects; blk++)
+//     {
+//       //libMesh::out << "Writing object block " << blk << " for var " << var << std::endl;
+
+//       // Each processor should build up its transfer buffers for its
+//       // local objects in [first_object,last_object).
+//       first_object = blk*io_blksize;
+//       last_object  = std::min((blk+1)*io_blksize,n_objects);
+
+//       // Clear the transfer buffers for this block.
+//       xfer_ids.clear(); xfer_vals.clear();
+
+//       for (iterator_type it=begin; it!=end; ++it)
+// 	if (((*it)->id() >= first_object) && // object in [first_object,last_object)
+// 	    ((*it)->id() <   last_object) &&
+// 	    (*it)->n_comp(sys_num,var)  )    // var has a nonzero # of components on this object
+// 	  {
+// 	    xfer_ids.push_back((*it)->id());
+// 	    xfer_ids.push_back((*it)->n_comp(sys_num, var));
+
+// 	    for (unsigned int comp=0; comp<(*it)->n_comp(sys_num, var); comp++)
+// 	      {
+// 		libmesh_assert_greater_equal ((*it)->dof_number(sys_num, var, comp), vec.first_local_index());
+// 		libmesh_assert_less ((*it)->dof_number(sys_num, var, comp), vec.last_local_index());
+// 		xfer_vals.push_back(vec((*it)->dof_number(sys_num, var, comp)));
+// 	      }
+// 	  }
+
+//       //-----------------------------------------
+//       // Send the transfer buffers to processor 0.
+
+//       // Get the size of the incoming buffers -- optionally
+//       // we could over-size the recv buffers based on
+//       // some maximum size to avoid these communications
+//       std::vector<unsigned int> ids_size, vals_size;
+//       const unsigned int my_ids_size  = xfer_ids.size();
+//       const unsigned int my_vals_size = xfer_vals.size();
+
+//       Parallel::gather (0, my_ids_size,  ids_size);
+//       Parallel::gather (0, my_vals_size, vals_size);
+
+//       // Note that we will actually send/receive to ourself if we are
+//       // processor 0, so let's use nonblocking receives.
+//       std::vector<Parallel::Request>
+// 	id_request_handles(libMesh::n_processors()),
+// 	val_request_handles(libMesh::n_processors());
+
+// #ifdef LIBMESH_HAVE_MPI
+//       Parallel::MessageTag
+//         id_tag    = Parallel::Communicator_World.get_unique_tag(2345),
+//         val_tag = Parallel::Communicator_World.get_unique_tag(2346);
+
+//       // Post the receives -- do this on processor 0 only.
+//       if (libMesh::processor_id() == 0)
+// 	for (unsigned int pid=0; pid<libMesh::n_processors(); pid++)
+// 	  {
+// 	    recv_ids[pid].resize(ids_size[pid]);
+// 	    recv_vals[pid].resize(vals_size[pid]);
+
+// 	    Parallel::nonblocking_receive (pid, recv_ids[pid],
+// 					   id_request_handles[pid],
+//                                            id_tag);
+// 	    Parallel::nonblocking_receive (pid, recv_vals[pid],
+// 					   val_request_handles[pid],
+//                                            val_tag);
+// 	  }
+
+//       // Send -- do this on all processors.
+//       Parallel::send(0, xfer_ids,  id_tag);
+//       Parallel::send(0, xfer_vals, val_tag);
+// #else
+//       // On one processor there's nothing to send
+//       recv_ids[0] = xfer_ids;
+//       recv_vals[0] = xfer_vals;
+// #endif
+
+//       // -------------------------------------------------------
+//       // Receive the messages and write the output on processor 0.
+//       if (libMesh::processor_id() == 0)
+// 	{
+// 	  // Wait for all the receives to complete. We have no
+// 	  // need for the statuses since we already know the
+// 	  // buffer sizes.
+// 	  Parallel::wait (id_request_handles);
+// 	  Parallel::wait (val_request_handles);
+
+// 	  // Write the values in this block.
+// 	  unsigned int tot_id_size=0, tot_val_size=0;
+// 	  val_iters.clear();
+// 	  for (unsigned int pid=0; pid<libMesh::n_processors(); pid++)
+// 	    {
+// 	      tot_id_size  += recv_ids[pid].size();
+// 	      tot_val_size += recv_vals[pid].size();
+// 	      val_iters.push_back(recv_vals[pid].begin());
+// 	    }
+
+// 	  libmesh_assert_less_equal (tot_id_size, 2*std::min(io_blksize,n_objects));
+
+// 	  // Create a map to avoid searching.  This will allow us to
+// 	  // traverse the received values in [first_object,last_object) order.
+// 	  idx_map.resize(3*io_blksize); std::fill (idx_map.begin(), idx_map.end(), libMesh::invalid_uint);
+// 	  for (unsigned int pid=0; pid<libMesh::n_processors(); pid++)
+// 	    for (unsigned int idx=0; idx<recv_ids[pid].size(); idx+=2)
+// 	      {
+// 		const unsigned int local_idx = recv_ids[pid][idx+0]-first_object;
+// 		libmesh_assert_less (local_idx, std::min(io_blksize,n_objects));
+// 		const unsigned int n_comp    = recv_ids[pid][idx+1];
+
+// 		idx_map[3*local_idx+0] = pid;
+// 		idx_map[3*local_idx+1] = n_comp;
+// 		idx_map[3*local_idx+2] = std::distance(recv_vals[pid].begin(), val_iters[pid]);
+// 		val_iters[pid] += n_comp;
+// 	      }
+
+// 	  output_vals.clear(); output_vals.reserve (tot_val_size);
+// 	  for (unsigned int idx=0; idx<idx_map.size(); idx+=3)
+// 	    if (idx_map[idx] != libMesh::invalid_uint) // this could happen when a local object
+// 	      {                                        // has no components for the current variable
+// 		const unsigned int pid       = idx_map[idx+0];
+// 		const unsigned int n_comp    = idx_map[idx+1];
+// 		const unsigned int first_pos = idx_map[idx+2];
+
+// 		for (unsigned int comp=0; comp<n_comp; comp++)
+// 		  {
+// 		    libmesh_assert_less (first_pos + comp, recv_vals[pid].size());
+// 		    output_vals.push_back(recv_vals[pid][first_pos + comp]);
+// 		  }
+// 	      }
+// 	  libmesh_assert_equal_to (output_vals.size(), tot_val_size);
+
+// 	  // write the stream
+// 	  io.data_stream (output_vals.empty() ? NULL : &output_vals[0], output_vals.size());
+// 	  written_length += output_vals.size();
+// 	} // end processor 0 conditional block
+//     } // end object block loop
+
+//   return written_length;
+}
+
+
+
 unsigned int System::write_SCALAR_dofs (const NumericVector<Number> &vec,
                                         const unsigned int var,
 					Xdr &io) const
@@ -1854,7 +2156,8 @@
 }
 
 
-void System::write_serialized_vector (Xdr& io, const NumericVector<Number>& vec) const
+
+unsigned int System::write_serialized_vector (Xdr& io, const NumericVector<Number>& vec) const
 {
   parallel_only();
 
@@ -1900,8 +2203,58 @@
 
   if (libMesh::processor_id() == 0)
     libmesh_assert_equal_to (written_length, vec_length);
+
+  return written_length;
 }
 
+
+
+unsigned int System::write_serialized_vectors (Xdr &io,
+					       const std::vector<std::string> &names,
+					       const std::vector<NumericVector<Number>*> &vectors) const
+{
+  parallel_only();
+
+  libmesh_assert (io.writing());
+
+  // Cache these - they are not free!
+  const unsigned int
+    n_nodes = this->get_mesh().n_nodes(),
+    n_elem  = this->get_mesh().n_elem();  
+
+  unsigned int written_length = 0.;
+  
+  // Loop over each vetor and write it out, object-major
+  for (std::vector<NumericVector<Number>*>::const_iterator vec_it=vectors.begin();
+       vec_it!=vectors.end(); ++vec_it)
+    {
+      libmesh_assert_not_equal_to (*vec_it, NULL);
+      const NumericVector<Number> &vec(**vec_it);
+
+      //---------------------------------
+      // Collect the values for all nodes
+      written_length +=
+	this->write_serialized_blocked_dof_objects (vec,
+						    n_nodes,
+						    this->get_mesh().local_nodes_begin(),
+						    this->get_mesh().local_nodes_end(),
+						    io);
+
+      //------------------------------------
+      // Collect the values for all elements
+      written_length +=
+	this->write_serialized_blocked_dof_objects (vec,
+						    n_elem,
+						    this->get_mesh().local_elements_begin(),
+						    this->get_mesh().local_elements_end(),
+						    io);
+
+      // and finally any scalars
+    }
+      
+  return written_length;
+}
+
 } // namespace libMesh
 
 
Index: examples/introduction/introduction_ex2/introduction_ex2.C
===================================================================
--- examples/introduction/introduction_ex2/introduction_ex2.C	(revision 6279)
+++ examples/introduction/introduction_ex2/introduction_ex2.C	(working copy)
@@ -81,7 +81,7 @@
   // 2D grid on the unit square.  By default a mesh of QUAD4
