diff --git a/CHANGES.rst b/CHANGES.rst
index c217aeb..5fcdb64 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -13,6 +13,10 @@
 
 - Test PyPy3 on Travis CI.
 
+- Stop requiring all values to support pickling in order to get
+  statistics. Instead, return ``False`` for the size if such a value
+  is found. Fixes `issue 1 <https://github.com/zopefoundation/zope.ramcache/issues/1>`_.
+
 2.1.0 (2014-12-29)
 ==================
 
diff --git a/src/zope/ramcache/interfaces/ram.py b/src/zope/ramcache/interfaces/ram.py
index 6e44313..f24ad35 100644
--- a/src/zope/ramcache/interfaces/ram.py
+++ b/src/zope/ramcache/interfaces/ram.py
@@ -34,9 +34,16 @@ class IRAMCache(ICache):
         """Reports on the contents of a cache.
 
         The returned value is a sequence of dictionaries with the
-        following keys:
-
-          `path`, `hits`, `misses`, `size`, `entries`
+        following (string) keys:
+
+          - ``path``: The object being cached.
+          - ``hits``: How many times this path (for all its keys)
+            has been looked up.
+          - ``misses``: How many misses there have been for this path
+            and all its keys.
+          - ``size``: An integer approximating the RAM usage for this path
+            (only available if all values can be pickled; otherwise ``False``)
+          - ``entries``: How many total keys there are for this path.
         """
 
     def update(maxEntries, maxAge, cleanupInterval):
diff --git a/src/zope/ramcache/ram.py b/src/zope/ramcache/ram.py
index fd07cf5..953fe50 100644
--- a/src/zope/ramcache/ram.py
+++ b/src/zope/ramcache/ram.py
@@ -19,6 +19,9 @@ from contextlib import contextmanager
 from time import time
 from threading import Lock
 
+from six import iteritems
+from six import itervalues
+
 from persistent import Persistent
 from zope.interface import implementer
 from zope.location.interfaces import IContained
@@ -254,12 +257,12 @@ class Storage(object):
 
             with self._invalidate_queued_after_writelock():
                 data = self._data
-                for object, dict in tuple(data.items()):
-                    for key in tuple(dict.keys()):
-                        if dict[key][1] < punchline:
-                            del dict[key]
-                            if not dict:
-                                del data[object]
+                for path, path_data in tuple(iteritems(data)): # copy, we modify
+                    for key, val in tuple(iteritems(path_data)): # likewise
+                        if val[1] < punchline:
+                            del path_data[key]
+                            if not path_data:
+                                del data[path]
 
     def cleanup(self):
         """Cleanup the data"""
@@ -270,7 +273,7 @@ class Storage(object):
     def removeLeastAccessed(self):
         with self._invalidate_queued_after_writelock():
             data = self._data
-            keys = [(ob, k) for ob, v in data.items() for k in v]
+            keys = [(ob, k) for ob, v in iteritems(data) for k in v]
 
             if len(keys) > self.maxEntries:
                 def getKey(item):
@@ -292,25 +295,31 @@ class Storage(object):
                 self._clearAccessCounters()
 
     def _clearAccessCounters(self):
-        for dict in self._data.values():
-            for val in dict.values():
+        for path_data in itervalues(self._data):
+            for val in itervalues(path_data):
                 val[2] = 0
-        for k in self._misses:
-            self._misses[k] = 0
+        self._misses = {}
 
     def getKeys(self, object):
         return self._data[object].keys()
 
     def getStatistics(self):
-        objects = sorted(self._data.keys())
+        objects = sorted(iteritems(self._data))
         result = []
 
