- From: James M Snell <jasnell@gmail.com>
- Date: Fri, 18 Jan 2013 11:58:56 -0800
- To: "ietf-http-wg@w3.org" <ietf-http-wg@w3.org>
- Message-ID: <CABP7Rbep0CjJV5OTc9-toJLbEHwc7g=by-3JUTtuoBWYu=L+eA@mail.gmail.com>
Just one more for the day... Looking at Cache-Control.. Currently the
cache-control header consists of a list of named directives that optionally
have associated values. The format is extensible which is great, but makes
things a bit more difficult to optimize. Let's look at a few random
examples...
Cache-Control: public (6 bytes)
Cache-Control: public, max-age=1600 (21 bytes)
Cache-Control: no-store, no-transform, must-revalidate (39 bytes)
Let's see if we can do better.
First off, let's assume that Cache-Control on requests can have a different
encoding than Cache-Control on responses. For requests, let's make it:
+----------+----------+---------------------+
| no-cache | no-store | no-transform |
+----------+-----+----+---------+-----------+
| only-if-cached |xxxx| max-age | max-stale |
+-----------+----+----+---------+-----------+
| min-fresh | num-ext | repeating ext block |
+-----------+-----+---+---------+-----------+
no-cache = 1 bit
no-store = 1 bit
no-transform = 1 bit
only-of-cached = 1 bit
xxx = 4 reserved bits
max-age = uintvar
max-stale = uintvar
min-fresh = uintvar
num-ext = 1 byte
repeating ext block =
+---------------------------+
|TYP|XXXXXX|len(key)|key|val|
+---------------------------+
TYP = 2 bit type code
00 = Boolean, no val
01 = Numeric, val is uintvar
10 = Text, val is encoded text
11 = Reserved
XXXXXX = Reserved Bits
if TYP is 00, then val is omitted. The idea is that this is a boolean
flag, like no-cache, no-store, etc. The key identifies the flag. Key is a
text label.
if TYP is 01, then val is uintvar.
if TYP is 02, then val is 2-byte length followed by encoded text
So if we look at examples, then,
Cache-Control: no-cache encodes as five-bytes
Cache-Control: only-if-cached, max-age=1600, encodes as seven-bytes
Looking at the Cache-Control header for Responses we can do:
+--------+---------+----------+-------------+
| public | private | no-cache | no-transform|
+--------+-+-------+----------+-----------+-+
| no-store | must-revalidate |proxy-reval|X|
+----------+----------+-------+-----------+-+
| max-age | s-maxage | num-no-cache-headers|
+----------+-------+--+---------------------+
| no-cache-headers | num-private-headers |
+------------------+------------------------+
|private-headers|num-ext|repeating ext block|
+------------------+------------------------+
Same idea,
public = 1 bit
private = 1 bit
no-cache = 1 bit
no-transform = 1 bit
no-store = 1 bit
must-revalidate = 1 bit
proxy-reval = 1 bit
X = reserved
max-age = uintvar
s-maxage = uintvar
num-no-cache-headers = 1-byte
no-cache-headers = null-byte separated list of header names
num-private-headers = 1-byte
private-headers = null-byte separated list of header names
Examples...
Cache-Control: public (encodes as 6 bytes)
Cache-Control: public, max-age=1600 (encodes as 6 bytes, saving 17 bytes)
Cache-Control: no-store, no-transform, must-revalidate (encodes as 6
bytes, saving 33 bytes)
So looking at these examples, it is definitely possible to save a lot of
space but at the cost of quite a bit of encoding-complexity. I'm sure we
could possibly do better but this provides a good starting point, and, it's
bidirectionally compatible with 1.1. Whether or not it's worth the effort
is a different question entirely.
- James
Received on Friday, 18 January 2013 19:59:44 UTC