Skip to content

Commit f97b72f

Browse files
committed
fix crash in parsing module data types containing floats
* modules save binary float, and not the old string based floats. * fix crash in the memory profiler when handling rdb files with modules or streams * improve memory report to contains the total estimated memory, and used_mem aux field, etc.
1 parent cce3449 commit f97b72f

File tree

3 files changed

+40
-14
lines changed

3 files changed

+40
-14
lines changed

rdbtools/memprofiler.py

+12-4
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,11 @@ def __init__(self, key_groupings = None):
2525
self.aggregates = {}
2626
self.scatters = {}
2727
self.histograms = {}
28+
self.metadata = {}
2829

2930
def next_record(self, record):
3031
self.add_aggregate('database_memory', record.database, record.bytes)
32+
self.add_aggregate('database_memory', 'all', record.bytes)
3133
self.add_aggregate('type_memory', record.type, record.bytes)
3234
self.add_aggregate('encoding_memory', record.encoding, record.bytes)
3335

@@ -47,7 +49,7 @@ def next_record(self, record):
4749
self.add_scatter('sortedset_memory_by_length', record.bytes, record.size)
4850
elif record.type == 'string':
4951
self.add_scatter('string_memory_by_length', record.bytes, record.size)
50-
elif record.type == 'dict':
52+
elif record.type in ['dict', 'module', 'stream']:
5153
pass
5254
else:
5355
raise Exception('Invalid data type %s' % record.type)
@@ -74,9 +76,12 @@ def add_scatter(self, heading, x, y):
7476
if not heading in self.scatters:
7577
self.scatters[heading] = []
7678
self.scatters[heading].append([x, y])
79+
80+
def set_metadata(self, key, val):
81+
self.metadata[key] = val
7782

7883
def get_json(self):
79-
return json.dumps({"aggregates":self.aggregates, "scatters":self.scatters, "histograms":self.histograms})
84+
return json.dumps({"aggregates": self.aggregates, "scatters": self.scatters, "histograms": self.histograms, "metadata": self.metadata})
8085

8186
class PrintAllKeys(object):
8287
def __init__(self, out, bytes, largest):
@@ -159,7 +164,6 @@ def start_rdb(self):
159164
pass
160165

161166
def aux_field(self, key, value):
162-
#print('aux: %s %s' % (key, value))
163167
if key == 'used-mem':
164168
self._aux_used_mem = int(value)
165169
if key == 'redis-ver':
@@ -179,9 +183,13 @@ def end_database(self, db_number):
179183
self._stream.end_database(db_number)
180184

181185
def end_rdb(self):
182-
#print('internal fragmentation: %s' % self._total_internal_frag)
183186
if hasattr(self._stream, 'end_rdb'):
184187
self._stream.end_rdb()
188+
if hasattr(self._stream, 'set_metadata'):
189+
self._stream.set_metadata('used_mem', self._aux_used_mem)
190+
self._stream.set_metadata('redis_ver', self._aux_redis_ver)
191+
self._stream.set_metadata('redis_bits', self._aux_redis_bits)
192+
self._stream.set_metadata('internal_frag', self._total_internal_frag)
185193

186194
def set(self, key, value, expiry, info):
187195
self._current_encoding = info['encoding']

rdbtools/parser.py

