├── .github └── workflows │ └── auto-publish.yml ├── .gitignore ├── .pr_preview.json ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md ├── index.bs └── w3c.json /.github/workflows/auto-publish.yml: -------------------------------------------------------------------------------- 1 | name: Automatic Publication 2 | 3 | on: 4 | pull_request: {} 5 | push: 6 | branches: [main] 7 | 8 | jobs: 9 | validate-and-publish: 10 | name: Validate and Publish to TR 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v2 14 | - uses: w3c/spec-prod@v2 15 | with: 16 | TOOLCHAIN: bikeshed 17 | W3C_ECHIDNA_TOKEN: ${{ secrets.ECHIDNA_TOKEN }} 18 | W3C_WG_DECISION_URL: https://lists.w3.org/Archives/Public/public-web-perf/2021Apr/0005.html 19 | W3C_BUILD_OVERRIDE: | 20 | Status: WD 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | index.html 2 | 3 | -------------------------------------------------------------------------------- /.pr_preview.json: -------------------------------------------------------------------------------- 1 | { 2 | "src_file": "index.bs", 3 | "type": "bikeshed", 4 | "params": { 5 | "force": 1 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | All documentation, code and communication under this repository are covered by the [W3C Code of Ethics and Professional Conduct](https://www.w3.org/Consortium/cepc/). 4 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Contributions to this repository are intended to become part of Recommendation-track documents governed by the 2 | [W3C Patent Policy](https://www.w3.org/Consortium/Patent-Policy/) and 3 | [Software and Document License](https://www.w3.org/Consortium/Legal/copyright-software). To make substantive contributions to specifications, you must either participate 4 | in the relevant W3C Working Group or make a non-member patent licensing commitment. 5 | 6 | For our editing test-driven process, see [CONTRIBUTING.md](https://github.com/w3c/web-performance/blob/gh-pages/CONTRIBUTING.md). 7 | 8 | If you are not the sole contributor to a contribution (pull request), please identify all 9 | contributors in the pull request comment. 10 | 11 | To add a contributor (other than yourself, that's automatic), mark them one per line as follows: 12 | 13 | ``` 14 | +@github_username 15 | ``` 16 | 17 | If you added a contributor by mistake, you can remove them in a comment with: 18 | 19 | ``` 20 | -@github_username 21 | ``` 22 | 23 | If you are making a pull request on behalf of someone else but you had no part in designing the 24 | feature, you can remove yourself with the above syntax. 25 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | All documents in this Repository are licensed by contributors 2 | under the 3 | [W3C Software and Document License](http://www.w3.org/Consortium/Legal/copyright-software). 4 | 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Device Memory 2 | 3 | ## Motivation & Use cases 4 | A “one-size-fits-all” web experience does not work in a world with widely varying device capabilities. Web apps that delight users on high end devices can be unusable on low end devices, particularly in emerging markets. 5 | To support a diverse web ecosystem that is inclusive of users on low end devices, apps need to be able to tailor their content to the device constraints. This allows users to consume content suited to their device, and ensures they have a good experience and fewer frustrations. 6 | 7 | Developers are interested in the “device class” for the following known use-cases: 8 | 1. Serve a “lite” version of the site or specific components, for low end devices. Egs: 9 | - Google’s "search lite" is a 10KB search results page used in EM. 10 | - Serve a "lite" version of video player in Facebook 11 | - Serve lightweight tile images in Google Maps 12 | 2. Normalize Metrics: analytics need to be able to normalize their metrics against the device-class. 13 | For instance, a 100ms long task is a more severe issue on a Pixel vs. on a low end device. 14 | 15 | Device memory is an interesting signal in this context. Low memory devices devices (under 512MB, 512MB-1GB) are widely used in emerging markets. Chrome telemetry indicates a large number of OOM (out-of-memory) crashes on foreground tabs on these devices. In this case, serving a lite version not only improves the user experience, it is necessary for the site to be usable at all (as opposed to crashing due to memory constraints). 16 | 17 | ## Proposal 18 | We propose a new HTTP Client Hints header and a web exposed API to surface device capabilities for memory (RAM). The mechanism should be extensible to other device capabilities such as CPU i.e. number of cores, clock speed etc. 19 | A Client Hints header will enable the server to deliver appropriate content, eg. a “lite” version of the site. 20 | The JS API will be a convenience for analytics reporting and may be used to make runtime decisions eg. using more storage vs. making additional requests, requesting appropriate resources from the server etc. 21 | 22 | ASIDE: the JS API for CPU Cores is already available via hardwareConcurrency API 23 | 24 | ### The Header 25 | Proposed Client Hints Header for memory: `Device-Memory`\ 26 | `Device-Memory : `\ 27 | where `` is an approximation of the amount of RAM in GiB (floating point number).\ 28 | The `` is calculated by using the actual device memory in MiB then rounding it to the nearest number where only the most significant bit can be set and the rest are zeros (nearest power of two). Then dividing that number by 1024.0 to get the value in GiB. 29 | 30 | An upper bound and a lower bound should be set on the list of values. While implementations may choose different values, the recommended upper bound is 8GiB and the recommended lower bound is 0.25GiB (or 256MiB). 31 | The upper and lower bounds are not explicit, as they are subject to change over time. 32 | 33 | The following table illustrates some examples: 34 | 35 | | Actual in MiB | Rounded in MiB | Reported in GiB | 36 | |---------------|----------------|-----------------| 37 | | 500 | 512 | 0.5 | 38 | | 512 | 512 | 0.5 | 39 | | 768 | 512 | 0.5 | 40 | | 1000 | 1024 | 1 | 41 | | 1793 | 2048 | 2 | 42 | 43 | A full list of possible values is as follows: 44 | 0.25, 0.5, 1, 2, 4, 8 45 | 46 | #### Why separate header and rounding? 47 | HTTP caching doesn't deal well with mixed value headers, therefore separate headers are recommended. Also, rounding down to power of two enables caching and mitigates fingerprinting. 48 | 49 | #### When is the header sent? 50 | Client Hints cannot be used to enable providing network performance data on the first request, however this is being actively addressed with [this proposal](https://github.com/httpwg/http-extensions/issues/306#issuecomment-283549512). 51 | The header is sent after an explicit per-origin opt-in via Client Hints mechanism. The following new hint will be added: `Accept-CH: Device-Memory` 52 | 53 | For background, [Client Hints](http://httpwg.org/http-extensions/client-hints.html) provides a set of HTTP request header fields, known as Client Hints, to deliver content that is optimized for the device. In that sense using Client Hints is a great fit for this proposal. 54 | Client Hints recently addressed a [significant limitation in spec](https://github.com/httpwg/http-extensions/issues/306#issuecomment-283549512): opt-in can now be persisted across browser restarts using `max-age` in header. 55 | 56 | #### Usage Guidance 57 | Servers can advertise support for Client Hints using the Accept-CH header field or an equivalent HTML meta element with http-equiv attribute 58 | ``` 59 | Accept-CH = Device-Memory 60 | ``` 61 | 62 | The Memory request header field is a number for the client’s device memory i.e. approximate amount of ram in GiB. 63 | eg. 512 MiB will be reported as: 64 | ``` 65 | Device-Memory: 0.5 66 | ``` 67 | 68 | Servers can use this header to customize content for low memory device eg. serve light version of the app or a component such as a video player. 69 | 70 | NOTE: This header will not be immediately available in all browser. Do not assume presence of the header, and provide a graceful fallback for browsers that don't support the header. 71 | 72 | ### The web exposed API 73 | We propose adding the following API to navigator: `navigator.deviceMemory` 74 | which returns number of GiB of ram (floating point number) rounded down to the nearest power of two (same as the header). 75 | 76 | ## Why not surface Device Class directly? 77 | While exposing a composite “Device Class” would be useful for developers, it has a number of challenges: it’s hard to specify in a future-proof manner as it is constantly changing, it requires significant and ongoing work (constantly update algorithm OR classify known devices), it is difficult to reach agreement amongst vendors, and come up with something that works for all web sites etc. 78 | While this is something worth considering down the road, we think we can get most of the benefit by exposing a couple of specific signals device memory and device CPU cores. In particular device memory is a reasonable proxy for device class. 79 | 80 | ## Security & Privacy 81 | The client hint header and API will only be available on HTTPS secure connections. 82 | 83 | See [Security section in Client Hints](http://httpwg.org/http-extensions/client-hints.html#security-considerations). 84 | Requiring per-origin opt-in with Accept-CH restricts when the header is advertised. 85 | To reduce fingerprinting risk, reported value is rounded to single most significant bit, as opposed to reporting the exact value. In addition, an upper and lower bound is placed on the reported values. 86 | 87 | NOTE: Device identification is already possible and rampant today, based on UA string. E.g. https://deviceatlas.com/products/web 88 | 89 | ## Relevant Links 90 | 91 | * [Facebook's device year class](https://github.com/facebook/device-year-class) 92 | * [HTTP Client Hints](https://github.com/igrigorik/http-client-hints) 93 | * [HTTP Client Hints User Guide](https://developers.google.com/web/updates/2015/09/automating-resource-selection-with-client-hints) 94 | * [Similar proposal for Network Speed](https://github.com/WICG/netinfo/issues/46) 95 | * [NavigatorConcurrentHardware API](https://developer.mozilla.org/en-US/docs/Web/API/NavigatorConcurrentHardware) 96 | 97 | 98 | -------------------------------------------------------------------------------- /index.bs: -------------------------------------------------------------------------------- 1 | 15 | 16 |
 17 | {
 18 |   "CLIENT-HINTS": {
 19 |     "authors": [
 20 |         "Ilya Grigorik",
 21 |         "Yoav Weiss"
 22 |       ],
 23 |     "href": "https://httpwg.org/http-extensions/client-hints.html",
 24 |     "publisher": "IETF HTTP-WG",
 25 |     "title": "Client Hints",
 26 |     "status": "ID"
 27 |   },
 28 |   "I-D.ietf-httpbis-header-structure": {
 29 |     "authors": [ "Mark Nottingham", "Poul-Henning Kamp" ],
 30 |     "href": "https://httpwg.org/http-extensions/draft-ietf-httpbis-header-structure.html",
 31 |     "title": "Structured Field Values for HTTP",
 32 | 
 33 |     "status": "ID",
 34 |     "publisher": "IETF HTTP-WG"
 35 |   }
 36 | }
 37 | 