-        for ob in objects:
-            size = len(dumps(self._data[ob]))
-            hits = sum(entry[2] for entry in self._data[ob].values())
-            result.append({'path': ob,
+        for path, path_data in objects:
+            try:
+                size = len(dumps(path_data))
+            except Exception:
+                # Some value couldn't be pickled properly.
+                # That's OK, they shouldn't have to be. Return
+                # a distinct value that can be recognized as such,
+                # but that also works in arithmetic.
+                size = False
+            hits = sum(entry[2] for entry in itervalues(path_data))
+            result.append({'path': path,
                            'hits': hits,
-                           'misses': self._misses.get(ob, 0),
+                           'misses': self._misses.get(path, 0),
                            'size': size,
-                           'entries': len(self._data[ob])})
+                           'entries': len(path_data)})
         return tuple(result)

Ram cache statistics crash
I've added a @ram.cache() decorator to a function returning a IITreeSet object.
Basically I need to cache some index search resultset in order to speedup the site.
Unfortunately when checking the ram cache statistcs, it fails with the message:

```python
Traceback (innermost last):
Module ZPublisher.Publish, line 138, in publish
Module ZPublisher.mapply, line 77, in mapply
Module ZPublisher.Publish, line 48, in call_object
Module plone.app.caching.browser.controlpanel, line 57, in call
Module plone.app.caching.browser.controlpanel, line 75, in render
Module Products.Five.browser.pagetemplatefile, line 125, in call
Module Products.Five.browser.pagetemplatefile, line 59, in call
Module zope.pagetemplate.pagetemplate, line 132, in pt_render
Module zope.pagetemplate.pagetemplate, line 240, in call
Module zope.tal.talinterpreter, line 271, in call
Module zope.tal.talinterpreter, line 343, in interpret
Module zope.tal.talinterpreter, line 888, in do_useMacro
Module zope.tal.talinterpreter, line 343, in interpret
Module zope.tal.talinterpreter, line 533, in do_optTag_tal
Module zope.tal.talinterpreter, line 518, in do_optTag
Module zope.tal.talinterpreter, line 513, in no_tag
Module zope.tal.talinterpreter, line 343, in interpret
Module zope.tal.talinterpreter, line 888, in do_useMacro
Module zope.tal.talinterpreter, line 343, in interpret
Module zope.tal.talinterpreter, line 533, in do_optTag_tal
Module zope.tal.talinterpreter, line 518, in do_optTag
Module zope.tal.talinterpreter, line 513, in no_tag
Module zope.tal.talinterpreter, line 343, in interpret
Module zope.tal.talinterpreter, line 946, in do_defineSlot
Module zope.tal.talinterpreter, line 343, in interpret
Module zope.tal.talinterpreter, line 533, in do_optTag_tal
Module zope.tal.talinterpreter, line 518, in do_optTag
Module zope.tal.talinterpreter, line 513, in no_tag
Module zope.tal.talinterpreter, line 343, in interpret
Module zope.tal.talinterpreter, line 954, in do_defineSlot
Module zope.tal.talinterpreter, line 343, in interpret
Module zope.tal.talinterpreter, line 533, in do_optTag_tal
Module zope.tal.talinterpreter, line 518, in do_optTag
Module zope.tal.talinterpreter, line 513, in no_tag
Module zope.tal.talinterpreter, line 343, in interpret
Module zope.tal.talinterpreter, line 946, in do_defineSlot
Module zope.tal.talinterpreter, line 343, in interpret
Module zope.tal.talinterpreter, line 583, in do_setLocal_tal
Module zope.tales.tales, line 696, in evaluate

URL: /home/dev/Plone-Dev/eggs/plone.app.caching-1.1.8-py2.7.egg/plone/app/caching/browser/ramcache.pt
Line 69, Column 16
Expression:
Names: {'args': (), 'container': , 'context': , 'default': , 'here': , 'loop': {}, 'nothing': None, 'options': {}, 'repeat': , 'request': , 'root': , 'template': , 'traverse_subpath': [], 'user': , 'view': , 'views': } 
Module zope.tales.expressions, line 217, in call 
Module Products.PageTemplates.Expressions, line 155, in _eval
Module Products.PageTemplates.Expressions, line 117, in render 
Module zope.ramcache.ram, line 80, in getStatistics 
Module zope.ramcache.ram, line 323, in getStatistics 
RuntimeError: maximum recursion depth exceeded while calling a Python object
```

