My Geeky Page
by Guillaume Chazarain

How to prevent firefox from being slowed down by the Macromedia Flash plugin

Tip This bug has been fixed in the final version of Macromedia Flash 9 Player for Linux (9.0.31.0) so this page serves now only an historical purpose.

So you downloaded the Macromedia Flash 9 beta plugin for firefox and now firefox seems less reponsive, even more when the machine is heavily loaded. First step is to blame the Linux scheduler. In this case, it is responsible but not guilty.

Let’s strace firefox to see if the cause for the slowdown can be revealed. The slowdown is more perceptible when the machine is loaded, so we simulate some load during the tracing.

$ while true; do true; done&
[1] 3514
$ while true; do true; done&
[2] 3515
$ strace -ttt -p $(pidof firefox-bin)
...
1162676844.724704 sched_yield()         = 0
...

The strace output clearly shows that firefox periodically waits in the sched_yield syscall. Being closed source, we can’t find out the reason for using sched_yield. Anyway, as Flash/firefox is not executed with real time scheduling there is no reason for calling sched_yield(), better concurrency primitives exist.

The next step is to remove those sched_yield() calls from the Flash plugin in order to give back some interactivity to firefox. One approach could be to use the same LD_PRELOAD trick as in getenv.sh to overload the sched_yield() function with a no-op. This approach has two slight limitations:

  • you must remember to always launch firefox with the LD_PRELOAD environment variable set, by using a wrapper script for example,

  • it will remove all sched_yield() calls from firefox and all of its plugins. In my tests, only Flash called sched_yield() but let’s keep safe.

We will instead modify the Flash plugin binary to remove the calls to sched_yield(). Now, step back and realize you are going to make some random modifications to a binary I don’t have the source for. Still there, ok.

Let’s disassemble the thing and look for sched_yield() calls.

$ objdump -d libflashplayer.so > libflashplayer.so.orig.asm
$ grep sched_yield libflashplayer.so.orig.asm
00021160 <sched_yield@plt>:
   bd762:       e8 f9 39 f6 ff          call   21160 <sched_yield@plt>

The goal is now to remove the sched_yield() call, that is, the instructions e8 f9 39 f6 ff. sched_yield() returns 0 on success, so we just have to clear the eax register. Inspection of the disassembly shows that the return value from sched_yield() is not used, but let’s play safe. Clearing eax is 0x31 0xc0, we can now replace two bytes out of five. The remaining three bytes will be nop-ped (0x90), so we just have to replace e8 f9 39 f6 ff with 31 c0 90 90 90 in the binary:

$ sed -i 's/\xe8\xf9\x39\xf6\xff/\x31\xc0\x90\x90\x90/g' libflashplayer.so

Let’s check the result:

$ objdump -d libflashplayer.so > libflashplayer.so.modified.asm
$ diff -u libflashplayer.so.orig.asm libflashplayer.so.modified.asm
--- libflashplayer.so.orig.asm
++ libflashplayer.so.modified.asm
@@ -193472,7 +193472,10 @@
    bd754:      e8 3c 49 f6 ff          call   22095 <strcpy@plt+0xd5>
    bd759:      81 c3 cb e9 58 00       add    $0x58e9cb,%ebx
    bd75f:      83 ec 04                sub    $0x4,%esp
-   bd762:      e8 f9 39 f6 ff          call   21160 <sched_yield@plt>
+   bd762:      31 c0                   xor    %eax,%eax
+   bd764:      90                      nop
+   bd765:      90                      nop
+   bd766:      90                      nop
    bd767:      58                      pop    %eax
    bd768:      5b                      pop    %ebx
    bd769:      5d                      pop    %ebp

The call to sched_yield() has been replaced, so now we can test firefox and hope the slowdown has disappeared.

Please contact me for any suggestion, problem, feedback…

Valid XHTML 1.1! Valid CSS! and hopefully compliant with your expectations

S