Merge lp:~aisrael/charms/trusty/mongodb/benchmarking into lp:charms/trusty/mongodb

Proposed by Adam Israel
Status: Merged
Merged at revision: 69
Proposed branch: lp:~aisrael/charms/trusty/mongodb/benchmarking
Merge into: lp:charms/trusty/mongodb
Diff against target: 249 lines (+217/-0)
4 files modified
README.md (+39/-0)
actions.yaml (+49/-0)
actions/perf (+127/-0)
metadata.yaml (+2/-0)
To merge this branch: bzr merge lp:~aisrael/charms/trusty/mongodb/benchmarking
Reviewer Review Type Date Requested Status
Tim Van Steenburgh (community) Approve
Review via email: mp+258558@code.launchpad.net

Description of the change

Add support for benchmarking mongodb with mongoperf, using juju actions.

To post a comment you must log in.
71. By Adam Israel

Remove stub for dex benchmark

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_lint_check #4469 mongodb for aisrael mp258558
    LINT OK: passed

Build: http://10.245.162.77:8080/job/charm_lint_check/4469/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_unit_test #4194 mongodb for aisrael mp258558
    UNIT OK: passed

Build: http://10.245.162.77:8080/job/charm_unit_test/4194/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_amulet_test #4092 mongodb for aisrael mp258558
    AMULET OK: passed

Build: http://10.245.162.77:8080/job/charm_amulet_test/4092/

Revision history for this message
Tim Van Steenburgh (tvansteenburgh) wrote :

