我需要从GCS下载多个文件。为此,我使用了代码
public class GCSStorage
{
static HttpClient httpClient;
static GoogleCredential credential = GoogleCredential.FromFile(ConfigurationManager.AppSettings["GCPCredentials"]);
if (credential.IsCreateScopedRequired)
{
credential = credential.CreateScoped(new[]
{
"https://www.googleapis.com/auth/devstorage.read_only"
});
httpClient = new Google.Apis.Http.HttpClientFactory()
.CreateHttpClient(
new Google.Apis.Http.CreateHttpClientArgs()
{
ApplicationName = "",
GZipEnabled = true,
Initializers = { credential },
});
httpClient.Timeout = new TimeSpan(0, 0, 5);
}
public string ReadObjectData(string bucketName, string location)
{
string responseBody = "";
bool isFetched = false;
try
{
Stopwatch sw = new Stopwatch();
string pathcode = System.Web.HttpUtility.UrlEncode(location);
UriBuilder uri = new UriBuilder(string.Format(googleStorageApi, bucketName, pathcode));
sw.Start();
var httpResponseMessage = httpClient.GetAsync(uri.Uri).Result;
var t = sw.ElapsedMilliseconds;
if (httpResponseMessage.StatusCode == HttpStatusCode.OK)
{
responseBody = httpResponseMessage.Content.ReadAsStringAsync().Result;
log.Info($"Read file from location : {location} in Get() time : {t} ms , ReadAsString time : {sw.ElapsedMilliseconds - t} ms, Total time : {sw.ElapsedMilliseconds} ms");
}
isFetched = true;
}
catch (Exception ex)
{
throw ex;
}
return responseBody;
}
}
并使用
将其称为多个文件GCSStorage gcs = new GCSStorage();
ParallelOptions option = new ParallelOptions { MaxDegreeOfParallelism = options };
Parallel.ForEach(myFiles, option, ri =>
{
text = gcs.ReadObjectData(bucket, ri); ;
});
我正在将每个单独的文件花费的时间记录在ReadObjectData()中。当我使用MaxDegreeOfParallelism作为1下载文件时,每个文件的下载时间约为100-150ms。但是,当我将MaxDegreeOfParallelism更改为50时,时间在1-3秒之间变化。我正在下载一堆50个文件。
我不知道为什么会这样。谁能帮助我了解这种行为。
此外,我尝试使用Amazon S3进行相同操作。在这两种情况下,S3的下载时间恒定为50-100ms。
我使用提琴手分析了GCS响应。对于耗时(〜> 200ms)的请求,总体经过时间大约为100-200 ms,但是写入日志的时间要长得多。对于其他人来说,恰恰是在同一时间。 为什么某些请求的时间会有如此大的时差?
提琴手统计
Request Count: 1
Bytes Sent: 439 (headers:439; body:0)
Bytes Received: 7,759 (headers:609; body:7,150)
ACTUAL PERFORMANCE
--------------
ClientConnected: 18:03:35.137
ClientBeginRequest: 18:04:13.606
GotRequestHeaders: 18:04:13.606
ClientDoneRequest: 18:04:13.606
Determine Gateway: 0ms
DNS Lookup: 0ms
TCP/IP Connect: 0ms
HTTPS Handshake: 0ms
ServerConnected: 18:03:35.152
FiddlerBeginRequest: 18:04:13.606
ServerGotRequest: 18:04:13.606
ServerBeginResponse: 18:04:13.700
GotResponseHeaders: 18:04:13.700
ServerDoneResponse: 18:04:13.700
ClientBeginResponse: 18:04:13.700
ClientDoneResponse: 18:04:13.700
Overall Elapsed: 0:00:00.093
日志文件
INFO 2018-08-25 18:04:13,606 41781ms GCSStorage ReadObjectData - Get() time : 114 ms
INFO 2018-08-25 18:04:14,512 42688ms GCSStorage ReadObjectData - Get() time : 902 ms
我可以看到
LogTime - ClientDoneResponse + Overall Elapsed is approximately equal to Total Time
18:04:14.512 - 18:04:13.700 + 0:00:00.093 = 905 ms
为什么从服务器接收到的响应并将其写入日志的时间差会如此之大?
答案 0 :(得分:0)
在执行并行编程时,需要注意多个线程。首先,并行确实可以提高性能,但并不是说无限并行比顺序更好。这件事情是由很多原因导致的。一是您受到物理核心数量以及操作系统中超线程的限制。例如,如果您有8个核心,则使用8个线程可获得最佳性能,如果还激活了超线程,则可能只有16个线程才具有良好的性能。
在您的示例中,将线程数从1更改为50太多了。以第2、4、6、8、10步进行尝试,看看何时获得最佳性能(记录到目前为止的时间)。
那么该数字很可能是您的并行性的最佳数字。