diff --git a/src/zope/ramcache/tests/test_ramcache.py b/src/zope/ramcache/tests/test_ramcache.py
index ce6e9b1..1c6aa99 100644
--- a/src/zope/ramcache/tests/test_ramcache.py
+++ b/src/zope/ramcache/tests/test_ramcache.py
@@ -54,6 +54,23 @@ class TestRAMCache(CleanUp,
         r2 = c.getStatistics()
         self.assertEqual(r1, r2, "see Storage.getStatistics() tests")
 
+    def test_getStatistics_non_pickle(self):
+        # https://github.com/zopefoundation/zope.ramcache/issues/1
+        class NoPickle(object):
+            def __getstate__(self):
+                raise RuntimeError()
+
+        c = RAMCache()
+        c.set(NoPickle(), "path")
+        stats = c.getStatistics()
+        self.assertEqual(stats,
+                         ({'entries': 1,
+                           'hits': 0,
+                           'misses': 0,
+                           'path': 'path',
+                           'size': False},))
+        self.assertEqual(stats[0]['size'] + 1, 1)
+
     def test_update(self):
         c = RAMCache()
         c.update(1, 2, 3)
@@ -445,7 +462,7 @@ class TestStorage(unittest.TestCase):
                    object2: {key1: [value, 4, 0],
                              key2: [value, 5, 0],
                              key3: [value, 6, 0]}}
-        clearMisses = {object: 0, object2: 0}
+        clearMisses = {}
 
         s._clearAccessCounters()
         self.assertEqual(s._data, cleared, "access counters not cleared")

pip install -e .[test]
parse_log_pytest
pytest
pytest
3.6
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
attrs @ file:///opt/conda/conda-bld/attrs_1642510447205/work
certifi==2021.5.30
cffi==1.15.1
importlib-metadata @ file:///tmp/build/80754af9/importlib-metadata_1631916693255/work
iniconfig @ file:///home/linux1/recipes/ci/iniconfig_1610983019677/work
more-itertools @ file:///tmp/build/80754af9/more-itertools_1637733554872/work
packaging @ file:///tmp/build/80754af9/packaging_1637314298585/work
persistent==4.9.3
pluggy @ file:///tmp/build/80754af9/pluggy_1615976315926/work
py @ file:///opt/conda/conda-bld/py_1644396412707/work
pycparser==2.21
pyparsing @ file:///tmp/build/80754af9/pyparsing_1635766073266/work
pytest==6.2.4
six==1.17.0
toml @ file:///tmp/build/80754af9/toml_1616166611790/work
typing_extensions @ file:///opt/conda/conda-bld/typing_extensions_1647553014482/work
zipp @ file:///tmp/build/80754af9/zipp_1633618647012/work
zope.event==4.6
zope.exceptions==4.6
zope.interface==5.5.2
zope.location==4.3
zope.proxy==4.6.1
-e git+https://github.com/zopefoundation/zope.ramcache.git@c8a5cc3e393783668826355fe26b7b4ec299304d#egg=zope.ramcache
zope.schema==6.2.1
zope.testing==5.0.1
zope.testrunner==5.6

