Skip to content

Commit

Permalink
Remove RequestTimeStatista (WalletWasabi#12972)
Browse files Browse the repository at this point in the history
`dotnet counters` provides this info and more. `dotnet trace` can show us exactly for long it takes each call of each method.
  • Loading branch information
lontivero authored May 6, 2024
1 parent 4aea284 commit eda718b
Show file tree
Hide file tree
Showing 8 changed files with 63 additions and 341 deletions.
3 changes: 0 additions & 3 deletions WalletWasabi.Backend/Controllers/BlockchainController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,11 @@
using WalletWasabi.BitcoinCore.Mempool;
using WalletWasabi.BitcoinCore.Rpc;
using WalletWasabi.Blockchain.Analysis.FeesEstimation;
using WalletWasabi.Blockchain.BlockFilters;
using WalletWasabi.Cache;
using WalletWasabi.Extensions;
using WalletWasabi.Helpers;
using WalletWasabi.Logging;
using WalletWasabi.Models;
using WalletWasabi.WabiSabi.Backend.Statistics;

namespace WalletWasabi.Backend.Controllers;

Expand Down Expand Up @@ -434,7 +432,6 @@ public async Task<IActionResult> GetUnconfirmedTransactionChainAsync([FromQuery,
action: (string request, CancellationToken token) => GetUnconfirmedTransactionChainNoCacheAsync(txId, token),
options: UnconfirmedTransactionChainCacheEntryOptions,
cancellationToken);
RequestTimeStatista.Instance.Add("unconfirmed-transaction-chain", DateTimeOffset.UtcNow - before);
return ret;
}
catch (OperationCanceledException)
Expand Down
44 changes: 4 additions & 40 deletions WalletWasabi.Backend/Controllers/WabiSabiController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,10 @@ public WabiSabiController(IdempotencyRequestCache idempotencyRequestCache, Arena
[HttpPost("status")]
public async Task<RoundStateResponse> GetStatusAsync(RoundStateRequest request, CancellationToken cancellationToken)
{
var before = DateTimeOffset.UtcNow;
var response = await Arena.GetStatusAsync(request, cancellationToken);
var medians = CoinJoinFeeRateStatStore.GetDefaultMedians();
var affiliateInformation = AffiliationManager.GetAffiliateInformation();
var ret = new RoundStateResponse(response.RoundStates, medians, affiliateInformation);

var duration = DateTimeOffset.UtcNow - before;
RequestTimeStatista.Instance.Add("status", duration);
return ret;
return new RoundStateResponse(response.RoundStates, medians, affiliateInformation);
}

[HttpPost("connection-confirmation")]
Expand All @@ -58,12 +53,7 @@ public async Task<ConnectionConfirmationResponse> ConfirmConnectionAsync(Connect
using CancellationTokenSource timeoutCts = new(RequestTimeout);
using CancellationTokenSource linkedCts = CancellationTokenSource.CreateLinkedTokenSource(timeoutCts.Token, cancellationToken);

var before = DateTimeOffset.UtcNow;
var ret = await IdempotencyRequestCache.GetCachedResponseAsync(request, action: Arena.ConfirmConnectionAsync, linkedCts.Token);

var duration = DateTimeOffset.UtcNow - before;
RequestTimeStatista.Instance.Add("connection-confirmation", duration);
return ret;
return await IdempotencyRequestCache.GetCachedResponseAsync(request, action: Arena.ConfirmConnectionAsync, linkedCts.Token);
}

[HttpPost("input-registration")]
Expand All @@ -72,12 +62,7 @@ public async Task<InputRegistrationResponse> RegisterInputAsync(InputRegistratio
using CancellationTokenSource timeoutCts = new(RequestTimeout);
using CancellationTokenSource linkedCts = CancellationTokenSource.CreateLinkedTokenSource(timeoutCts.Token, cancellationToken);

var before = DateTimeOffset.UtcNow;
InputRegistrationResponse ret = await IdempotencyRequestCache.GetCachedResponseAsync(request, Arena.RegisterInputAsync, linkedCts.Token);

var duration = DateTimeOffset.UtcNow - before;
RequestTimeStatista.Instance.Add("input-registration", duration);
return ret;
return await IdempotencyRequestCache.GetCachedResponseAsync(request, Arena.RegisterInputAsync, linkedCts.Token);
}

[HttpPost("output-registration")]
Expand All @@ -86,11 +71,7 @@ public async Task RegisterOutputAsync(OutputRegistrationRequest request, Cancell
using CancellationTokenSource timeoutCts = new(RequestTimeout);
using CancellationTokenSource linkedCts = CancellationTokenSource.CreateLinkedTokenSource(timeoutCts.Token, cancellationToken);

var before = DateTimeOffset.UtcNow;
await IdempotencyRequestCache.GetCachedResponseAsync(request, action: Arena.RegisterOutputCoreAsync, linkedCts.Token);

var duration = DateTimeOffset.UtcNow - before;
RequestTimeStatista.Instance.Add("output-registration", duration);
}

[HttpPost("credential-issuance")]
Expand All @@ -99,42 +80,25 @@ public async Task<ReissueCredentialResponse> ReissuanceAsync(ReissueCredentialRe
using CancellationTokenSource timeoutCts = new(RequestTimeout);
using CancellationTokenSource linkedCts = CancellationTokenSource.CreateLinkedTokenSource(timeoutCts.Token, cancellationToken);

var before = DateTimeOffset.UtcNow;
var ret = await IdempotencyRequestCache.GetCachedResponseAsync(request, action: Arena.ReissuanceAsync, linkedCts.Token);

var duration = DateTimeOffset.UtcNow - before;
RequestTimeStatista.Instance.Add("credential-issuance", duration);
return ret;
return await IdempotencyRequestCache.GetCachedResponseAsync(request, action: Arena.ReissuanceAsync, linkedCts.Token);
}

[HttpPost("input-unregistration")]
public async Task RemoveInputAsync(InputsRemovalRequest request, CancellationToken cancellableToken)
{
var before = DateTimeOffset.UtcNow;
await Arena.RemoveInputAsync(request, cancellableToken);

var duration = DateTimeOffset.UtcNow - before;
RequestTimeStatista.Instance.Add("input-unregistration", duration);
}

[HttpPost("transaction-signature")]
public async Task SignTransactionAsync(TransactionSignaturesRequest request, CancellationToken cancellableToken)
{
var before = DateTimeOffset.UtcNow;
await Arena.SignTransactionAsync(request, cancellableToken);

var duration = DateTimeOffset.UtcNow - before;
RequestTimeStatista.Instance.Add("transaction-signature", duration);
}

[HttpPost("ready-to-sign")]
public async Task ReadyToSignAsync(ReadyToSignRequestRequest request, CancellationToken cancellableToken)
{
var before = DateTimeOffset.UtcNow;
await Arena.ReadyToSignAsync(request, cancellableToken);

var duration = DateTimeOffset.UtcNow - before;
RequestTimeStatista.Instance.Add("ready-to-sign", duration);
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
using Moq;
using NBitcoin;
using NBitcoin.RPC;
using SQLitePCL;
using WalletWasabi.BitcoinCore.Rpc;
using WalletWasabi.Helpers;
using WalletWasabi.JsonConverters.Timing;
Expand Down
170 changes: 59 additions & 111 deletions WalletWasabi/BitcoinCore/Rpc/RpcClientBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
using System.Threading.Tasks;
using WalletWasabi.BitcoinCore.Rpc.Models;
using WalletWasabi.Extensions;
using WalletWasabi.WabiSabi.Backend.Statistics;

namespace WalletWasabi.BitcoinCore.Rpc;

Expand All @@ -27,126 +26,101 @@ public RpcClientBase(RPCClient rpc)

public virtual async Task<uint256> GetBestBlockHashAsync(CancellationToken cancellationToken = default)
{
return await MeasureAsync(
nameof(GetBestBlockHashAsync),
() => Rpc.GetBestBlockHashAsync(cancellationToken)).ConfigureAwait(false);
return await Rpc.GetBestBlockHashAsync(cancellationToken).ConfigureAwait(false);
}

public virtual async Task<Block> GetBlockAsync(uint256 blockHash, CancellationToken cancellationToken = default)
{
return await MeasureAsync(
nameof(GetBlockAsync),
() => Rpc.GetBlockAsync(blockHash, cancellationToken)).ConfigureAwait(false);
return await Rpc.GetBlockAsync(blockHash, cancellationToken).ConfigureAwait(false);
}

public virtual async Task<Block> GetBlockAsync(uint blockHeight, CancellationToken cancellationToken = default)
{
return await MeasureAsync(
nameof(GetBlockAsync),
() => Rpc.GetBlockAsync(blockHeight, cancellationToken)).ConfigureAwait(false);
return await Rpc.GetBlockAsync(blockHeight, cancellationToken).ConfigureAwait(false);
}

public virtual async Task<BlockHeader> GetBlockHeaderAsync(uint256 blockHash, CancellationToken cancellationToken = default)
{
return await MeasureAsync(
nameof(GetBlockHeaderAsync),
() => Rpc.GetBlockHeaderAsync(blockHash, cancellationToken)).ConfigureAwait(false);
return await Rpc.GetBlockHeaderAsync(blockHash, cancellationToken).ConfigureAwait(false);
}

public virtual async Task<BlockchainInfo> GetBlockchainInfoAsync(CancellationToken cancellationToken = default)
{
return await MeasureAsync(
nameof(GetBlockchainInfoAsync),
() => Rpc.GetBlockchainInfoAsync(cancellationToken)).ConfigureAwait(false);
return await Rpc.GetBlockchainInfoAsync(cancellationToken).ConfigureAwait(false);
}

public virtual async Task<PeerInfo[]> GetPeersInfoAsync(CancellationToken cancellationToken = default)
{
return await MeasureAsync(
nameof(GetPeersInfoAsync),
() => Rpc.GetPeersInfoAsync(cancellationToken)).ConfigureAwait(false);
return await Rpc.GetPeersInfoAsync(cancellationToken).ConfigureAwait(false);
}

public virtual async Task<MempoolEntry> GetMempoolEntryAsync(uint256 txid, bool throwIfNotFound = true, CancellationToken cancellationToken = default)
{
return await MeasureAsync(
nameof(GetMempoolEntryAsync),
() => Rpc.GetMempoolEntryAsync(txid, throwIfNotFound, cancellationToken)).ConfigureAwait(false);
return await Rpc.GetMempoolEntryAsync(txid, throwIfNotFound, cancellationToken).ConfigureAwait(false);
}

public virtual async Task<MemPoolInfo> GetMempoolInfoAsync(CancellationToken cancel = default)
{
return await MeasureAsync(
nameof(GetMempoolInfoAsync),
async () =>
{
try
{
var response = await Rpc.SendCommandAsync(RPCOperations.getmempoolinfo, cancel, true)
.ConfigureAwait(false);
static IEnumerable<FeeRateGroup> ExtractFeeRateGroups(JToken jt) =>
jt switch
{
JObject jo => jo.Properties()
.Where(p => p.Name != "total_fees")
.Select(
p => new FeeRateGroup
{
Group = int.Parse(p.Name),
Sizes = p.Value.Value<ulong>("sizes"),
Count = p.Value.Value<uint>("count"),
Fees = Money.Satoshis(p.Value.Value<ulong>("fees")),
From = new FeeRate(p.Value.Value<decimal>("from_feerate")),
To = new FeeRate(Math.Min(50_000, p.Value.Value<decimal>("to_feerate")))
}),
_ => Enumerable.Empty<FeeRateGroup>()
};
return new MemPoolInfo()
{
Size = int.Parse((string) response.Result["size"]!, CultureInfo.InvariantCulture),
Bytes = int.Parse((string) response.Result["bytes"]!, CultureInfo.InvariantCulture),
Usage = int.Parse((string) response.Result["usage"]!, CultureInfo.InvariantCulture),
MaxMemPool =
double.Parse((string) response.Result["maxmempool"]!, CultureInfo.InvariantCulture),
MemPoolMinFee = double.Parse(
(string) response.Result["mempoolminfee"]!,
CultureInfo.InvariantCulture),
MinRelayTxFee = double.Parse(
(string) response.Result["minrelaytxfee"]!,
CultureInfo.InvariantCulture),
Histogram = ExtractFeeRateGroups(response.Result["fee_histogram"]!).ToArray()
};
}
catch (RPCException ex) when (ex.RPCCode == RPCErrorCode.RPC_MISC_ERROR)
try
{
var response = await Rpc.SendCommandAsync(RPCOperations.getmempoolinfo, cancel, true)
.ConfigureAwait(false);

static IEnumerable<FeeRateGroup> ExtractFeeRateGroups(JToken jt) =>
jt switch
{
cancel.ThrowIfCancellationRequested();
JObject jo => jo.Properties()
.Where(p => p.Name != "total_fees")
.Select(
p => new FeeRateGroup
{
Group = int.Parse(p.Name),
Sizes = p.Value.Value<ulong>("sizes"),
Count = p.Value.Value<uint>("count"),
Fees = Money.Satoshis(p.Value.Value<ulong>("fees")),
From = new FeeRate(p.Value.Value<decimal>("from_feerate")),
To = new FeeRate(Math.Min(50_000, p.Value.Value<decimal>("to_feerate")))
}),
_ => Enumerable.Empty<FeeRateGroup>()
};

return new MemPoolInfo()
{
Size = int.Parse((string) response.Result["size"]!, CultureInfo.InvariantCulture),
Bytes = int.Parse((string) response.Result["bytes"]!, CultureInfo.InvariantCulture),
Usage = int.Parse((string) response.Result["usage"]!, CultureInfo.InvariantCulture),
MaxMemPool =
double.Parse((string) response.Result["maxmempool"]!, CultureInfo.InvariantCulture),
MemPoolMinFee = double.Parse(
(string) response.Result["mempoolminfee"]!,
CultureInfo.InvariantCulture),
MinRelayTxFee = double.Parse(
(string) response.Result["minrelaytxfee"]!,
CultureInfo.InvariantCulture),
Histogram = ExtractFeeRateGroups(response.Result["fee_histogram"]!).ToArray()
};
}
catch (RPCException ex) when (ex.RPCCode == RPCErrorCode.RPC_MISC_ERROR)
{
cancel.ThrowIfCancellationRequested();

return await Rpc.GetMemPoolAsync(cancel).ConfigureAwait(false);
}
}).ConfigureAwait(false);
return await Rpc.GetMemPoolAsync(cancel).ConfigureAwait(false);
}
}

public virtual async Task<uint256[]> GetRawMempoolAsync(CancellationToken cancellationToken = default)
{
return await MeasureAsync(
nameof(GetRawMempoolAsync),
() => Rpc.GetRawMempoolAsync(cancellationToken)).ConfigureAwait(false);
return await Rpc.GetRawMempoolAsync(cancellationToken).ConfigureAwait(false);
}

public virtual async Task<GetTxOutResponse?> GetTxOutAsync(uint256 txid, int index, bool includeMempool = true, CancellationToken cancellationToken = default)
{
return await MeasureAsync(
nameof(GetTxOutAsync),
() => Rpc.GetTxOutAsync(txid, index, includeMempool, cancellationToken)).ConfigureAwait(false);
return await Rpc.GetTxOutAsync(txid, index, includeMempool, cancellationToken).ConfigureAwait(false);
}

public virtual async Task<MempoolAcceptResult> TestMempoolAcceptAsync(Transaction transaction, CancellationToken cancellationToken = default)
{
return await MeasureAsync(
nameof(TestMempoolAcceptAsync),
() => Rpc.TestMempoolAcceptAsync(transaction, cancellationToken)).ConfigureAwait(false);
return await Rpc.TestMempoolAcceptAsync(transaction, cancellationToken).ConfigureAwait(false);
}

public virtual async Task StopAsync(CancellationToken cancellationToken = default)
Expand All @@ -156,30 +130,22 @@ public virtual async Task StopAsync(CancellationToken cancellationToken = defaul

public virtual async Task<uint256[]> GenerateAsync(int blockCount, CancellationToken cancellationToken = default)
{
return await MeasureAsync(
nameof(GenerateAsync),
() => Rpc.GenerateAsync(blockCount, cancellationToken)).ConfigureAwait(false);
return await Rpc.GenerateAsync(blockCount, cancellationToken).ConfigureAwait(false);
}

public virtual async Task<TimeSpan> UptimeAsync(CancellationToken cancellationToken = default)
{
return await MeasureAsync(
nameof(UptimeAsync),
() => Rpc.UptimeAsync(cancellationToken)).ConfigureAwait(false);
return await Rpc.UptimeAsync(cancellationToken).ConfigureAwait(false);
}

public virtual async Task<uint256> SendRawTransactionAsync(Transaction transaction, CancellationToken cancellationToken = default)
{
return await MeasureAsync(
nameof(SendRawTransactionAsync),
() => Rpc.SendRawTransactionAsync(transaction, cancellationToken)).ConfigureAwait(false);
return await Rpc.SendRawTransactionAsync(transaction, cancellationToken).ConfigureAwait(false);
}

public virtual async Task<EstimateSmartFeeResponse> EstimateSmartFeeAsync(int confirmationTarget, EstimateSmartFeeMode estimateMode = EstimateSmartFeeMode.Conservative, CancellationToken cancellationToken = default)
{
return await MeasureAsync(
nameof(EstimateSmartFeeAsync),
() => Rpc.EstimateSmartFeeAsync(confirmationTarget, estimateMode, cancellationToken)).ConfigureAwait(false);
return await Rpc.EstimateSmartFeeAsync(confirmationTarget, estimateMode, cancellationToken).ConfigureAwait(false);
}

public virtual IRPCClient PrepareBatch()
Expand All @@ -189,17 +155,13 @@ public virtual IRPCClient PrepareBatch()

public virtual async Task<VerboseBlockInfo> GetVerboseBlockAsync(uint256 blockId, CancellationToken cancellationToken = default)
{
var resp = await MeasureAsync(
nameof(GetVerboseBlockAsync),
() => Rpc.SendCommandAsync(RPCOperations.getblock, cancellationToken, blockId, 3)).ConfigureAwait(false);
var resp = await Rpc.SendCommandAsync(RPCOperations.getblock, cancellationToken, blockId, 3).ConfigureAwait(false);
return RpcParser.ParseVerboseBlockResponse(resp.ResultString);
}

public async Task<uint256[]> GenerateToAddressAsync(int nBlocks, BitcoinAddress address, CancellationToken cancellationToken = default)
{
return await MeasureAsync(
nameof(GenerateToAddressAsync),
() => Rpc.GenerateToAddressAsync(nBlocks, address, cancellationToken)).ConfigureAwait(false);
return await Rpc.GenerateToAddressAsync(nBlocks, address, cancellationToken).ConfigureAwait(false);
}

#region For Testing Only
Expand Down Expand Up @@ -299,18 +261,4 @@ public Task<RPCClient> CreateWalletAsync(string walletNameOrPath, CreateWalletOp
}

#endregion For Testing Only

private async Task<T> MeasureAsync<T>(string methodName, Func<Task<T>> fnc)
{
var start = DateTimeOffset.UtcNow;
try
{
return await fnc().ConfigureAwait(false);
}
finally
{
RequestTimeStatista.Instance.Add(methodName, DateTimeOffset.UtcNow - start);
}
}

}
Loading

0 comments on commit eda718b

Please sign in to comment.