~ubuntu-branches/ubuntu/trusty/uwsgi/trusty

« back to all changes in this revision

Viewing changes to contrib/uwsgi-cache-monitor.py

  • Committer: Package Import Robot
  • Author(s): Janos Guljas
  • Date: 2012-02-13 03:43:28 UTC
  • mfrom: (1.1.3)
  • Revision ID: package-import@ubuntu.com-20120213034328-d02hz8m5pon6kaxf
Tags: 1.0.3+dfsg-1
* New upstream version.
* Adjust rack plugin LD_RUN_PATH patch.
* Adjust patch for uWSGI Control Center jQuery links in templates.
* Remove '-fno-strict-aliasing' CFLAG patch as it is implemented upstream.
* Remove fix indentation of uwsgidecorators_py patch as implemented upstream.
* Adjust init scripts to use top-bottom options order, as --inherit option
  is not working as in earlier versions. 
* Update debian/copyright file.
* Add LSB Description field to debian/uwsgi.init.d.
* Set Architecture to "all" for binary package uwsgi-extra because
  it contains no architecture dependent files.
* Change uwsgi description. (Closes: #640698)
* New binary packages:
  - uwsgi-plugin-carbon
  - uwsgi-plugin-graylog2
  - uwsgi-plugin-logsocket
  - uwsgi-plugin-probeconnect
  - uwsgi-plugin-probepg
  - uwsgi-plugin-rrdtool
  - uwsgi-plugin-rsyslog
  - uwsgi-plugin-signal
  - uwsgi-plugin-symcall
  - uwsgi-plugin-syslog
* python-uwsgidecorators:
  - fix binary-install rule to call dh_python2
  - remove debian/source.lintian-overrides
* uwsgi-plugin-jvm-openjdk-6:
  - fix FTBFS on armel and powerpc (Closes: #656280)
* uwsgi-plugin-python:
  - document issue "ImportError: No module named site" when using
    virtualenv with Python 2.6 in README.Debian (Closes: #654333)
* Adjust debian/watch uversionmangle option.
* Repack upstram source to remove minimized jQuery and jQuery UI JavaScript
  libraries:
  - add get-orig-source rule to debian/rules
  - append +dfsg to upstream version
  - update debian/watch with dversionmangle option

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
import mmap
 
2
import os
 
3
import struct
 
4
import array
 
5
import time
 
6
import sys
 
7
from optparse import OptionParser
 
8
 
 
9
class Cache:
 
10
 
 
11
    def __init__(self, filename, cache_slots, block_size=65536, sample_sleep=1):
 
12
 
 
13
        self.block_size = block_size
 
14
        self.cache_slots = cache_slots
 
15
 
 
16
        self.key_size = 2048
 
17
        self.item_size = 2 + 2 + 4 + 8 + 8 + 8 + 8 + 8 + self.key_size
 
18
        self.block_size_start = self.item_size * self.cache_slots
 
19
 
 
20
        fd = os.open(filename, os.O_RDONLY)
 
21
        self.cache_store = mmap.mmap(fd, 0, mmap.MAP_SHARED, mmap.PROT_READ)
 
22
 
 
23
        self.sample_sleep = sample_sleep
 
24
        self.samples = 0
 
25
        self.history = []
 
26
        self.cache_full = 0
 
27
        self.cache_empty = 0
 
28
        self.cache_items = 0
 
29
        self.block_sizes = 0
 
30
 
 
31
    def store_read_item_block(self, position):
 
32
        pos = self.cache_store.tell()
 
33
        # uwsgi cache stores cache entries first and then the blocks
 
34
        self.cache_store.seek(self.block_size_start + (position * self.block_size))
 
35
        buf = self.cache_store.read(self.block_size)
 
36
        self.cache_store.seek(pos)
 
37
        return buf
 
38
 
 
39
    def store_read_item(self, position):
 
40
        buf = self.cache_store.read(self.item_size)
 
41
        fields = struct.unpack_from('@HHIQQQQQ2048c', buf)
 
42
        key = array.array('c', fields[8:self.key_size+8]).tostring().rstrip('\x00')
 
43
 
 
44
        if [x for x in key if x!= '\x00']:
 
45
            buf = self.store_read_item_block(position)
 
46
            value = array.array('c', buf).tostring().rstrip('\x00')
 
47
        else:
 
48
            value = ''
 
49
        return (position, key, value, len(value))
 
50
 
 
51
    def read(self):
 
52
        data = [self.store_read_item(i) for i in range(self.cache_slots)]
 
53
        self.cache_store.seek(0)
 
54
        self.update_stats(data)
 
55
        if self.sample_sleep:
 
56
            time.sleep(self.sample_sleep)
 
57
        return data
 
58
 
 
59
    def update_stats(self, data):
 
60
        # data is a list of (position, key, value, len(value)) tuples
 
61
        items = len([1 for x in data if x[3] > 0])
 
62
        self.cache_items += items
 
63
        full, empty = items == self.cache_slots, items == 0
 
64
        if full:
 
65
            self.cache_full += 1
 
66
        if empty:
 
67
            self.cache_empty += 1
 
68
        self.samples += 1
 
69
        block_sizes = sum([x[3] for x in data])
 
70
        self.block_sizes += block_sizes
 
71
        self.history.append({'full': full, 'empty': empty, 'data': data, \
 
72
            'items': items, 'block_sizes': block_sizes})
 
73
 
 
74
    def dump(self):
 
75
        return {
 
76
            'samples': self.samples,
 
77
            'history': self.history,
 
78
            'cache_slots': self.cache_slots,
 
79
            'sample_sleep': self.sample_sleep, 
 
80
            'cache_empty': self.cache_empty,
 
81
            'cache_full': self.cache_full,
 
82
            'cache_items': self.cache_items,
 
83
            'block_sizes': self.block_sizes,
 
84
         }
 
85
 
 
86
    def show_dump(self):
 
87
        d = self.dump()
 
88
        print
 
89
        print "Recorded %d samples (%d second(s) sleep between samples)" % \
 
90
            (d['samples'], d['sample_sleep'])
 
91
        print "Cache empty %d times, full %d times, %.2f items on average" % \
 
92
            (d['cache_empty'], d['cache_full'], d['cache_items'] / d['samples'])
 
93
        print "Block size average size: %d bytes" % \
 
94
            (d['block_sizes'] / d['cache_items'] * 8)
 
95
        print "Data in cache average: %d bytes" % \
 
96
            (d['block_sizes'] / d['samples'] * 8)
 
97
 
 
98
def main(options):
 
99
    cache = Cache(options.cache_store, options.cache_slots, options.block_size,
 
100
        options.sleep_time)
 
101
    print "Recording..."
 
102
    while True:
 
103
        try:
 
104
            data = cache.read()
 
105
        except KeyboardInterrupt:
 
106
            cache.show_dump()
 
107
            sys.exit(0)
 
108
 
 
109
if __name__ == '__main__':
 
110
    parser = OptionParser()
 
111
    parser.add_option("-s", "--cache-slots", dest="cache_slots", type="int",
 
112
        help="Slots available in the cache, uwsgi cache option")
 
113
    parser.add_option("-c", "--cache-store", dest="cache_store", default="uwsgi.cache",
 
114
        help="The filename of the cache store, uwsgi cache-store option. Default: uwsgi.cache")
 
115
    parser.add_option("-b", "--block-size", dest="block_size", default=65536, type="int",
 
116
        help="The size of the cache block, uwsgi cache-blocksize option. Default: 65536")
 
117
    parser.add_option("-t", "--sleep-time", dest="sleep_time", default=1, type="int",
 
118
        help="The time to sleep between each sample. Default: 1")
 
119
 
 
120
    (options, args) = parser.parse_args()
 
121
    if not options.cache_slots:
 
122
        parser.error('Option -s / --cache-slots is mandatory')
 
123
    main(options)