Large OFS.Image.File download trashes connectino cache
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
Zope 2 |
Invalid
|
Medium
|
Unassigned |
Bug Description
'OFS.Image.File' breaks up "large" files into a singly-linked list of 'Pdata'
chunks, each stored as its own Persistent object. This strategy keeps Zope
from loading the entire file into RAM when serviing it, which is a Good
Thing(TM).
However, it reads through those 'Pdata' objects from its connection one at a
time, and the connection *caches* them. This has two downsides:
- Once served out the the client, the 'Pdata' objects remains in the cache,
where they are not likely to be needed again (large file downloads are
much rarer than catalog queries, for instance).
- Worse, the 'Pdata' objects are "newer" than the objects already in the
cache, and thus *displace* them when the cache uses LRU to shrink back to
its target size. The application thus spends a lot of pain reloading its
old "working set".
I have a branch in Subversion[1] which modifies 'OFS.Image' as follows:
- It adds a class, 'FileIterator', which implements
'ZPublisher
'OFS.
- It changes 'OFS.Image.
where it would previously have used 'RESPOSNE.write' to "stream"
data to the client, it now manufactures a transient 'ZODB.Connection'
object, not tied to the main appserver thread's connection.
It then fetches the "clone" of the file object from that connection,
and returns a 'FileIterator' wrapped around the clone.
Under light testing, I can see that the number of reads apparent on the
'Control_
because the 'Pdata' objects read in the transient connection are not
affecting the long-lived connection objects.
Note that this patch does *not* deal with cache-thrasing at the level
of the disk-based ZEO Client Cache; it is purely relevant to the object
cache maintained in RAM.
[1] http://
Changed in zope2: | |
status: | New → Confirmed |
importance: | Undecided → Medium |
A Zope2 which has ZODB >= 3.8.0 could use the blob storage feature provided in
that version to implement OFS.Image.File, which would remove the need for my patch
altogether.