jiebi/CodeConvo huggingface dataset:
Presuming the reference is ~50 MB, and the updated content is also ~50 MB, one would need a window size of ~50 MB to ensure access into the dictionary during the entire reconstruction process. But if the updated content is just a bit bigger, say ~51 MB, a ~50 MB window size would allow delta operation only during the first ~50 MB, the last ~1 MB would have to be compressed without dictionary. If follows that the size of the dictionary is irrelevant for the Window size. What matters is for how long one wants to access the dictionary while rebuilding the content. And as a general approximation, one wants this dictionary during the entire reconstruction process, so the window size is effectively the size of the content to rebuild. Zstandard has a "windowless" mode which states exactly that : the size of the "window" is the size of the content. For this to work, one has to set the size of the content at the beginning of the compression process . Setting the content size is either an automatic operation when data is provided entirely upfront (), or, when data is provided in small increments (), it must be stated explicitly at the beginning (). will automatically trigger the "windowless" mode when the declared content size is smaller than the set Window size (effectively reducing the memory requirement for the decoder side). I'm not sure if there is another way to trigger it. Note that the decoder will be informed of the Window Size requirement by reading the frame header, and may decide to not proceed if this value is deemed too large. For example, has a default 128 MB limit, and will refuse to decompress payload requiring more that that, unless explicitly authorized to employ more memory (). Just for reference, offers a "large delta compression" mode with the command . It has made us somewhat familiar with some of these issues. In situations where the amount of data to compress and compare is very large, we now prefer to both the dictionary content and the destination file. It has proven useful to reduce memory pressure.
Thanks. That makes things a bit more complicated for the case where we want to require a minimum window size that the server can trust that all clients advertising content-encoding will be able to decode.
For the dictionary case it might be cleanest to use the same 128MB limit for window sizes as the default zstd limit (knowing that the client won't allocate that much unless it actually gets a stream that uses it).
Hello. Shared dictionary is placed in the address space between backward reference window and static dictionary. In other words it does not interfere with normal compression window, but using it makes "static dictionary" references more expensive. We decided to order it that way, because shared dictionary works almost the same way as extra window. Sorry for the late response. Best regards, Eugene.
Extra note. As you can see brotli allows backward distances behind window. IIRC, regular (as opposed to large-window) brotli allows distances up to ~56MiB, i.e. larger shared dictionaries would not be useful (== referenced)
Thanks. For the dictionaries to be usable for a broad set of apps (including large wasm bundles), I'm considering spec'ing: Brotli: Regular 16MB window, allowing for delta-compression of resources up to ~50MB. ZStandard: 128MB window, allowing for delta compression of resources up to around that size, depending on where the duplicated bytes are in the updated resource. The main difference with regular content-encoding is on the ZStandard side where the window is 8MB. For platforms that are resource constrained and are not willing to support a 128MB window they would be limited to Brotli (and then decide how large of a dictionary they are willing to keep and use). Another option on the ZStandard side would be to allow for a maximum window that is a multiple of the dictionary size (i.e. 8MB or 2 * dictionary size whichever is larger with a 128MB max). That way the client can have an upper limit that it knows in advance before advertising as being available. That adds complexity to the encoding side though. We have already seen cases where people want to delta-compress resources > 50MB (wasm apps) where they had to use ZStandard instead of Brotli because of the Brotli limits so I don't think a small limit like 8MB for ZStandard would work with this use case.
That massive resources exist is not sufficient justification to build a system that will not be available to some users.
I would prefer a far smaller default. If only to encourage the use of smaller resources overall. Defining a separate codepoint for massive windows is possible, say . The scalable option also seems reasonable. Clients can then choose to offer dictionaries when they exceed available resources.
I'm ok using the same 8MB window ( I believe) that we use for for and note that the effectiveness of delta compression for responses > 8MB using may be limited. The scalable option concerns me that people are likely to get it wrong and it won't be obvious and the decompression will start to fail as the dictionary and resource size changes. NAME does that sound about right?
The alternative floated where 's window size is derived from the size of the dictionary is much more attractive to me. (That is, cap the window size log at , where the spec picks an somewhere in the range .) In such a scheme, where the window size is deterministically derived from the size of the dictionary--a resource the client must already have access to--the client is free to decline to advertise support for for dictionaries which would require the use of a window larger than the client is willing to support. I.e., in resource-constrained environments, Chrome could avoid having to allocate more than 8 MB windows for by not advertising support for on requests where the resolved available dictionary is larger than . Put another way, given that the client will have the tools to make these choices for themselves, I would rather give the client discretion here rather than just bake a flat restriction into the spec.
NAME would you be supportive of updating the zstd command-line tooling to add an option that would set the window to the larger of 8MB or the dictionary size (i.e. match the content-encoding behavior)? My main concern is that it is easy to document and get people to use a fixed command-line for a 8MB window but if it involves a more complicated algorithm then it is likely to break in subtle ways that they may not notice until the resources are bigger than the dictionary (and are bigger than 8MB).
NAME yeah, that would be pretty straightforward. Happy to add that.
If we end up that bundles the dictionary hash with the compressed stream we can make sure the tooling for that file format handles the window size stuff for zstandard automatically (my main concern is around unexpected breakage from different server and client window requirements that only trigger when resources grow). The language will be a bit complex but will probably have to look something like
If I may chime in for some tactical consideration : In an update scenario, it's common for a new resource to be slightly larger than the old one it replaces. The expectation is that we generally tend to add stuff over time. A formulation which caps the window size to the size of the dictionary would introduce problems for all these update cases, which are expected to be the majority of update scenarios. On the other hand, we don't want this increase in size to be completely uncapped, in order to keep control of memory size. And if the new resource is really much larger than the old one, the benefits of delta compression are dubious anyway. So the suggestion is to authorize a window size which is slightly larger than the external dictionary size. As to how much larger exactly, a suggestion here is by +25% (x1.25). I would expect a large majority of update scenarios to fit into this picture, with the new resource being slightly larger than the old one by a few %. For the less common cases where the new ressource is much larger than the old one, Zstandard could still employ the dictionary but only for the beginning of decompression. The compression process will have to select a window size which remains under the specified limit (x1.25 external dictionary size). As a technical insight, note that byte-accurate window size is only a thing when the window is the entire decompressed content. Otherwise, the window size is encoded in a condensed format, which can only represent increments by 1/8th of a power of 2. This is not a problem to determine this "largest window size under the specified limit", but due to limited accuracy, you can already guess what would be the problem is we were to keep the formulation "not more than the larger of 8 MB and the size of the dictionary". Imagine that the external dictionary size is bytes, and the new resource to delta-compress is , aka 1-byte larger than the dictionary.
With the initial formulation, since the window size is limited to the size of the dictionary, the compressor cannot use as a window size, because it's 1 byte larger than the limit. So, it will have to find the next best window size under the limit. Due to granularity limitations, this next best window size is 8 MB. So delta compression would proceed fine for the first 8 MB, but for the last 1 MB, data would have to be compressed without the benefit of the dictionary. With the newly proposed limitation to "x1.25 the dictionary size", delta compression would remain active in above scenario during the entire decompression process. And it would remain fully active if the new resource to decompress is 10 MB, 11 MB or 11.24 MB. But if the new resource is 11.25 MB or larger, then the compressor will automatically limit the window size to 11 MB (since it's the largest representable window size under the limit, which, in this particular instance, is ), achieving the wanted memory size control.
Since neither the server not the client may know what the resource size will be when compression starts (say, in a streaming HTML case), won't the 1/8th power of 2 granularity apply even for cases where the resource is the same size (or sometimes smaller) than the dictionary? For resources slightly larger than the old one, the dictionary would still be used for the majority of the resource but the last bit would fall back to regular window-based compression. I agree that having the dictionary available for the whole resource would provide better compression but I'm not sure where to draw the line. Something like a 25% fudge factor can be quite a bit when you start talking about 50 MB+ resources that might be close to where the client wants to draw the line anyway. They may have allowed the dictionary at 50 MB but not allow it's use at all if it needed 62 MB available for a window. A similar case could be made for the non-update case where you have a custom-built dictionary but the resource being compressed exceeds 8 MB. Only the first 8 MB of the resource would be able to use the dictionary.
Hopefully at that point the compression window would have most of the stuff that was in the dictionary but the dictionary becoming unavailable is something we should expect for some cases with ZStandard, even if we use a fudge factor. Is there a way to convey the 1/8th power of two granularity on the window size or is it something that the ZStandard libraries will take care of automatically for users (i.e. setting the window size to 11 MB when the caller sets it to 11.24 MB)? I'm wondering how much of this implementors are going to have to deal with directly.
It depends if the compression side (server) is informed upfront of the size of the payload to compress. If not, then indeed you are right, the compressor will have to set a Window Size, and the granularity rule applies. So for example, let's assume the payload to delta-compress is 50 MB, and the reference dictionary is also 50 MB. Let's then assume it implies a window size limit of 50 MB (dictionary size) and the compressor is not informed of the size of the payload. In which case, the compressor will have to set a Window Size, and it will have to settle for the largest representable window size under the limit, which happens to be 48 MB. Therefore, the dictionary won't be used during the compression of the last 2 MB of the payload. With the proposed +25% tolerance rule, the limit would become 62.5 MB, and the largest representable window size under the limit is 60 MB. Now the dictionary remains active during the entire compression of the 50 MB payload. When the data to decompress ends up being smaller than the window size, it's obviously not a problem for the decompression process: the final decompressed size is still properly reported at the end. It's just that the intermediate buffer allocation will be larger than it could have been. Note that uses for the allocation of buffers, so the address space is just reserved, but the physical memory may never be used if it's not needed (i.e. if there is no write action on the later segment part). +25% is more like a suggestion, this can certainly be discussed if some other limit feels better.
I liked that it's a (binary) clean factor, and it's larger than , which covers the scenario above, and gives a little bit of breathing room if the newer payload is a bit larger than the older reference one. I see this scenario as being very distinct from delta-compression. For delta-compression, we expect large segments to be identical between the reference and the payload to compress, so we want this ability to access the reference during the entire compression of the payload. The price to pay is that the reference is very specific, and is not designed to offer any serious benefit to any other payload. Custom dictionaries are different: they are supposed to carry the most relevant "commonalities" detected across a set of samples. Presuming a large enough sample set, the common components are not expected to be very large. In such a scenario, the custom dictionary is expected to be (relatively) lightweight (compared to delta-compression), likely in the <= 100 KB range. Consequently, by the time the payload to compress reaches 1 MB, it should already contain all references it needs to compress the rest of the file. I would not expect a large impact of the custom dictionary beyond that point, let alone beyond 8 MB. The plan would be for the library to do this adaptation automatically. The user would not have to know anything about it, though it's better if the user understands that the library selects the closest window size which is <= to the limit, so that they are not surprised if, upon inspection, the final window size is not byte-identical to the set limit. A good API documentation will likely help to reach this objective If by implementors you mean "server side programmers", they would have to know what's the implicit window size limit when a client requests a format (essentially the rule you are currently defining). Then they would set this limit as a compression parameter, and the library will take care of the adaptation into window size.
Yes. (Keeping in mind of course that most traffic in question will presumably be under the 8 MB floor and so none of this complexity will apply.) Right now the zstd library has limited controls about setting detailed window constraints. We'll need to add a new option to give users that fine-grained control. We can do that with an eye towards user simplicity.
Frankly, I'm also very open to also adding a flag (and equivalent compression parameter in the library) that would just look at the size of the dictionary (which zstd necessarily has access to) and would configure the window accordingly. In that case, users wouldn't have to do any math at all.
OK, I chaged the structure and language so that they are no longer streams of bytes compressed with a given algorithm but are now specifically and . The references for those named formats have the window restrictions (which for Zstandard includes the 1.25x dictionary requirement). Currently the byte stream itself is still a native Brotli/Zstandard stream, just with specific settings but this also makes it cleaner if we decide to . PR with the update is here: URL
lgtm other than the comment
A recent xml2rfc update changed the way that the element was rendered in text. Take advantage of that by adding quotes to strings that really do benefit from additional quoting, such as the "PRI ..." preface string. Most of the changes shown in a recent diff are down to losing quotes on header field names and other protocol elements. These do not need to be quoted for their meaning to be clear and unambiguous. The use of for these items improves the HTML rendering, but the loss of line noise in text renderings is a net win (at least in my opinion).
I agree with your reasoning, this seems like a good change.
This simplifies the text and makes flag consistent with CONTINUATION which only bears ENDHEADERS. Technically, both have the same meaning of ending sequence of header block fragments. Therefore there is no reason to use the different flag name for the same purpose. This will also make the implementaion easier because most likely HEADERS and PUSHPROMISE handling share the same code and dancing with ENDPUSHPROMISE and END_HEADERS is not fun. Although currently they have the same number, it is not guaranteed to the last. If they are guarenteed to be the same, then it is simpler to use the same name for same value.
Im ok with replacing the 0.9 reference (although having the link here acknowledges where 0.9 came from, right). The idea was to mention 0.9 in the context of RFC 1945 as well as that is an IETF document which actually describes what 0.9 is.
URL out that RFC 1945 defines HTTP/0.9 as well (see URL). Maybe we should add this reference, or replace the existing one.
We do reference 1945 for HTTP/1.0. Revised proposal: just mention that that RFC describes 0.9 as well.
This PR adds explanations helping readers to understand when empty requests for upload creation or appending might be useful and why server should support them. Closes URL
The field definitions allow for a client to send 0-length content. Sometimes this is useful, other times it it might not be. For example, A client could perform upload creation by making a request content-length: 0 and with upload-complete:?0. This would allow it to test creation wihout having to commit to an upload in the same message. A client could attempt to append to append zero bytes. Is this useful or should we prohibit it? This is a cheap way to keep an upload "active". However, that might be a vector for abuse by allowing a client to cause server-side state commintment. Depending on what we decide, we might need some text in the security considerations.
Just to add to the two bullet points: This can also be used for clients/servers that do not support 1xx response by sending a 0 byte upload-complete: ?0 request to get the unique resource URL. This is for instance how does it. For cases where multiple upload-complete: ?0 requests are made, a final 0 byte upload-complete: ?1 request can be used to notify the server that the upload is complete. This can be useful in cases where the client wants to provide all the data before finalizing the upload to reduce the risk of losing the final response. I don't really see a use case for sending multiple 0 byte upload-complete: ?0 but there might be some?
While testing firefox's implementation of this draft Vlad determined that some versions of Chrome throw PROTOCOL_ERROR and close the connection if it receives a type 0xB frame with a non zero length on stream 0. Other frame type numbers, such as 0xC do not seem to have that problem. testing indicates this is fixed in version 59 and is a problem previous to that. (57 is in release as I write this). presumably this is related to historical code around BLOCKED which was proposed to use 0xB. Prudence says to just use a different code point for the moment.
Question for NAME and NAME should we somehow reserve 0xb to avoid this problem?
If this is fixed in Chrome 59, why bother? Actually, I'd also revert this change.
Neither. There are still old Chrome versions deployed (some people lag, for various reasons), so it's not safe to use now, but it should be in the not-to-distant future; we just need to wait a while to use it (presumably for another extension). Reserving it for all time would be a bad precedent.
During the , NAME asked I answered (even though I'm not a MOQ chair), , but it's worth noting that this question has come up more than once during MOQ meetings, so it seems useful to add a short summary to the draft, in order to make sure we all have the same understanding. If I get this wrong, NAME and NAME can correct me, of course. :innocent:
Ta Hi, Lucas, I'm not a MOQ chair, but I can talk about history on one point. intentional, and (IIRC) derived from URL, which says, While writing down such things as requirements and use cases help to get a common understanding (and often common language) between participants in the working group, support documentation doesn’t always have a high archival value. Under most circumstances, the IESG encourages the community to consider alternate mechanisms for publishing this content, such as on a working group wiki, in an informational appendix of a solution document, or simply as an expired draft. My personal opinion is that we haven't spent enough time discussing use cases and requirements to have a good sense of the archival value of this documentation. If we did a good job on them, and kept them roughly up to date with solution drafts, the documentation may be worth publishing, but my understanding of the IESG statement is that no AD will ever ask the working group when these drafts will be submitted for publication as IETF-stream RFCs. And now, I'll let Alan and Ted give us the real answer. Best, Spencer >
Hi MoQ, I think this document is suitable candidate for adoption. It's not perfect and needs further development but that is sort of the point of adopting it. I note that the WG has a milestone of "WG adoption of Use Cases and Requirements document for Media Delivery over QUIC". If we dont adopt this document now, when and how would we axpext that milestone to be achieved? As a point of administration, I don't see a corresponding milestone for submission of a document to the IESG. Can I ask the chairs to clarify if the intention is to adopt and develop a draft but not seek taking it through to an RFC? Cheers Lucas This isn't as odd as it might sound. The MASQUE WG did something similar to help make progress on the protocol spec for IP tunnelling. So I would appreciate clarification here.
I think the alias draft should probably have a (non-normative) reference to , in particular noting that: can be populated from the output of . can be used to emulate or substitute for .
I think the flag to only gives you the "canonical name" which is the final CNAME target at the end of the CNAME chain. If you want the full set of interior names across a chain of multiple CNAME records I don't believe you can retrieve that with .
Yeah, I'm hesitant to add references to system APIs like , and particularly for the reason given above. NAME what do you think?
I think AI_CANONNAME is important historical context here. You can't understand where the draft is coming from without it. I also think that this extension will often be implemented by wrapping getaddrinfo, and some guidance about whether that is compliant would be appropriate. I think Robert's comment raises a good example of why this is not trivial, and hence is worth mentioning.
I'm not sure is really required to understand the context of the draft. We don't use it at all on iOS/macOS implementations for current CNAME cloaking detection. I do see that it may be good to warn that it is not sufficient to just wrap up .
Thanks LGTM