View Issue Details

IDProjectCategoryView StatusLast Update
0011222Talerwallet-corepublic2026-03-10 12:10
Reporteravalos Assigned To 
PrioritynormalSeveritymajorReproducibilityhave not tried
Status newResolutionopen 
Summary0011222: adding taler-ops.ch exchange takes 4-6 seconds!
DescriptionThis is bad for onboarding new users!

Here are the performance stats in a fresh Android wallet, running wallet-core 1.3.13 (c0a35f4), where the only performed action was adding the exchange.taler-ops.ch exchange as part of the new "Withdraw CHF" button.

{
    "http-fetch": [
        {
            "url": "https://exchange.taler-ops.ch/keys",
            "maxDurationMs": 2497,
            "count": 1
        },
        {
            "url": "https://exchange.taler-ops.ch/terms",
            "maxDurationMs": 180,
            "count": 1
        }
    ],
    "db-query": [
        {
            "name": "<unknown>",
            "location": "updateExchangeFromUrlHandler",
            "maxDurationMs": 3442,
            "count": 1
        },
        {
            "name": "<unknown>",
            "location": "processValidateDenoms",
            "maxDurationMs": 163,
            "count": 4
        },
        {
            "name": "<unknown>",
            "location": "processValidateDenoms/callOperationHandlerForTaskId",
            "maxDurationMs": 104,
            "count": 6
        },
        {
            "name": "<unknown>",
            "location": "checkState/genericWaitForState",
            "maxDurationMs": 97,
            "count": 3
        },
        {
            "name": "<unknown>",
            "location": "processTaskExchangeAutoRefresh/callOperationHandlerForTaskId",
            "maxDurationMs": 93,
            "count": 2
        },
        {
            "name": "<unknown>",
            "location": "updateWithdrawalDenomsForExchange/doExchangeAutoRefresh",
            "maxDurationMs": 90,
            "count": 1
        },
        {
            "name": "<unknown>",
            "location": "updateExchangeFromUrlHandler/callOperationHandlerForTaskId",
            "maxDurationMs": 89,
            "count": 3
        },
        {
            "name": "<unknown>",
            "location": "listExchanges/dispatchRequestInternal",
            "maxDurationMs": 72,
            "count": 2
        },
        {
            "name": "<unknown>",
            "location": "getBalances/dispatchRequestInternal",
            "maxDurationMs": 71,
            "count": 2
        },
        {
            "name": "<unknown>",
            "location": "handleSetWalletRunConfig/dispatchRequestInternal",
            "maxDurationMs": 58,
            "count": 1
        }
    ],
    "crypto": [
        {
            "operation": "isValidDenom",
            "maxDurationMs": 26,
            "count": 344
        },
        {
            "operation": "isValidGlobalFees",
            "maxDurationMs": 1,
            "count": 1
        }
    ],
    "wallet-request": [
        {
            "operation": "addExchange",
            "maxDurationMs": 6507,
            "count": 1
        },
        {
            "operation": "initWallet",
            "maxDurationMs": 121,
            "count": 1
        },
        {
            "operation": "getWithdrawalDetailsForAmount",
            "maxDurationMs": 103,
            "count": 1
        },
        {
            "operation": "listExchanges",
            "maxDurationMs": 75,
            "count": 2
        },
        {
            "operation": "getBalances",
            "maxDurationMs": 73,
            "count": 2
        },
        {
            "operation": "getExchangeEntryByUrl",
            "maxDurationMs": 61,
            "count": 1
        },
        {
            "operation": "getCurrencySpecification",
            "maxDurationMs": 32,
            "count": 4
        },
        {
            "operation": "hintNetworkAvailability",
            "maxDurationMs": 21,
            "count": 2
        },
        {
            "operation": "testingGetPerformanceStats",
            "maxDurationMs": 2,
            "count": 2
        }
    ],
    "wallet-task": [
        {
            "taskId": "exchange-update:https%3A%2F%2Fexchange.taler-ops.ch%2F",
            "maxDurationMs": 6720,
            "count": 2
        },
        {
            "taskId": "validate-denoms:",
            "maxDurationMs": 459,
            "count": 5
        },
        {
            "taskId": "exchange-auto-refresh:https%3A%2F%2Fexchange.demo.taler.net%2F",
            "maxDurationMs": 93,
            "count": 1
        },
        {
            "taskId": "exchange-update:https%3A%2F%2Fexchange.demo.taler.net%2F",
            "maxDurationMs": 90,
            "count": 1
        },
        {
            "taskId": "exchange-auto-refresh:https%3A%2F%2Fexchange.taler-ops.ch%2F",
            "maxDurationMs": 14,
            "count": 1
        }
    ]
}
TagsNo tags attached.

Activities

Christian Grothoff

2026-03-10 10:57

manager   ~0028066

The HTTP fetch already takes a long time. I wonder if the client tries HTTP2/3 first and needs to fall back to HTTP1. We should enable HTTP2+3 on the server.

avalos

2026-03-10 11:09

developer   ~0028067

(I think I switched WiFi network, hence the x2 faster fetch time)

Enabling/disabling HTTP/2 in the client doesn't seem to make much difference:

HTTP/2 disabled:

{
    "url": "https://exchange.taler-ops.ch/keys",
    "maxDurationMs": 1010,
    "count": 1
}

HTTP/2 enabled:
 {
    "url": "https://exchange.taler-ops.ch/keys",
    "maxDurationMs": 1062,
    "count": 1
}