+9-6
Original file line numberDiff line numberDiff line change
@@ -558,7 +558,7 @@ def read_object(self, f, enc_type) :
558558
self._callback.start_sorted_set(self._key, length, self._expiry, info={'encoding':'skiplist','idle':self._idle,'freq':self._freq})
559559
for count in range(0, length):
560560
val = self.read_string(f)
561-
score = read_double(f) if enc_type == REDIS_RDB_TYPE_ZSET_2 else self.read_float(f)
561+
score = read_binary_double(f) if enc_type == REDIS_RDB_TYPE_ZSET_2 else self.read_float(f)
562562
self._callback.zadd(self._key, score, val)
563563
self._callback.end_sorted_set(self._key)
564564
elif enc_type == REDIS_RDB_TYPE_HASH:
@@ -825,9 +825,9 @@ def skip_module(self, f):
825825
if opcode == REDIS_RDB_MODULE_OPCODE_SINT or opcode == REDIS_RDB_MODULE_OPCODE_UINT:
826826
self.read_length(f)
827827
elif opcode == REDIS_RDB_MODULE_OPCODE_FLOAT:
828-
self.skip_float(f)
828+
read_binary_float(f)
829829
elif opcode == REDIS_RDB_MODULE_OPCODE_DOUBLE:
830-
read_double(f)
830+
read_binary_double(f)
831831
elif opcode == REDIS_RDB_MODULE_OPCODE_STRING:
832832
self.skip_string(f)
833833
else:
@@ -851,9 +851,9 @@ def read_module(self, f):
851851
if opcode == REDIS_RDB_MODULE_OPCODE_SINT or opcode == REDIS_RDB_MODULE_OPCODE_UINT:
852852
data = self.read_length(iowrapper)
853853
elif opcode == REDIS_RDB_MODULE_OPCODE_FLOAT:
854-
data = self.read_float(iowrapper)
854+
data = read_binary_float(iowrapper)
855855
elif opcode == REDIS_RDB_MODULE_OPCODE_DOUBLE:
856-
data = read_double(iowrapper)
856+
data = read_binary_double(iowrapper)
857857
elif opcode == REDIS_RDB_MODULE_OPCODE_STRING:
858858
data = self.read_string(iowrapper)
859859
else:
@@ -1104,9 +1104,12 @@ def read_milliseconds_time(f) :
11041104
def read_unsigned_long_be(f) :
11051105
return struct.unpack('>Q', f.read(8))[0]
11061106

1107-
def read_double(f) :
1107+
def read_binary_double(f) :
11081108
return struct.unpack('d', f.read(8))[0]
11091109

1110+
def read_binary_float(f) :
1111+
return struct.unpack('f', f.read(4))[0]
1112+
11101113
def string_as_hexcode(string) :
11111114
for s in string :
11121115
if isinstance(s, int) :

rdbtools/templates/report.html.template

+19-4
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@
1515
google.setOnLoadCallback(draw_charts);
1616

1717
function draw_charts() {
18-
//draw_pie_chart('database_memory', chart_data.aggregates.database_memory, 'Database Number', 'Size in Bytes', 'Memory Usage by Database')
18+
document.getElementById('database_memory').innerHTML = chart_data.aggregates.database_memory['all']
19+
document.getElementById('aux_used_mem').innerHTML = chart_data.metadata.used_mem
20+
document.getElementById('aux_redis_ver_and_bits').innerHTML = chart_data.metadata.redis_ver + ' - ' + chart_data.metadata.redis_bits + 'bit'
21+
document.getElementById('internal_frag').innerHTML = chart_data.metadata.internal_frag
1922

2023
draw_pie_chart('type_memory', chart_data.aggregates.type_memory, 'Data Type', 'Total Size in Bytes', 'Memory Usage by Data Type')
2124
draw_column_chart('type_count', chart_data.aggregates.type_count, 'Data Type', 'Keys', 'Number of Keys by Data Type')
@@ -105,14 +108,26 @@
105108
<body>
106109
<h1>Redis Memory Distribution for dump.rdb</h1>
107110
<div class="container">
108-
<!--
111+
<h2>Total database computed memory:</h2>
109112
<div class="row">
110113
<div class="span6" id="database_memory">
111114
</div>
112-
<div class="span6" id="">
115+
</div>
116+
<h2>Total database memory from RDB aux field:</h2>
117+
<div class="row">
118+
<div class="span6" id="aux_used_mem">
119+
</div>
120+
</div>
121+
<h2>Database redis version and bits:</h2>
122+
<div class="row">
123+
<div class="span6" id="aux_redis_ver_and_bits">
124+
</div>
125+
</div>
126+
<h2>Total estimated internal fragmentation:</h2>
127+
<div class="row">
128+
<div class="span6" id="internal_frag">
113129
</div>
114130
</div>
115-
-->
116131
<h2>Memory Usage By Data Type and Data Encoding</h2>
117132
<div class="row">
118133
<div class="span6" id="type_memory">

0 commit comments

Comments
 (0)