This is the mail archive of the cygwin mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

performance degradation because of sparse file handling in cygwin


Hi,
 I have some questions about handling of sparse file in cygwin 1.5.5
onwards. cygwin makes a file as a sparse if there is a write request  
beyond 128 KB from file end. I am not sure whether it is a heuristic or
some statistical fact governs the use of 128 KB. Please clarify.
The code of fhandler_base::write in fhandler.cc suggest that the check for
sparse file runs if there has been a seek before write request. The code
performs fine when dealing with local file. For files on network (netapps
or samba) write performance degrades because of this code. If a testcase
performs seek followed by write then each time code checks whether the
file is sparse or not. In that case GetFileSize gets called each time
write is performed, which takes good amount of time on network.
Is there any alternative to GetFileSize which
does not take much time? I searched in MSDN and found none faster than
GetFileSize.
I found that if i comment GetFileSize then the
same application takes half of the time what it was taking before on
samba.

The code in question is written below:

else if (get_did_lseek ())
    {
      _off64_t actual_length, current_position;
      DWORD size_high = 0;
      LONG pos_high = 0;

      set_did_lseek (0); /* don't do it again */

      actual_length = GetFileSize (get_output_handle (), &size_high);
      actual_length += ((_off64_t) size_high) << 32;

      current_position = SetFilePointer (get_output_handle (), 0,
&pos_high,
					 FILE_CURRENT);
      current_position += ((_off64_t) pos_high) << 32;

      if (current_position > actual_length)
	{
	  if ((get_fs_flags (FILE_SUPPORTS_SPARSE_FILES))
	      && current_position >= actual_length + (128 * 1024))
	    {
	      /* If the file systemn supports sparse files and the
application
	         is writing after a long seek beyond EOF, convert the file
to
		 a sparse file. */
	      DWORD dw;
	      HANDLE h = get_output_handle ();
	      BOOL r = DeviceIoControl (h, FSCTL_SET_SPARSE, NULL, 0,
NULL,
	      				0, &dw, NULL);
	      syscall_printf ("%d = DeviceIoControl(%p, FSCTL_SET_SPARSE,
"
			      "NULL, 0, NULL, 0, &dw, NULL)", r, h);
	    }
	  else if (wincap.has_lseek_bug ())
	    {
	      /* Oops, this is the bug case - Win95 uses whatever is on
the
	         disk instead of some known (safe) value, so we must seek
		 back and fill in the gap with zeros. - DJ
	         Note: this bug doesn't happen on NT4, even though the
	         documentation for WriteFile() says that it *may* happen
		 on any OS. */
	      char zeros[512];
	      int number_of_zeros_to_write = current_position -
actual_length;
	      memset (zeros, 0, 512);
	      SetFilePointer (get_output_handle (), 0, NULL, FILE_END);
	      while (number_of_zeros_to_write > 0)
		{
		  DWORD zeros_this_time = (number_of_zeros_to_write > 512
					 ? 512 :
number_of_zeros_to_write);
		  DWORD written;
		  if (!WriteFile (get_output_handle (), zeros,
zeros_this_time,
				  &written, NULL))
		    {
		      __seterrno ();
		      if (get_errno () == EPIPE)
			raise (SIGPIPE);
		      /* This might fail, but it's the best we can hope
for */
		      SetFilePointer (get_output_handle (),
current_position, NULL,
				      FILE_BEGIN);
		      return -1;

		    }
		  if (written < zeros_this_time) /* just in case */
		    {
		      set_errno (ENOSPC);
		      /* This might fail, but it's the best we can hope
for */
		      SetFilePointer (get_output_handle (),
current_position, NULL,
				      FILE_BEGIN);
		      return -1;
		    }
		  number_of_zeros_to_write -= written;
		}
	    }
	}
    }



regards
Vinay					





--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Problem reports:       http://cygwin.com/problems.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]