I am trying to upload a large file (> 1 GB) from one server to another using HTTP. To do this, I am making HTTP range requests in parallel. This allows me to upload a file in parallel.
When saving to disk, I take each response stream, opening the same file as a file stream, aiming for the range that I want, and then writing.
However, I find that all but one of my response streams expire. It seems that disk I / O cannot keep up with network I / O. However, if I do the same, but each stream writes to a separate file, it works fine.
For reference, here is my code entry in the same file:
int numberOfStreams = 4; List<Tuple<int, int>> ranges = new List<Tuple<int, int>>(); string fileName = @"C:\MyCoolFile.txt"; //List populated here Parallel.For(0, numberOfStreams, (index, state) => { try { HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create("Some URL"); using(Stream responseStream = webRequest.GetResponse().GetResponseStream()) { using (FileStream fileStream = File.Open(fileName, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Write)) { fileStream.Seek(ranges[index].Item1, SeekOrigin.Begin); byte[] buffer = new byte[64 * 1024]; int bytesRead; while ((bytesRead = responseStream.Read(buffer, 0, buffer.Length)) > 0) { if (state.IsStopped) { return; } fileStream.Write(buffer, 0, bytesRead); } } }; } catch (Exception e) { exception = e; state.Stop(); } });
And here is the code that writes several files:
int numberOfStreams = 4; List<Tuple<int, int>> ranges = new List<Tuple<int, int>>(); string fileName = @"C:\MyCoolFile.txt"; //List populated here Parallel.For(0, numberOfStreams, (index, state) => { try { HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create("Some URL"); using(Stream responseStream = webRequest.GetResponse().GetResponseStream()) { using (FileStream fileStream = File.Open(fileName + "." + index + ".tmp", FileMode.OpenOrCreate, FileAccess.Write, FileShare.Write)) { fileStream.Seek(ranges[index].Item1, SeekOrigin.Begin); byte[] buffer = new byte[64 * 1024]; int bytesRead; while ((bytesRead = responseStream.Read(buffer, 0, buffer.Length)) > 0) { if (state.IsStopped) { return; } fileStream.Write(buffer, 0, bytesRead); } } }; } catch (Exception e) { exception = e; state.Stop(); } });
My question is, are there any additional checks / actions that C # / Windows takes when writing to a single file from multiple streams, which will cause file I / O to be slower than when writing to multiple files? Should all disk operations be related by the speed of the disk to the right? Can anyone explain this behavior?
Thanks in advance!
UPDATE: Here is the error that the source server is starting:
"Cannot write data to the transport connection: the connection attempt failed because the connected party did not respond properly after some time or the connection failed because the connected host was unable to respond." [System.IO.IOException]: "Unable to write data to the transport connection: the connection attempt failed because the connected party did not respond properly after some time or the connection failed because the connected host was unable to respond." InnerException: "The connection attempt failed because the connected party did not respond properly after some time or the connection could not be established because the connected host was unable to respond" Message: "Unable to write data to the transport connection: connection attempt failed because the related party didn’t respond properly after some time or the connection failed because the connected host was unable to respond. " StackTrace: "in System.Net.Sockets.NetworkStream.Write (Byte [] buffer, Int32 offset, Int32 size) \ r \ n in System.Net.Security._SslStream.StartWriting (Byte [] buffer, Int32 offset, Int32 count , AsyncProtocolRequest asyncRequest) \ r \ n in System.Net.Security._SslStream.ProcessWrite (Byte buffer [], Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest) \ r \ n in System.Net.Security.SslStream.Write (Byte [ ], offset Int32, number Int32) \ r \ n