Before answering, it's important to understand, on_message is the base of commands extension.
What it does is
commands = {} # example dictionary
@bot.command() # this registers the function in the command dictionary
async def test(ctx: commands.Context):
# some code here
# after this line is executed, your commands dictionary would look somethig like
# commands = {'test': test} (here, test is coroutine function you made)
on_message looks for a message.content, if it starts with the prefix, it gets the message without the prefix, then checks if the command called is in the dictionary, if yes, then call the command on that part with the arguments provided. If not, raise commands.CommandsNotFound
The above on_message I spoke about is the default on_message event bound to the bot. This is also a reason why commands extension doesn't work if one overrides the on_message event
Now with that out of the way, python dictionaries are implemented as hash tables. If the amount of if else staement is less then yes, they might be equally performative but in the longer run, dictionary lookup will prevail. Thus, I would say the commands extesnion is better to use.
In addition to the long run benefit, commands extension offers a much better way to manage your code.
if x == "test":
s = 1
y = 1
j = 1
print(s, y, z)
elif x == "test2":
s = 2
y = 2
j = 2
print(s, y, z)
elif x == "test3":
s = 3
y = 3
j = 3
print(s, y, z)
elif x == "test4":
s = 4
y = 4
j = 4
print(s, y, z)
elif x == "test5":
s = 5
y = 5
j = 5
print(s, y, z)
is certainly not appealing comapred to
def test1():
s = 1
y = 1
j = 1
print(s, y, z)
def test2():
s = 2
y = 2
j = 2
print(s, y, z)
def test3():
s = 3
y = 3
j = 3
print(s, y, z)
def test4():
s = 4
y = 4
j = 4
print(s, y, z)
def test5():
s = 5
y = 5
j = 5
print(s, y, z)
And it's also much easier to navigate and maintain your code with the command extension!
So, there is no reason for anyone to use if else in on_message to create commands when given a superior choice, i.e commands extesnion