diff --git a/pyasn1/codec/ber/decoder.py b/pyasn1/codec/ber/decoder.py
index 13067380249e7885f5b64787c046d63aba78b0cc_cHlhc24xL2NvZGVjL2Jlci9kZWNvZGVyLnB5..381a9f0baf6e7a3c4dfb4235cbba9d3218d4be67_cHlhc24xL2NvZGVjL2Jlci9kZWNvZGVyLnB5 100644
--- a/pyasn1/codec/ber/decoder.py
+++ b/pyasn1/codec/ber/decoder.py
@@ -38,6 +38,9 @@
     Note that the implementation is tied to the decoder,
     not checking for dangerous arguments for the sake
     of performance.
+
+    The read bytes are kept in an internal cache until
+    setting _markedPosition which may reset the cache.
     """
     def __init__(self, raw):
         self._raw = raw
@@ -53,9 +56,10 @@
         return True
 
     def seek(self, n=-1, whence=os.SEEK_SET):
+        # Note that this not safe for seeking forward.
         return self._cache.seek(n, whence)
 
     def read(self, n=-1):
         read_from_cache = self._cache.read(n)
         if n != -1:
             n -= len(read_from_cache)
@@ -56,12 +60,15 @@
         return self._cache.seek(n, whence)
 
     def read(self, n=-1):
         read_from_cache = self._cache.read(n)
         if n != -1:
             n -= len(read_from_cache)
+            if n <= 0:
+                return read_from_cache
+
         read_from_raw = self._raw.read(n)
         self._cache.write(read_from_raw)
         return read_from_cache + read_from_raw
 
     @property
     def _markedPosition(self):
@@ -62,12 +69,16 @@
         read_from_raw = self._raw.read(n)
         self._cache.write(read_from_raw)
         return read_from_cache + read_from_raw
 
     @property
     def _markedPosition(self):
-        # This closely corresponds with how _marked_position attribute
-        # is manipulated with in Decoder.__call__ and (indefLen)ValueDecoder's
+        """Position where the currently processed element starts.
+
+        This is used for back-tracking in Decoder.__call__
+        and (indefLen)ValueDecoder and should not be used for other purposes.
+        The client is not supposed to ever seek before this position.
+        """
         return self._markedPosition_
 
     @_markedPosition.setter
     def _markedPosition(self, value):
@@ -70,5 +81,8 @@
         return self._markedPosition_
 
     @_markedPosition.setter
     def _markedPosition(self, value):
+        # By setting the value, we ensure we won't seek back before it.
+        # `value` should be the same as the current position
+        # We don't check for this for performance reasons.
         self._markedPosition_ = value
@@ -74,7 +88,6 @@
         self._markedPosition_ = value
-        self.seek(value)
 
         # Whenever we set _marked_position, we know for sure
         # that we will not return back, and thus it is
         # safe to drop all cached data.
         if self._cache.tell() > DEFAULT_BUFFER_SIZE:
@@ -76,13 +89,9 @@
 
         # Whenever we set _marked_position, we know for sure
         # that we will not return back, and thus it is
         # safe to drop all cached data.
         if self._cache.tell() > DEFAULT_BUFFER_SIZE:
-            current = self._cache.read()
-            self._cache.seek(0, os.SEEK_SET)
-            self._cache.truncate()
-            self._cache.write(current)
-            self._cache.seek(0, os.SEEK_SET)
+            self._cache = BytesIO(self._cache.read())
             self._markedPosition_ = 0
 
     def tell(self):