38 |
 39 | urlPrefix: https://httpwg.org/http-extensions/draft-ietf-httpbis-header-structure.html; spec: I-D.ietf-httpbis-header-structure
 40 |     type: dfn
 41 |         text: structured header value; url: #
 42 |     for: structured header value
 43 |         type: dfn
 44 |             text: decimal; url: #name-decimals
 45 |             text: item; url: #name-items
 46 | 
47 | 48 | Introduction {#intro} 49 | ===================== 50 | Developers need device-class signal for: 51 | 1. Serving light version of the site or specific components, for low-end devices. Egs: 52 | * Serve Google "search lite" - a 10KB search results page used in EM. 53 | * Serve a light version of video player in Facebook. 54 | * Serve lightweight tile images in Google Maps. 55 | 56 | 2. Normalizing Metrics: analytics need to be able to normalize their metrics against the device-class. For instance, a 100ms long task on a high end device is a more severe issue compared to a low-end device. 57 | 58 | Device memory is an especially useful signal for determining “device-class”. Low memory devices devices (under 512MB, 512MB - 1GB) are widely used in emerging markets. 59 | 60 | Usage Example {#example} 61 | ------------------------ 62 | A server opts-in to receive a `Device-Memory` client hint [[!CLIENT-HINTS]] using the `Accept-CH` header field, or an equivalent HTML meta element with http-equiv attribute: 63 |
 64 |     Accept-CH: Device-Memory
 65 | 
66 | 67 | In turn, on receiving the above preferences from the server, a compatible user agent would then advertise the device capability for memory, via the `Device-Memory` request header field: 68 |
 69 |     GET /example HTTP/1.1
 70 |     Device-Memory: 0.5
 71 |     ...
 72 | 
73 | 74 | Device Memory (Client Hint) Header Field {#sec-device-memory-client-hint-header} 75 | ======================================= 76 | 77 | The Device Memory header field is a [[CLIENT-HINTS]] header. 78 | It is a [=structured header value=] containing an [=item=] which value is a [=decimal=] that indicates the client’s device memory, i.e. the approximate amount of RAM in GiB. 79 | The ABNF (Augmented Backus-Naur Form) syntax for the `Device-Memory` header field is as follows: 80 | 81 | ~~~ abnf 82 | Device-Memory = sf-decimal 83 | ~~~ 84 | 85 |

Computing Device Memory Value

86 | The value is calculated by using the actual device memory in MiB then rounding it to the nearest number where only the most signicant bit can be set and the rest are zeros (nearest power of two). Then dividing that number by 1024.0 to get the value in GiB. 87 | 88 | An upper bound and a lower bound should be set on the list of values. 89 | 90 | NOTE: While implementations may choose different values, the recommended upper bound is 8GiB and the recommended lower bound is 0.25GiB (or 256MiB). 91 | 92 | If Device-Memory header field occurs in a message more than once, the last value overrides all previous occurrences. 93 | 94 | 95 |

Examples

96 | 97 | 512 MiB will be reported as: 98 |
 99 |     Device-Memory: 0.5
100 | 
101 | 102 | 1000 MiB will be reported as: 103 |
104 |     Device-Memory: 1
105 | 
106 | 107 | A full list of possible values should be as follows: 0.25, 0.5, 1, 2, 4, 8 108 | 109 | 110 | 111 | Device Memory JS API {#sec-device-memory-js-api} 112 | ======================================= 113 |
114 | [
115 |     SecureContext,
116 |     Exposed=(Window,Worker)
117 | ] interface mixin NavigatorDeviceMemory {
118 |     readonly attribute double deviceMemory;
119 | };
120 | 
121 | Navigator includes NavigatorDeviceMemory;
122 | WorkerNavigator includes NavigatorDeviceMemory;
123 | 
124 | 125 | NOTE: self.navigator.deviceMemory Returns the amount of ram in GiB as described in [[#computing-device-memory-value]] 126 | 127 | Security Considerations {#sec-security-considerations} 128 | ======================================= 129 | Device-Memory Client Hint header and JS API will only be available to HTTPS secure contexts. 130 | 131 | Device identification and classification (e.g. device type and class) based on advertised User-Agent, and other characteristics of the client, are commonly used to select and provide optimized content. Such solutions frequently rely on commercial device databases, which are costly, hard to integrate, and hard to maintain. This specification defines a mechanism to obtain device memory capability that addresses these technical challenges. 132 | 133 | To reduce fingerprinting risk, reported value is rounded to single most significant bit, as opposed to reporting the exact value. In addition, an upper and lower bound is placed on the reported values. 134 | 135 | IANA considerations {#iana} 136 | =================== 137 | This document defines the `Device-Memory` HTTP request header field, and registers them in the permanent message header field registery ([[RFC3864]]). 138 | 139 | Device-Memory Header field {#iana-device-memory} 140 | --------------------------------- 141 | 142 | : Header field name 143 | :: Device-Memory 144 | 145 | : Applicable protocol 146 | :: http 147 | 148 | : Status 149 | :: standard 150 | 151 | : Author/Change controller 152 | :: IETF 153 | 154 | : Specification document 155 | :: this specification ([[#sec-device-memory-client-hint-header]]) 156 | 157 | 158 |

Acknowledgements

159 | 160 | 161 | 162 | Special thanks to all the contributors for their technical input and suggestions that led to improvements to this 163 | specification. 164 | -------------------------------------------------------------------------------- /w3c.json: -------------------------------------------------------------------------------- 1 | { 2 | "group": 45211, 3 | "contacts": [ 4 | "plehegar" 5 | ], 6 | "shortName": "device-memory", 7 | "repo-type": "rec-track" 8 | } --------------------------------------------------------------------------------