qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
To: Sanidhya Kashyap <sanidhya.iiith@gmail.com>
Cc: qemu list <qemu-devel@nongnu.org>, Juan Quintela <quintela@redhat.com>
Subject: Re: [Qemu-devel] [PATCH v5 6/6] BitmapLog: python script for extracting bitmap from a binary file
Date: Tue, 12 Aug 2014 15:04:25 +0100	[thread overview]
Message-ID: <20140812140425.GB3255@work-vm> (raw)
In-Reply-To: <20140812123623.GA3255@work-vm>

* Dr. David Alan Gilbert (dgilbert@redhat.com) wrote:
> * Sanidhya Kashyap (sanidhya.iiith@gmail.com) wrote:
> > The file not only extracts the bitmap from the file but also draws the figure
> > if required. Currently, figure is drawn for all the bitmaps. Later, I'll make
> > the change to draw for different blocks.
> > 
> > The picture is drawn by generating a matrix of 0s and 1s from the bitmap. The
> > dimensions are calculated on the basis of total bitmap pages which is represented
> > as sqrt(total pages) X (sqrt(total pages) + 1). The white parts indicate non dirtied
> > region while the black - dirtied region.
> > 
> > The python code requires some libraries such as numpy, pylab and math to generate
> > the images.
> 
> This is interesting; I've tried this out with a Fedora boot and recorded about 240
> frames; the script has problems when trying to convert that big a recording to images;
>   1) It loads it all into memory - so it used about 2GB of RAM
>   2) It opens each image as a window - so I then had to close about 240 windows
> 
> I fiddled with it a bit and created .png files, and then stiched these together
> with imagemagick to create an animation.  It's quite interesting watch the OS boot
> and then see me login and start google's stress apptest which suddenly changes
> the whole of memory.
> 
> I suggest making it dump each image to a file in a similar way and making it free the
> python image data after each frame, then there shouldn't be a size limit.
> (I did try and upload the image, but QEMU's wiki didn't like the size)

and here's the (scaled down for size) looping gif:
http://wiki.qemu-project.org/images/9/9a/Fedboot50.gif

Dave