+1 LGTM. Very nice, thanks Adam!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'README.md'
2--- README.md 2015-01-22 15:31:20 +0000
3+++ README.md 2015-05-07 20:42:54 +0000
4@@ -236,6 +236,45 @@
5
6 To fetch the backups scp the files down from the path in the config.
7
8+### Benchmarking
9+
10+Mongo units can be benchmarked via the `perf` juju action, available beginning with juju 1.23.
11+
12+ $ juju action defined mongodb
13+ perf: The standard mongoperf benchmark.
14+ $ juju action do mongodb/0 perf
15+ Action queued with id: 23532149-15c2-47f0-8d97-115fb7dfa1cd
16+ $ juju action fetch --wait 0 23532149-15c2-47f0-8d97-115fb7dfa1cd
17+ results:
18+ meta:
19+ composite:
20+ direction: desc
21+ units: ops/sec
22+ value: "7736507.70391"
23+ start: 2015-05-07T16:36:04Z
24+ stop: 2015-05-07T16:39:05Z
25+ results:
26+ average:
27+ units: ops/sec
28+ value: "7736507.70391"
29+ iterations:
30+ units: iterations
31+ value: "179"
32+ max:
33+ units: ops/sec
34+ value: "10282496"
35+ min:
36+ units: ops/sec
37+ value: "3874546"
38+ total:
39+ units: ops
40+ value: "1384834879"
41+ status: completed
42+ timing:
43+ completed: 2015-05-07 16:39:06 +0000 UTC
44+ enqueued: 2015-05-07 16:36:01 +0000 UTC
45+ started: 2015-05-07 16:36:04 +0000 UTC
46+
47 ## Known Limitations and Issues
48
49 - If your master/slave/replicaset deployment is not updating correctly, check the log files at `/var/log/mongodb/mongodb.log` to see if there is an obvious reason ( port not open etc.).
50
51=== added directory 'actions'
52=== added file 'actions.yaml'
53--- actions.yaml 1970-01-01 00:00:00 +0000
54+++ actions.yaml 2015-05-07 20:42:54 +0000
55@@ -0,0 +1,49 @@
56+perf:
57+ description: The standard mongoperf benchmark.
58+ params:
59+ runtime:
60+ description: The time, in seconds, to run mongoperf.
61+ type: integer
62+ default: 180
63+ nthreads:
64+ description: |
65+ Defines the number of threads mongoperf will use in the test. To saturate your system’s storage system you will need multiple threads. Consider setting nThreads to 16.
66+ type: integer
67+ default: 1
68+ fileSizeMB:
69+ description: Test file size, in megabytes.
70+ type: integer
71+ default: 1
72+ sleepMicros:
73+ description: |
74+ mongoperf will pause for the number of specified sleepMicros divided by the nThreads between each operation.
75+ type: integer
76+ default: 0
77+ mmf:
78+ description: |
79+ Set mmf to true to use memory mapped files for the tests.
80+ type: boolean
81+ default: False
82+ r:
83+ description: |
84+ Set r to true to perform reads as part of the tests.
85+ type: boolean
86+ default: False
87+ w:
88+ description: |
89+ Set w to true to perform writes as part of the tests.
90+ type: boolean
91+ default: False
92+ recSizeKB:
93+ description: The size of each write operation, in kilobytes.
94+ type: integer
95+ default: 4
96+ syncDelay:
97+ description: |
98+ Seconds between disk flushes. mongoperf.syncDelay is similar to --syncdelay for mongod.
99+
100+ The syncDelay controls how frequently mongoperf performs an asynchronous disk flush of the memory mapped file used for testing. By default, mongod performs this operation every 60 seconds. Use syncDelay to test basic system performance of this type of operation.
101+
102+ Only use syncDelay in conjunction with mmf set to true.
103+ type: integer
104+ default: 0
105
106=== added file 'actions/perf'
107--- actions/perf 1970-01-01 00:00:00 +0000
108+++ actions/perf 2015-05-07 20:42:54 +0000
109@@ -0,0 +1,127 @@
110+#!/usr/bin/env python
111+import signal
112+import subprocess
113+import os
114+import json
115+import re
116+from tempfile import NamedTemporaryFile
117+from distutils.spawn import find_executable
118+
119+try:
120+ from charmhelpers.contrib.benchmark import Benchmark
121+except ImportError:
122+ subprocess.check_call(['apt-get', 'install', '-y', 'python-pip'])
123+ subprocess.check_call(['pip', 'install', 'charmhelpers'])
124+ from charmhelpers.contrib.benchmark import Benchmark
125+
126+
127+def handler(signum, frame):
128+ raise IOError('Timeout')
129+
130+
131+def action_set(key, val):
132+ action_cmd = ['action-set']
133+ if isinstance(val, dict):
134+ for k, v in val.iteritems():
135+ action_set('%s.%s' % (key, k), v)
136+ return
137+
138+ action_cmd.append('%s=%s' % (key, val))
139+ subprocess.check_call(action_cmd)
140+
141+
142+def action_get(key):
143+ if find_executable('action-get'):
144+ return subprocess.check_output(['action-get', key]).strip()
145+ return None
146+
147+
148+def main():
149+
150+ Benchmark.start()
151+
152+ """
153+ mongoperf runs until interupted so we have to use a
154+ signal handler to stop it and gather the results
155+ """
156+ signal.signal(signal.SIGALRM, handler)
157+ runtime = int(action_get('runtime') or 180)
158+ signal.alarm(runtime)
159+
160+ js = {}
161+ js['nThreads'] = int(action_get('nthreads'))
162+ js['fileSizeMB'] = int(action_get('fileSizeMB'))
163+ js['sleepMicros'] = int(action_get('sleepMicros'))
164+ js['mmf'] = action_get('mmf')
165+ js['r'] = action_get('r')
166+ js['w'] = action_get('w')
167+ js['recSizeKB'] = int(action_get('recSizeKB'))
168+ js['syncDelay'] = int(action_get('syncDelay'))
169+
170+ config = NamedTemporaryFile(delete=False)
171+ config.write(json.dumps(js))
172+ config.close()
173+ config = open(config.name, 'r')
174+
175+ output = NamedTemporaryFile(delete=False)
176+
177+ p = None
178+ try:
179+ p = subprocess.Popen(
180+ 'mongoperf',
181+ stdin=config,
182+ stdout=output,
183+ )
184+ os.waitpid(p.pid, 0)
185+ except subprocess.CalledProcessError as e:
186+ rc = e.returncode
187+ print "Exit with error code %d" % rc
188+ except IOError as e:
189+ signal.alarm(0)
190+ os.kill(p.pid, signal.SIGKILL)
191+ finally:
192+ os.unlink(config.name)
193+
194+ output.close()
195+ output = open(output.name, 'r')
196+ scores = []
197+ regex = re.compile(r'(\d+)\sops\/sec')
198+ for line in output:
199+ m = regex.match(line)
200+ if m:
201+ scores.append(int(m.group(1)))
202+
203+ action_set(
204+ "results.total",
205+ {'value': sum(scores), 'units': 'ops'}
206+ )
207+
208+ action_set(
209+ "results.iterations",
210+ {'value': len(scores), 'units': 'iterations'}
211+ )
212+
213+ action_set(
214+ "results.average",
215+ {'value': sum(scores) / float(len(scores)), 'units': 'ops/sec'}
216+ )
217+ action_set(
218+ "results.max",
219+ {'value': max(scores), 'units': 'ops/sec'}
220+ )
221+ action_set(
222+ "results.min",
223+ {'value': min(scores), 'units': 'ops/sec'}
224+ )
225+
226+ Benchmark.set_composite_score(
227+ sum(scores) / float(len(scores)),
228+ 'ops/sec',
229+ 'desc'
230+ )
231+
232+ Benchmark.finish()
233+
234+
235+if __name__ == "__main__":
236+ main()
237
238=== modified file 'metadata.yaml'
239--- metadata.yaml 2014-10-30 06:00:52 +0000
240+++ metadata.yaml 2015-05-07 20:42:54 +0000
241@@ -37,6 +37,8 @@
242 interface: shard
243 mongos:
244 interface: mongodb
245+ benchmark:
246+ interface: benchmark
247 peers:
248 replica-set:
249 interface: mongodb-replica-set

Subscribers

People subscribed via source and target branches