BaseTools/GenFds: speed up Region.PadBuffer()

The current implementation calls both pack() and Buffer.write() Size
times. The new implementation calls both of these methods only once; the
full data to write are constructed locally [1]. The range() function is
replaced by xrange() because the latter is supposed to be faster / lighter
weight [2].

On my laptop, I tested the change as follows: I pre-built the series at
[3] with

  build -a X64 -p OvmfPkg/OvmfPkgX64.dsc -t GCC48 -b DEBUG \
      -D HTTP_BOOT_ENABLE -D SECURE_BOOT_ENABLE

(The series at [3] is relevant because it increases the size of one of the
padded regions by 8.5 MB, slowing down the build quite a bit.)

With all source code already compiled, repeating the above command takes
approximately 45 seconds. With the patch applied, it goes down to 29
seconds.

[1] http://stackoverflow.com/questions/27384093/fastest-way-to-write-huge-data-in-file
[2] https://docs.python.org/2/library/functions.html?highlight=xrange#xrange
[3] http://thread.gmane.org/gmane.comp.bios.edk2.devel/14214

We can also measure the impact with a synthetic test:

> import timeit
>
> test_old = """
> import struct, string, StringIO
> Size = (8 * 1024 + 512) * 1024
> Buffer = StringIO.StringIO()
> PadData = 0xFF
> for i in range(0, Size):
>     Buffer.write(struct.pack('B', PadData))
> """
>
> test_new = """
> import struct, string, StringIO
> Size = (8 * 1024 + 512) * 1024
> Buffer = StringIO.StringIO()
> PadByte = struct.pack('B', 0xFF)
> PadData = string.join(PadByte for i in xrange(0, Size))
> Buffer.write(PadData)
> """
>
> print(timeit.repeat(stmt=test_old, number=1, repeat=3))
> print(timeit.repeat(stmt=test_new, number=1, repeat=3))

The output is

[8.231637001037598, 8.81188416481018, 8.948754072189331]
[0.5503702163696289, 0.5461571216583252, 0.578315019607544]

Cc: Yonghong Zhu <yonghong.zhu@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Liming Gao <liming.gao@intel.com>
This commit is contained in:
Laszlo Ersek
2016-07-11 16:26:31 +02:00
parent 5588565f48
commit bd907fb638

View File

@ -18,6 +18,7 @@
from struct import * from struct import *
from GenFdsGlobalVariable import GenFdsGlobalVariable from GenFdsGlobalVariable import GenFdsGlobalVariable
import StringIO import StringIO
import string
from CommonDataClass.FdfClass import RegionClassObject from CommonDataClass.FdfClass import RegionClassObject
import Common.LongFilePathOs as os import Common.LongFilePathOs as os
from stat import * from stat import *
@ -52,11 +53,11 @@ class Region(RegionClassObject):
def PadBuffer(self, Buffer, ErasePolarity, Size): def PadBuffer(self, Buffer, ErasePolarity, Size):
if Size > 0: if Size > 0:
if (ErasePolarity == '1') : if (ErasePolarity == '1') :
PadData = 0xFF PadByte = pack('B', 0xFF)
else: else:
PadData = 0 PadByte = pack('B', 0)
for i in range(0, Size): PadData = string.join(PadByte for i in xrange(0, Size))
Buffer.write(pack('B', PadData)) Buffer.write(PadData)
## AddToBuffer() ## AddToBuffer()
# #