> 
> Dave
> 
> 
> > 
> > Signed-off-by: Sanidhya Kashyap <sanidhya.iiith@gmail.com>
> > ---
> >  scripts/extract-bitmap.py | 144 ++++++++++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 144 insertions(+)
> >  create mode 100755 scripts/extract-bitmap.py
> > 
> > diff --git a/scripts/extract-bitmap.py b/scripts/extract-bitmap.py
> > new file mode 100755
> > index 0000000..942deca
> > --- /dev/null
> > +++ b/scripts/extract-bitmap.py
> > @@ -0,0 +1,144 @@
> > +#!/usr/bin/python
> > +# This python script helps in extracting the dirty bitmap present
> > +# in the file after executing the log-dirty-bitmap command either
> > +# from the qmp or hmp interface. This file only processes binary
> > +# file obtained via command.
> > +#
> > +# Copyright (C) 2014 Sanidhya Kashyap <sanidhya.iiith@gmail.com>
> > +#
> > +# Authors:
> > +#       Sanidhya Kashyap
> > +#
> > +#
> > +# This work is licensed under the terms of the GNU GPL, version 2 or later.
> > +
> > +import struct
> > +import argparse
> > +from functools import partial
> > +from math import sqrt
> > +from numpy import array
> > +from pylab import figure,imshow,show,gray
> > +
> > +long_bytes = 8
> > +byte_size = 8
> > +int_bytes = 4
> > +complete_bitmap_list = []
> > +block_list = []
> > +
> > +def get_unsigned_long_integer(value):
> > +	return struct.unpack('<Q', value)[0]
> > +
> > +def get_long_integer(value):
> > +	return struct.unpack('<q', value)[0]
> > +
> > +def get_integer(value):
> > +	return struct.unpack('<i', value)[0]
> > +
> > +def get_char(value):
> > +	return struct.unpack('<c', value)[0]
> > +
> > +def get_string(value, length):
> > +	name = struct.unpack('<'+str(length)+'s', value)[0]
> > +	for i in range(len(name)):
> > +		if name[i] == '\x00':
> > +			return name[:i]
> > +
> > +def dec2bin(decimal):
> > +    bin_value = bin(decimal)[2:]
> > +    if len(bin_value) < long_bytes * byte_size:
> > +        add_zeroes = long_bytes * byte_size - len(bin_value)
> > +        for i in range(add_zeroes):
> > +            bin_value += "0"
> > +    return str(bin_value)
> > +
> > +def get_bitmap_length(ram_bitmap_pages):
> > +    bitmap_length = ram_bitmap_pages / (long_bytes * byte_size)
> > +    if ram_bitmap_pages % (long_bytes * byte_size) != 0:
> > +        bitmap_length += 1
> > +    return bitmap_length
> > +
> > +def dump_ram_block_info(infile):
> > +    total_blocks = get_integer(infile.read(int_bytes))
> > +    for i in range(total_blocks):
> > +        block_name_length = get_integer(infile.read(int_bytes))
> > +        block_name = get_string(infile.read(block_name_length), block_name_length)
> > +        block_offset = get_unsigned_long_integer(infile.read(long_bytes))
> > +        block_length = get_unsigned_long_integer(infile.read(long_bytes))
> > +        block_list.append(dict(name=block_name, offset=block_offset, length=block_length))
> > +
> > +def generate_images():
> > +    r = 0
> > +    for list in complete_bitmap_list:
> > +        all_digits = ""
> > +        for element in list:
> > +            all_digits += dec2bin(element)
> > +        l = len(all_digits)
> > +        sqrtvalue = int(sqrt(l))
> > +        for i in range(sqrtvalue * (sqrtvalue+1)-l):
> > +            all_digits+="0"
> > +
> > +        v = []
> > +        l = len(all_digits)
> > +        for i in range(sqrtvalue+1):
> > +            v1 = []
> > +            for j in range(sqrtvalue):
> > +                v1.append(int(all_digits[i*sqrtvalue+j]))
> > +            v.append(v1)
> > +
> > +        im_array = array(v)
> > +        figure(r)
> > +        imshow(im_array, cmap=gray())
> > +        r += 1
> > +    show()
> > +
> > +def dump_bitmap(infile, draw):
> > +    marker = 'M'
> > +    count = 0
> > +    value = ' '
> > +    current_ram_bitmap_pages = 0
> > +    prev_ram_bitmap_pages = 0
> > +    while True:
> > +        if len(value) == 0  or marker != 'M':
> > +            print "issue with the dump"
> > +            return
> > +        bitmap_page_raw_value = infile.read(long_bytes)
> > +        if not bitmap_page_raw_value:
> > +            break
> > +        current_ram_bitmap_pages = get_long_integer(bitmap_page_raw_value)
> > +        if current_ram_bitmap_pages != prev_ram_bitmap_pages:
> > +            prev_ram_bitmap_pages = current_ram_bitmap_pages
> > +            dump_ram_block_info(infile)
> > +
> > +        bitmap_length = get_bitmap_length(current_ram_bitmap_pages)
> > +        bitmap_list = []
> > +        bitmap_raw_value = infile.read(long_bytes * bitmap_length)
> > +        if not bitmap_raw_value:
> > +            break
> > +        count+=1
> > +        for i in range(bitmap_length):
> > +            mark = i * long_bytes
> > +            bitmap_list.append((get_unsigned_long_integer(bitmap_raw_value[mark:mark+long_bytes])))
> > +        complete_bitmap_list.append(bitmap_list)
> > +        value = infile.read(1)
> > +        marker = get_char(value)
> > +    if draw is True:
> > +        generate_images()
> > +    else:
> > +        print complete_bitmap_list
> > +
> > +def main():
> > +    extracter = argparse.ArgumentParser(description='Extract dirty bitmap from binary file.')
> > +    extracter.add_argument('infile', help='Input file to extract the bitmap')
> > +    extracter.add_argument('-d', action='store_true', dest='draw', default=False,
> > +            help='Draw a black and white image of the processed dirty bitmap')
> > +    args = extracter.parse_args()
> > +    print 'The filename is {}'.format(args.infile)
> > +
> > +    infile = open(format(args.infile), 'rb')
> > +
> > +    dump_bitmap(infile, args.draw);
> > +
> > +    infile.close()
> > +
> > +if __name__ == '__main__':
> > +    main()
> > -- 
> > 1.9.3
> > 
> > 
> --
> Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK

      reply	other threads:[~2014-08-12 14:04 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-08-01  3:12 [Qemu-devel] [PATCH v5 0/6] Obtain dirty bitmap via VM logging Sanidhya Kashyap
2014-08-01  3:12 ` [Qemu-devel] [PATCH v5 1/6] generic function between migration and bitmap dump Sanidhya Kashyap
2014-08-12 10:37   ` Dr. David Alan Gilbert
2014-08-01  3:12 ` [Qemu-devel] [PATCH v5 2/6] BitmapLog: bitmap dump code Sanidhya Kashyap
2014-08-12 11:15   ` Dr. David Alan Gilbert
2014-08-12 13:12   ` Eric Blake
2014-08-01  3:12 ` [Qemu-devel] [PATCH v5 3/6] BitmapLog: get the information about the parameters Sanidhya Kashyap
2014-08-12 11:20   ` Dr. David Alan Gilbert
2014-08-12 13:53   ` Eric Blake
2014-08-01  3:12 ` [Qemu-devel] [PATCH v5 4/6] BitmapLog: cancel mechanism for an already running dump bitmap process Sanidhya Kashyap
2014-08-12 13:55   ` Eric Blake
2014-08-01  3:12 ` [Qemu-devel] [PATCH v5 5/6] BitmapLog: set the period of the " Sanidhya Kashyap
2014-08-12 13:57   ` Eric Blake
2014-08-01  3:12 ` [Qemu-devel] [PATCH v5 6/6] BitmapLog: python script for extracting bitmap from a binary file Sanidhya Kashyap
2014-08-12 12:36   ` Dr. David Alan Gilbert
2014-08-12 14:04     ` Dr. David Alan Gilbert [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20140812140425.GB3255@work-vm \
    --to=dgilbert@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=quintela@redhat.com \
    --cc=sanidhya.iiith@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).