Revision e4d452b4

b/Makefile.am
587 587
	doc/examples/gnt-debug/README \
588 588
	doc/examples/gnt-debug/delay0.json \
589 589
	doc/examples/gnt-debug/delay50.json \
590
	test/lockperf.py \
590 591
	test/testutils.py \
591 592
	test/mocks.py \
592 593
	$(dist_TESTS) \
b/test/lockperf.py
1
#!/usr/bin/python
2
#
3

  
4
# Copyright (C) 2011 Google Inc.
5
#
6
# This program is free software; you can redistribute it and/or modify
7
# it under the terms of the GNU General Public License as published by
8
# the Free Software Foundation; either version 2 of the License, or
9
# (at your option) any later version.
10
#
11
# This program is distributed in the hope that it will be useful, but
12
# WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
# General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License
17
# along with this program; if not, write to the Free Software
18
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
# 02110-1301, USA.
20

  
21

  
22
"""Script for testing lock performance"""
23

  
24
import os
25
import sys
26
import time
27
import optparse
28
import threading
29
import resource
30

  
31
from ganeti import locking
32

  
33

  
34
def ParseOptions():
35
  """Parses the command line options.
36

  
37
  In case of command line errors, it will show the usage and exit the
38
  program.
39

  
40
  @return: the options in a tuple
41

  
42
  """
43
  parser = optparse.OptionParser()
44
  parser.add_option("-t", dest="thread_count", default=1, type="int",
45
                    help="Number of threads", metavar="NUM")
46
  parser.add_option("-d", dest="duration", default=5, type="float",
47
                    help="Duration", metavar="SECS")
48

  
49
  (opts, args) = parser.parse_args()
50

  
51
  if opts.thread_count < 1:
52
    parser.error("Number of threads must be at least 1")
53

  
54
  return (opts, args)
55

  
56

  
57
class State:
58
  def __init__(self, thread_count):
59
    """Initializes this class.
60

  
61
    """
62
    self.verify = [False for _ in range(thread_count)]
63
    self.counts = [0 for _ in range(thread_count)]
64
    self.total_count = 0
65

  
66

  
67
def _Counter(lock, state, me):
68
  """Thread function for acquiring locks.
69

  
70
  """
71
  counts = state.counts
72
  verify = state.verify
73

  
74
  while True:
75
    lock.acquire()
76
    try:
77
      verify[me] = 1
78

  
79
      counts[me] += 1
80

  
81
      state.total_count += 1
82

  
83
      if state.total_count % 1000 == 0:
84
        sys.stdout.write(" %8d\r" % state.total_count)
85
        sys.stdout.flush()
86

  
87
      if sum(verify) != 1:
88
        print "Inconsistent state!"
89
        os._exit(1) # pylint: disable=W0212
90

  
91
      verify[me] = 0
92
    finally:
93
      lock.release()
94

  
95

  
96
def main():
97
  (opts, _) = ParseOptions()
98

  
99
  lock = locking.SharedLock("TestLock")
100

  
101
  state = State(opts.thread_count)
102

  
103
  lock.acquire(shared=0)
104
  try:
105
    for i in range(opts.thread_count):
106
      t = threading.Thread(target=_Counter, args=(lock, state, i))
107
      t.setDaemon(True)
108
      t.start()
109

  
110
    start = time.clock()
111
  finally:
112
    lock.release()
113

  
114
  while True:
115
    if (time.clock() - start) > opts.duration:
116
      break
117
    time.sleep(0.1)
118

  
119
  # Make sure we get a consistent view
120
  lock.acquire(shared=0)
121

  
122
  lock_cputime = time.clock() - start
123

  
124
  res = resource.getrusage(resource.RUSAGE_SELF)
125

  
126
  print "Total number of acquisitions: %s" % state.total_count
127
  print "Per-thread acquisitions:"
128
  for (i, count) in enumerate(state.counts):
129
    print ("  Thread %s: %d (%0.1f%%)" %
130
           (i, count, (100.0 * count / state.total_count)))
131

  
132
  print "Benchmark CPU time: %0.3fs" % lock_cputime
133
  print ("Average time per lock acquisition: %0.5fms" %
134
         (1000.0 * lock_cputime / state.total_count))
135
  print "Process:"
136
  print "  User time: %0.3fs" % res.ru_utime
137
  print "  System time: %0.3fs" % res.ru_stime
138
  print "  Total time: %0.3fs" % (res.ru_utime + res.ru_stime)
139

  
140
  # Exit directly without attempting to clean up threads
141
  os._exit(0) # pylint: disable=W0212
142

  
143

  
144
if __name__ == "__main__":
145
  main()

Also available in: Unified diff