diff --git a/CHANGELOG.md b/CHANGELOG.md
index 11f8ddfc3c3dd25f89fc1ac660a3b2857233a58b..8bb53a2e6e15dcd22a7f888a70be5717933756dc 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,3 +3,9 @@ on GitHub. This file serves to only note what changes
 have been made so far, between releases.
 
 # v1.2.14
+
+* added __slots__ to `AMQPContentPropertyList`
+    * without __slots__ in the base class the compiled classes
+      gained no boost from __slots__ being specified for them whatsoever
+* fixed __str__ in `AMQPContentPropertyList`
+* added __slots__ to `AMQPFrame`
diff --git a/coolamqp/__init__.py b/coolamqp/__init__.py
index 7c080820f1bca774595ebec342d80385cea69eac..9a285184b3c5c5970f8b6316b77ca184e20de799 100644
--- a/coolamqp/__init__.py
+++ b/coolamqp/__init__.py
@@ -1 +1 @@
-__version__ = '1.2.14a1'
+__version__ = '1.2.14rc1'
diff --git a/coolamqp/framing/base.py b/coolamqp/framing/base.py
index 6c4307ca50643ff461fd740528e8c17a82c94978..3cb4c953deafaa0ab02104c17474597437c92863 100644
--- a/coolamqp/framing/base.py
+++ b/coolamqp/framing/base.py
@@ -25,6 +25,7 @@ DYNAMIC_BASIC_TYPES = (u'table', u'longstr', u'shortstr')
 
 
 class AMQPFrame(object):  # base class for framing
+    __slots__ = ('channel', )
     FRAME_TYPE = None  # override me!
 
     def __init__(self, channel):  # type: (int) -> None
@@ -96,11 +97,15 @@ class AMQPContentPropertyList(object):
     If YOU create a property list, they will be bytes all right.
     """
     PROPERTIES = []
+    __slots__ = ()
 
     # todo they are immutable, so they could just serialize themselves...
 
     def __str__(self):  # type: () -> str
-        return '<AMQPContentPropertyList>'
+        values = {}
+        for field_name in self.__class__.__slots__():
+            values[field_name] = getattr(self, field_name)
+        return '<AMQPContentPropertyList (%s)>' % (values, )
 
     def get(self, property_name, default=None):
         # type: (str, str) -> tp.Union[memoryview, bytes]
diff --git a/coolamqp/framing/frames.py b/coolamqp/framing/frames.py
index f8f3590c409d76f9e5ee3aa5d51f8e7e9fcc526e..f44addee4c41fe9652bbc672519e0bb07cc6fe2e 100644
--- a/coolamqp/framing/frames.py
+++ b/coolamqp/framing/frames.py
@@ -23,6 +23,7 @@ STRUCT_BHLB = struct.Struct('!BHLB')
 
 class AMQPMethodFrame(AMQPFrame):
     FRAME_TYPE = FRAME_METHOD
+    __slots__ = ('payload', )
 
     def __init__(self, channel, payload):
         # type: (int, coolamqp.framing.base.AMQPMethodPayload) -> None
@@ -76,6 +77,7 @@ class AMQPHeaderFrame(AMQPFrame):
     :param body_size: size of the body to follow
     :param properties: a suitable AMQPContentPropertyList instance
     """
+    __slots__ = ('class_id', 'weight', 'body_size', 'properties')
     FRAME_TYPE = FRAME_HEADER
 
     def __init__(self, channel, class_id, weight, body_size, properties):
@@ -120,7 +122,7 @@ class AMQPBodyFrame(AMQPFrame):
     :param data: body (or a piece of it) of a message
     :type data: binary
     """
-
+    __slots__ = ('data', )
     FRAME_TYPE = FRAME_BODY
 
     FRAME_SIZE_WITHOUT_PAYLOAD = 8
@@ -151,6 +153,7 @@ class AMQPHeartbeatFrame(AMQPFrame):
     FRAME_TYPE = FRAME_HEARTBEAT
     LENGTH = 8
     DATA = STRUCT_BHLB.pack(FRAME_HEARTBEAT, 0, 0, FRAME_END)
+    __slots__ = ()
 
     def __init__(self):
         AMQPFrame.__init__(self, 0)
diff --git a/tests/test_objects.py b/tests/test_objects.py
index 908c83910796cad6e2683744c31f3cc147313e7c..b3335475bc52520c7e4d1eab503be159384f1271 100644
--- a/tests/test_objects.py
+++ b/tests/test_objects.py
@@ -7,6 +7,11 @@ from coolamqp.objects import NodeDefinition, MessageProperties
 
 
 class TestObjects(unittest.TestCase):
+    def test_message_properties(self):
+        empty_p_msg = MessageProperties()
+        ce_p_msg = MessageProperties(content_encoding=b'wtf')
+        self.assertIn('wtf', str(ce_p_msg))
+
     def test_node_definition_from_amqp(self):
         n1 = NodeDefinition(u'amqp://ala:ma@kota/psa')