Re: [PATCH 2/2] s390: qeth: Avoid unneeded command name lookup

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, 10 Sep 2018 15:05:05 +0200
Jean Delvare <jdelvare@xxxxxxx> wrote:

> Hi Martin,
> 
> Thanks for the quick reply.
> 
> On Mon, 2018-09-10 at 11:28 +0200, Martin Schwidefsky wrote:
> > On Mon, 10 Sep 2018 11:11:03 +0200
> > Jean Delvare <jdelvare@xxxxxxx> wrote:
> >   
> > > While it is generally a good practice to store the result of a lookup
> > > function in a local variable if you need it more than once, in this
> > > specific case it is not such a good idea because both uses are
> > > conditional (one depends on an error, the other on debugging). On top
> > > of that, they are mutually exclusive, so in the worst case the result
> > > of the lookup function will only be used once anyway.
> > > 
> > > So better call qeth_get_ipa_cmd_name() where it is needed, so that in
> > > the best (and most frequent) case it is never called at all. It
> > > should improve the qeth driver performance a little bit.
> > > 
> > > Signed-off-by: Jean Delvare <jdelvare@xxxxxxx>
> > > Cc: Julian Wiedmann <jwi@xxxxxxxxxxxxx>
> > > Cc: Ursula Braun <ubraun@xxxxxxxxxxxxx>
> > > Cc: Martin Schwidefsky <schwidefsky@xxxxxxxxxx>
> > > Cc: Heiko Carstens <heiko.carstens@xxxxxxxxxx>
> > > ---
> > > Note: build-tested only.
> > > 
> > >  drivers/s390/net/qeth_core_main.c |    9 +++++----
> > >  1 file changed, 5 insertions(+), 4 deletions(-)
> > > 
> > > --- linux-4.19-rc2.orig/drivers/s390/net/qeth_core_main.c	2018-09-08 15:19:47.225337133 +0200
> > > +++ linux-4.19-rc2/drivers/s390/net/qeth_core_main.c	2018-09-10 10:41:15.552350012 +0200
> > > @@ -609,18 +609,19 @@ static void qeth_put_reply(struct qeth_r
> > >  static void qeth_issue_ipa_msg(struct qeth_ipa_cmd *cmd, int rc,
> > >  		struct qeth_card *card)
> > >  {
> > > -	const char *ipa_name;
> > >  	int com = cmd->hdr.command;
> > > -	ipa_name = qeth_get_ipa_cmd_name(com);
> > > +
> > >  	if (rc)
> > >  		QETH_DBF_MESSAGE(2, "IPA: %s(x%X) for %s/%s returned "
> > >  				"x%X \"%s\"\n",
> > > -				ipa_name, com, dev_name(&card->gdev->dev),
> > > +				qeth_get_ipa_cmd_name(com), com,
> > > +				dev_name(&card->gdev->dev),
> > >  				QETH_CARD_IFNAME(card), rc,
> > >  				qeth_get_ipa_msg(rc));
> > >  	else
> > >  		QETH_DBF_MESSAGE(5, "IPA: %s(x%X) for %s/%s succeeded\n",
> > > -				ipa_name, com, dev_name(&card->gdev->dev),
> > > +				qeth_get_ipa_cmd_name(com), com,
> > > +				dev_name(&card->gdev->dev),
> > >  				QETH_CARD_IFNAME(card));
> > >  }
> > > 
> > >   
> > 
> > This does not make sense to me. "com" is read at the beginning of the function,
> > the ipa_name is dependent on com only, no?  
> 
> Correct, but I'm not sure where you are going with that. I do agree
> that qeth_get_ipa_cmd_name(com) will return the same thing in both
> branches, is that was your point. My proposal is not making any
> functional changes, it only aims at avoiding useless function calls.
> 
> > Moving the call to qeth_get_ipa_cmd_name
> > to the two statements of the if-then-else does not change a thing, in particular
> > if you have an intelligent compiler it will promptly undo the indented effect of
> > your patch..  
> 
> I can't see how it could or would even want to. I know that the
> compiler can reorder independent instructions for optimization
> purposes, but as far as I know it is not allowed to execute functions
> in anticipation "just in case" - the compiler has no idea what side
> effects calling a function can have. Plus, all the benefits of the
> optimization would potentially be lost or even negated by the cost of
> the function call.
> 
> If you look at the preprocessed code with my patch applied (reformatted
> because the output of gcc -E was barely readable), it looks like:
> 
> static void qeth_issue_ipa_msg(struct qeth_ipa_cmd *cmd, int rc,
> 				struct qeth_card *card)
> {
> 	int com = cmd->hdr.command;
> 
> 	if (rc) {
> 		debug_entry_t *__ret;
> 		debug_info_t *__id = qeth_dbf[QETH_DBF_MSG].id;
> 		int __level = 2;
> 
> 		if ((!__id) || (__level > __id->level))
> 			__ret = ((void *)0);
> 		else
> 			__ret = __debug_sprintf_event(__id, __level,
> 				"IPA: %s(x%X) for %s/%s returned x%X \"%s\"\n",
> 				qeth_get_ipa_cmd_name(com), com,
> 				dev_name(&card->gdev->dev),
> 				(((card)->dev)? (card)->dev->name : ""),
> 				rc, qeth_get_ipa_msg(rc));
> 	} else {
> 		debug_entry_t *__ret;
> 		debug_info_t *__id = qeth_dbf[QETH_DBF_MSG].id;
> 		int __level = 5;
> 
> 		if ((!__id) || (__level > __id->level))
> 			__ret = ((void *)0);
> 		else
> 			__ret = __debug_sprintf_event(__id, __level,
> 				"IPA: %s(x%X) for %s/%s succeeded\n",
> 				qeth_get_ipa_cmd_name(com), com,
> 				dev_name(&card->gdev->dev),
> 				(((card)->dev)? (card)->dev->name : ""));
> 	}
> }
> 
> As you can see, each call to qeth_get_ipa_cmd_name() is behind a
> conditional. Gcc simply can't call them if the branch in question is
> not taken. The preprocessed code also illustrates how the sprintfs (and
> thus the calls to qeth_get_ipa_cmd_name) are skipped in most cases,
> which is what makes my proposed optimization valuable.
> 
> The fact that gcc does not move or merge the calls
> to qeth_get_ipa_cmd_name() is further confirmed by inspecting the
> assembly output of gcc -S. With my patch applied, there are two calling
> sites for qeth_get_ipa_cmd_name() in qeth_issue_ipa_msg():
> 
> 18127          .type   qeth_issue_ipa_msg.isra.43, @function
> 18128  qeth_issue_ipa_msg.isra.43:
> 
> 18186          brasl   %r14,qeth_get_ipa_cmd_name@PLT
> 
> 18252          brasl   %r14,qeth_get_ipa_cmd_name@PLT
> 
> Are you convinced now?

Ah, ok. I missed the extra conditional in the expansion of
QETH_DBF_MESSAGE. So on the plus side we have faster execution
time for qeth_issue_ipa_msg, on the down side we now have two
function calls instead of one, +14 bytes in bloat-o-meter.

That function is rarely used, no? Then I am not sure if we are
making the right trade-off. I leave the decision to our network
maintainers..

-- 
blue skies,
   Martin.

"Reality continues to ruin my life." - Calvin.




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Kernel Development]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Info]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Linux Media]     [Device Mapper]

  Powered by Linux