It is currently Thu Mar 28, 2024 5:37 pm

Mulle kybernetiK Optimization

Forum for Optimizations around Cocoa and Mac OS X

Use local variables to avoid redundant method calls

Optimizations concerning <i>Foundation</i> or <i>Objective-C</i> and its runtime
User avatar
 
Posts: 42
Joined: Fri Aug 06, 2004 9:20 am
Location: Bochum
Website: http://www.mulle-kybernetik.com/weblog

Use local variables to avoid redundant method calls

Post by Nat! » Tue Sep 07, 2004 10:17 pm

This is a pet peeve of mine. I often see code, where methods, most often accessors, are called repeatedly within the same method, although the result is invariant. I am not quite sure, if that is because of a bad functional programming habit :twisted:, a false hope that the compiler will optimize it away :roll: , or just laziness 8).

The truth is, the compiler can't optimize it away. This

Code: Select all

static unsigned int   foo( NSString *s)
{
   return( [s length] + [s length] + [s length]);
}



compiles to 100 bytes (and as long as nothing major changes in Objective-C this will always compile into three method calls)
_foo:
000043fc mfspr r0,lr
00004400 bcl 20,31,0x4404
00004404 stmw r27,0xffec(r1)
00004408 mfspr r31,lr
0000440c stw r0,0x8(r1)
00004410 or r27,r3,r3
00004414 addis r29,r31,0x0
00004418 stwu r1,0xffa0(r1)
0000441c addi r29,r29,0x1c08
00004420 lwz r4,0x0(r29)
00004424 bl 0x467c
00004428 lwz r4,0x0(r29)
0000442c or r28,r3,r3
00004430 or r3,r27,r27
00004434 bl 0x467c
00004438 lwz r4,0x0(r29)
0000443c add r28,r28,r3
00004440 or r3,r27,r27
00004444 bl 0x467c
00004448 lwz r0,0x68(r1)
0000444c addi r1,r1,0x60
00004450 add r3,r28,r3
00004454 lmw r27,0xffec(r1)
00004458 mtspr lr,r0
0000445c blr


but

Code: Select all

static unsigned int   bar( NSString *s)
{
   unsigned int   len;
   
   len = [s length];
   return( len + len + len);
}


compiles to only 64 bytes

_bar:
00004460 mfspr r0,lr
00004464 stw r31,0xfffc(r1)
00004468 bcl 20,31,0x446c
0000446c stw r0,0x8(r1)
00004470 mfspr r31,lr
00004474 stwu r1,0xffb0(r1)
00004478 addis r4,r31,0x0
0000447c lwz r4,0x1ba0(r4)
00004480 bl 0x467c
00004484 rlwinm r0,r3,1,0,30
00004488 add r3,r0,r3
0000448c lwz r0,0x58(r1)
00004490 addi r1,r1,0x50
00004494 lwz r31,0xfffc(r1)
00004498 mtspr lr,r0
0000449c blr


not only is bar (in my opinion) better style and more readable. It is also faster because the invariant result of the method call is cached and you saved two method calls. Now smaller code size makes for faster programs, because of better cache usage and smaller VM working sets. So you gain even more.

Using local variables as a habit can reduce code size appreciably.

 
Posts: 1
Joined: Thu Sep 09, 2004 2:05 pm
Location: Paris

Post by GrosJambon » Thu Sep 09, 2004 2:13 pm

Hum, I've seen worse in some Apple source code.

[...]

if (something==false)
{
// deallocate a lot of stuff

[...]

return false;
}

// deallocate the very same lot of stuff

[...]

return true;
}

 
Posts: 5
Joined: Tue Sep 07, 2004 4:50 am

Post by whitenoise » Thu Sep 09, 2004 5:03 pm

It's not a functional programming thing, it's because it's often faster and easier to write the code that way (usually via copy/paste), even though what you say is true: it's both more elegant (results in more readable code) and faster to execute using the cached variable value.

Thing is, I have a zillion things to do, I often have to get this particular code out immediately, and I can (and usually do) come back and clean up such code later when I have time. And usually the code isn't time-critical.

That's the rationale, at least for the experienced programmer who should otherwise know better. It's not a very good one, but it does save time to write code this way, especially if you're maintaining somebody else's lousy code with huge, bloated functions and you'd have to scroll the document to create the variable.

Novices may actually not realize the performance impact of multiple method or function calls. Even in C or C++ such code is more expensive than it needs to be.

The multiple deallocations thing I won't defend, because it's a major correctness issue. Multiple points of deallocation are doomed to get out of sync over time. There needs to be one point of deallocation.


Return to “Foundation & Objective-C”

Who is online

Users browsing this forum: No registered users and 1 guest