name: zope.ramcache
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - attrs=21.4.0=pyhd3eb1b0_0
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2021.5.30=py36h06a4308_0
  - importlib-metadata=4.8.1=py36h06a4308_0
  - importlib_metadata=4.8.1=hd3eb1b0_0
  - iniconfig=1.1.1=pyhd3eb1b0_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.3=he6710b0_2
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - more-itertools=8.12.0=pyhd3eb1b0_0
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - packaging=21.3=pyhd3eb1b0_0
  - pip=21.2.2=py36h06a4308_0
  - pluggy=0.13.1=py36h06a4308_0
  - py=1.11.0=pyhd3eb1b0_0
  - pyparsing=3.0.4=pyhd3eb1b0_0
  - pytest=6.2.4=py36h06a4308_2
  - python=3.6.13=h12debd9_1
  - readline=8.2=h5eee18b_0
  - setuptools=58.0.4=py36h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - toml=0.10.2=pyhd3eb1b0_0
  - typing_extensions=4.1.1=pyh06a4308_0
  - wheel=0.37.1=pyhd3eb1b0_0
  - xz=5.6.4=h5eee18b_1
  - zipp=3.6.0=pyhd3eb1b0_0
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - cffi==1.15.1
      - persistent==4.9.3
      - pycparser==2.21
      - six==1.17.0
      - zope-event==4.6
      - zope-exceptions==4.6
      - zope-interface==5.5.2
      - zope-location==4.3
      - zope-proxy==4.6.1
      - zope-schema==6.2.1
      - zope-testing==5.0.1
      - zope-testrunner==5.6
prefix: /opt/conda/envs/zope.ramcache

src/zope/ramcache/tests/test_ramcache.py::TestRAMCache::test_getStatistics_non_pickle src/zope/ramcache/tests/test_ramcache.py::TestStorage::test__clearAccessCounters
src/zope/ramcache/tests/test_ramcache.py::TestRAMCache::testCaching src/zope/ramcache/tests/test_ramcache.py::TestRAMCache::testInvalidateAll src/zope/ramcache/tests/test_ramcache.py::TestRAMCache::testVerifyICache src/zope/ramcache/tests/test_ramcache.py::TestRAMCache::test_buildKey src/zope/ramcache/tests/test_ramcache.py::TestRAMCache::test_cache src/zope/ramcache/tests/test_ramcache.py::TestRAMCache::test_getStatistics src/zope/ramcache/tests/test_ramcache.py::TestRAMCache::test_getStorage src/zope/ramcache/tests/test_ramcache.py::TestRAMCache::test_init src/zope/ramcache/tests/test_ramcache.py::TestRAMCache::test_interface src/zope/ramcache/tests/test_ramcache.py::TestRAMCache::test_invalidate src/zope/ramcache/tests/test_ramcache.py::TestRAMCache::test_query src/zope/ramcache/tests/test_ramcache.py::TestRAMCache::test_set src/zope/ramcache/tests/test_ramcache.py::TestRAMCache::test_timedCleanup src/zope/ramcache/tests/test_ramcache.py::TestRAMCache::test_update src/zope/ramcache/tests/test_ramcache.py::TestStorage::test_do_invalidate src/zope/ramcache/tests/test_ramcache.py::TestStorage::test_getEntry src/zope/ramcache/tests/test_ramcache.py::TestStorage::test_getEntry_do_cleanup src/zope/ramcache/tests/test_ramcache.py::TestStorage::test_getKeys src/zope/ramcache/tests/test_ramcache.py::TestStorage::test_getStatistics src/zope/ramcache/tests/test_ramcache.py::TestStorage::test_invalidate src/zope/ramcache/tests/test_ramcache.py::TestStorage::test_invalidateAll src/zope/ramcache/tests/test_ramcache.py::TestStorage::test_invalidate_queued src/zope/ramcache/tests/test_ramcache.py::TestStorage::test_invalidate_removes_empty src/zope/ramcache/tests/test_ramcache.py::TestStorage::test_locking src/zope/ramcache/tests/test_ramcache.py::TestStorage::test_removeLeastAccessed src/zope/ramcache/tests/test_ramcache.py::TestStorage::test_removeStale src/zope/ramcache/tests/test_ramcache.py::TestStorage::test_setEntry src/zope/ramcache/tests/test_ramcache.py::TestStorage::test_set_get src/zope/ramcache/tests/test_ramcache.py::TestModule::test_locking
src/zope/ramcache/interfaces/ram.py src/zope/ramcache/ram.py CHANGES.rst
src/zope/ramcache/interfaces/ram.py src/zope/ramcache/ram.py CHANGES.rst