diff --git a/cloud/blockstore/libs/client_rdma/rdma_client.cpp b/cloud/blockstore/libs/client_rdma/rdma_client.cpp index 559fee648cd..3f43875ac75 100644 --- a/cloud/blockstore/libs/client_rdma/rdma_client.cpp +++ b/cloud/blockstore/libs/client_rdma/rdma_client.cpp @@ -66,19 +66,25 @@ struct IRequestHandler: public NRdma::TNullContext //////////////////////////////////////////////////////////////////////////////// template -void ProcessPostponeTime( +void ProcessThrottleTime( const TCallContextPtr& callContext, TResponse& localResponse) { + NProto::TThrottlerInfo& throttler = + *localResponse.MutableHeaders()->MutableThrottler(); const ui64 throttlerDelay = - Max(localResponse.GetDeprecatedThrottlerDelay(), - localResponse.GetHeaders().GetThrottler().GetDelay()); + Max(localResponse.GetDeprecatedThrottlerDelay(), throttler.GetDelay()); callContext->AddTime( EProcessingStage::Postponed, TDuration::MicroSeconds(throttlerDelay)); localResponse.SetDeprecatedThrottlerDelay(0); - localResponse.MutableHeaders()->MutableThrottler()->SetDelay(0); + throttler.SetDelay(0); callContext->SetPossiblePostponeDuration(TDuration::Zero()); + + callContext->AddTime( + EProcessingStage::Shaping, + TDuration::MicroSeconds(throttler.GetShapingDelay())); + throttler.SetShapingDelay(0); } //////////////////////////////////////////////////////////////////////////////// @@ -181,7 +187,7 @@ class TReadBlocksHandler final responseMsg.MutableHeaders()->ClearTrace(); } - ProcessPostponeTime(CallContext, localResponse); + ProcessThrottleTime(CallContext, localResponse); Response.SetValue(std::move(localResponse)); } @@ -316,7 +322,7 @@ class TWriteBlocksHandler final responseMsg.MutableHeaders()->ClearTrace(); } - ProcessPostponeTime(CallContext, responseMsg); + ProcessThrottleTime(CallContext, responseMsg); Response.SetValue(std::move(responseMsg)); } @@ -418,7 +424,7 @@ class TZeroBlocksHandler final responseMsg.MutableHeaders()->ClearTrace(); responseMsg.ClearDeprecatedTrace(); - ProcessPostponeTime(CallContext, responseMsg); + ProcessThrottleTime(CallContext, responseMsg); Response.SetValue(std::move(responseMsg)); } diff --git a/cloud/blockstore/libs/service_rdma/rdma_target.cpp b/cloud/blockstore/libs/service_rdma/rdma_target.cpp index 1f3fd66aee6..cecfe0292e2 100644 --- a/cloud/blockstore/libs/service_rdma/rdma_target.cpp +++ b/cloud/blockstore/libs/service_rdma/rdma_target.cpp @@ -67,6 +67,10 @@ void FillResponse(const TCallContextPtr& callContext, TResponse& response) callContext->Time(EProcessingStage::Postponed).MicroSeconds(); response.SetDeprecatedThrottlerDelay(postponeTime); response.MutableHeaders()->MutableThrottler()->SetDelay(postponeTime); + + const ui64 shapingTime = + callContext->Time(EProcessingStage::Shaping).MicroSeconds(); + response.MutableHeaders()->MutableThrottler()->SetShapingDelay(shapingTime); } //////////////////////////////////////////////////////////////////////////////// diff --git a/cloud/blockstore/libs/storage/service/volume_client_actor.cpp b/cloud/blockstore/libs/storage/service/volume_client_actor.cpp index e8fc39b68ac..674b51264dd 100644 --- a/cloud/blockstore/libs/storage/service/volume_client_actor.cpp +++ b/cloud/blockstore/libs/storage/service/volume_client_actor.cpp @@ -378,15 +378,22 @@ void TVolumeClientActor::HandleResponse( THasGetDeprecatedThrottlerDelay::value); if constexpr (RequiresThrottling) { + NProto::TThrottlerInfo& throttler = + *msg->Record.MutableHeaders()->MutableThrottler(); const ui64 throttlerDelay = Max(msg->Record.GetDeprecatedThrottlerDelay(), - msg->Record.GetHeaders().GetThrottler().GetDelay()); + throttler.GetDelay()); it->second.CallContext->AddTime( EProcessingStage::Postponed, TDuration::MicroSeconds(throttlerDelay)); msg->Record.SetDeprecatedThrottlerDelay(0); - msg->Record.MutableHeaders()->MutableThrottler()->SetDelay(0); + throttler.SetDelay(0); it->second.CallContext->SetPossiblePostponeDuration(TDuration::Zero()); + + it->second.CallContext->AddTime( + EProcessingStage::Shaping, + TDuration::MicroSeconds(throttler.GetShapingDelay())); + throttler.SetShapingDelay(0); } LWTRACK( diff --git a/cloud/blockstore/libs/storage/volume/volume_actor_forward.cpp b/cloud/blockstore/libs/storage/volume/volume_actor_forward.cpp index 941b284e7b6..0290642473d 100644 --- a/cloud/blockstore/libs/storage/volume/volume_actor_forward.cpp +++ b/cloud/blockstore/libs/storage/volume/volume_actor_forward.cpp @@ -31,7 +31,10 @@ namespace { Y_HAS_MEMBER(SetDeprecatedThrottlerDelay); template -void StoreThrottlerDelay(typename TMethod::TResponse& response, TDuration delay) +void StoreThrottlerDelay( + typename TMethod::TResponse& response, + TDuration delay, + TDuration shapingDelay) { using TProtoType = decltype(TMethod::TResponse::Record); static_assert( @@ -41,6 +44,8 @@ void StoreThrottlerDelay(typename TMethod::TResponse& response, TDuration delay) response.Record.SetDeprecatedThrottlerDelay(delay.MicroSeconds()); response.Record.MutableHeaders()->MutableThrottler()->SetDelay( delay.MicroSeconds()); + response.Record.MutableHeaders()->MutableThrottler()->SetShapingDelay( + shapingDelay.MicroSeconds()); } } @@ -59,7 +64,8 @@ void RejectVolumeRequest( StoreThrottlerDelay( *response, - callContext.Time(EProcessingStage::Postponed)); + callContext.Time(EProcessingStage::Postponed), + callContext.Time(EProcessingStage::Shaping)); NCloud::Send(ctx, caller, std::move(response), callerCookie); } @@ -321,7 +327,8 @@ void TVolumeActor::FillResponse( StoreThrottlerDelay( response, - callContext.Time(EProcessingStage::Postponed)); + callContext.Time(EProcessingStage::Postponed), + callContext.Time(EProcessingStage::Shaping)); } //////////////////////////////////////////////////////////////////////////////// diff --git a/cloud/blockstore/libs/storage/volume_proxy/volume_proxy.cpp b/cloud/blockstore/libs/storage/volume_proxy/volume_proxy.cpp index 9367b84b4e9..6637b9edd9e 100644 --- a/cloud/blockstore/libs/storage/volume_proxy/volume_proxy.cpp +++ b/cloud/blockstore/libs/storage/volume_proxy/volume_proxy.cpp @@ -826,15 +826,22 @@ void TVolumeProxyActor::HandleResponse( THasGetDeprecatedThrottlerDelay::value == RequiresThrottling); if constexpr (RequiresThrottling) { + NProto::TThrottlerInfo& throttler = + *msg->Record.MutableHeaders()->MutableThrottler(); const ui64 throttlerDelay = Max(msg->Record.GetDeprecatedThrottlerDelay(), - msg->Record.GetHeaders().GetThrottler().GetDelay()); + throttler.GetDelay()); it->second.CallContext->AddTime( EProcessingStage::Postponed, TDuration::MicroSeconds(throttlerDelay)); msg->Record.SetDeprecatedThrottlerDelay(0); - msg->Record.MutableHeaders()->MutableThrottler()->SetDelay(0); + throttler.SetDelay(0); it->second.CallContext->SetPossiblePostponeDuration(TDuration::Zero()); + + it->second.CallContext->AddTime( + EProcessingStage::Shaping, + TDuration::MicroSeconds(throttler.GetShapingDelay())); + throttler.SetShapingDelay(0); } LWTRACK( diff --git a/cloud/storage/core/libs/common/context.cpp b/cloud/storage/core/libs/common/context.cpp index 9fc1fbf0489..ca455c015b9 100644 --- a/cloud/storage/core/libs/common/context.cpp +++ b/cloud/storage/core/libs/common/context.cpp @@ -30,13 +30,14 @@ TRequestTime TCallContextBase::CalcRequestTime(ui64 nowCycles) const const auto postponeDuration = Time(EProcessingStage::Postponed); const auto backoffTime = Time(EProcessingStage::Backoff); + const auto shapingTime = Time(EProcessingStage::Shaping); auto responseSentCycles = GetResponseSentCycles(); auto responseDuration = CyclesToDurationSafe( (responseSentCycles ? responseSentCycles : nowCycles) - startCycles); requestTime.ExecutionTime = responseDuration - postponeDuration - - backoffTime - GetPossiblePostponeDuration(); + backoffTime - shapingTime - GetPossiblePostponeDuration(); return requestTime; } diff --git a/cloud/storage/core/libs/common/context.h b/cloud/storage/core/libs/common/context.h index cd3efae3a0f..da9dabf0f7d 100644 --- a/cloud/storage/core/libs/common/context.h +++ b/cloud/storage/core/libs/common/context.h @@ -13,7 +13,9 @@ enum class EProcessingStage { Postponed, Backoff, - Last + Shaping, + + Last = Shaping, }; struct TRequestTime @@ -33,7 +35,7 @@ struct TCallContextBase : public TThrRefBase { private: - TAtomic Stage2Time[static_cast(EProcessingStage::Last)] = {}; + TAtomic Stage2Time[static_cast(EProcessingStage::Last) + 1] = {}; TAtomic RequestStartedCycles = 0; TAtomic ResponseSentCycles = 0; TAtomic PossiblePostponeMicroSeconds = 0; diff --git a/cloud/storage/core/protos/throttler.proto b/cloud/storage/core/protos/throttler.proto index 4357fc77f4d..71cb85b6cae 100644 --- a/cloud/storage/core/protos/throttler.proto +++ b/cloud/storage/core/protos/throttler.proto @@ -11,4 +11,7 @@ message TThrottlerInfo { // Time spent by a request in the throttler queue in us. uint64 Delay = 1; + + // Time spent by a request in the shaping queue in us. + uint64 ShapingDelay = 2; }