In both cases the addExchange request takes ~5 seconds.

avalos

2026-03-10 11:42

reporter   ~0028070

Also worth noting, isValidDenom was called 344 times.

Upper bound for the operation was 26ms, meaning: 344 * 26 = 8944ms.

MarcS

2026-03-10 12:03

reporter   ~0028071

Last edited: 2026-03-10 12:10

This is what I see on iOS (virgin wallet, I tapped on the "Withdraw CHF" button to open the withdraw-exchange talerURI):

[10] 12:07:07.871 � WalletCore.swift:157 WalletCore#1 handleResponse(_:_:) {"type":"response","operation":"testingGetPerformanceStats","id":11,"result":{"stats":{
"db-query":[
{"type":"db-query","name":"<unknown>","location":"updateExchangeFromUrlHandler","maxDurationMs":779,"count":1},
{"type":"db-query","name":"<unknown>","location":"processValidateDenoms","maxDurationMs":66,"count":1},
{"type":"db-query","name":"<unknown>","location":"startUpdateExchangeEntry","maxDurationMs":66,"count":3},
{"type":"db-query","name":"<unknown>","location":"checkState/genericWaitForState","maxDurationMs":30,"count":4},
{"type":"db-query","name":"<unknown>","location":"updateWithdrawalDenomsForExchange","maxDurationMs":24,"count":1},
{"type":"db-query","name":"<unknown>","location":"lookupExchangeByUri/dispatchRequestInternal","maxDurationMs":17,"count":4},
{"type":"db-query","name":"<unknown>","location":"updateWithdrawalDenomsForExchange/doExchangeAutoRefresh","maxDurationMs":11,"count":1},
{"type":"db-query","name":"<unknown>","location":"processValidateDenoms/callOperationHandlerForTaskId","maxDurationMs":9,"count":2},
{"type":"db-query","name":"<unknown>","location":"startUpdateExchangeEntry/fetchFreshExchange","maxDurationMs":8,"count":3},
{"type":"db-query","name":"<unknown>","location":"getBalances/dispatchRequestInternal","maxDurationMs":4,"count":1},
{"type":"db-query","name":"<unknown>","location":"doExchangeAutoRefresh","maxDurationMs":3,"count":1},
{"type":"db-query","name":"<unknown>","location":"handleGetCurrencySpecification/dispatchRequestInternal","maxDurationMs":2,"count":1},
{"type":"db-query","name":"<unknown>","location":"processTaskExchangeAutoRefresh/callOperationHandlerForTaskId","maxDurationMs":2,"count":1},
{"type":"db-query","name":"<unknown>","location":"fetchFreshExchange/handlePrepareWithdrawExchange","maxDurationMs":1,"count":1},
{"type":"db-query","name":"<unknown>","location":"updateExchangeFromUrlHandler/callOperationHandlerForTaskId","maxDurationMs":1,"count":2},
{"type":"db-query","name":"<unknown>","location":"getPreferredExchangeForCurrency/internalGetWithdrawalDetailsForAmount","maxDurationMs":1,"count":2},
{"type":"db-query","name":"<unknown>","location":"fetchFreshExchange/getExchangeWithdrawalInfo","maxDurationMs":0,"count":2},
{"type":"db-query","name":"<unknown>","location":"fetchAccount/fetchWithdrawalAccountInfo","maxDurationMs":0,"count":2}],
"wallet-task":[
{"type":"wallet-task","taskId":"exchange-update:https%3A%2F%2Fexchange.taler-ops.ch%2F","maxDurationMs":1557,"count":2},
{"type":"wallet-task","taskId":"validate-denoms:","maxDurationMs":105,"count":2},
{"type":"wallet-task","taskId":"exchange-auto-refresh:https%3A%2F%2Fexchange.taler-ops.ch%2F","maxDurationMs":2,"count":1}],
"wallet-request":[
{"type":"wallet-request","operation":"prepareWithdrawExchange","maxDurationMs":1524,"count":1},
{"type":"wallet-request","operation":"getWithdrawalDetailsForAmount","maxDurationMs":73,"count":2},
{"type":"wallet-request","operation":"getExchangeEntryByUrl","maxDurationMs":17,"count":4},
{"type":"wallet-request","operation":"getBalances","maxDurationMs":4,"count":1},
{"type":"wallet-request","operation":"getCurrencySpecification","maxDurationMs":2,"count":1},
{"type":"wallet-request","operation":"getDefaultExchanges","maxDurationMs":0,"count":1},
{"type":"wallet-request","operation":"testingGetPerformanceStats","maxDurationMs":0,"count":1}],
"http-fetch":[
{"type":"http-fetch","url":"https://exchange.taler-ops.ch/keys","maxDurationMs":636,"count":1},
{"type":"http-fetch","url":"https://exchange.taler-ops.ch/terms","maxDurationMs":42,"count":1}],
"crypto":[
{"type":"crypto","operation":"isValidDenom","maxDurationMs":3,"count":89},
{"type":"crypto","operation":"isValidGlobalFees","maxDurationMs":0,"count":1}]}}}

Issue History

Date Modified Username Field Change
2026-03-10 10:50 avalos New Issue
2026-03-10 10:57 Christian Grothoff Note Added: 0028066
2026-03-10 11:09 avalos Note Added: 0028067
2026-03-10 11:42 avalos Note Added: 0028070
2026-03-10 12:03 MarcS Note Added: 0028071
2026-03-10 12:10 MarcS Note Edited: 0028071