yannstatic/static/2019/12/25/intel-14-nm-amd-7-nm-arm-7-nm-et-mon-serveur.html

2030 lines
196 KiB
HTML
Raw Normal View History

2024-10-31 20:18:37 +01:00
<!DOCTYPE html><html lang="fr">
<head><meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"><title>intel-14-nm-amd-7-nm-arm-7-nm-et-mon-serveur - YannStatic</title>
<meta name="description" content="URL: https://linuxfr.org/users/oliver_h/journaux/intel-14-nm-amd-7-nm-arm-7-nm-et-mon-serveurTitle: Intel = 14nm, AMD = 7nm, ARM = 7nm… et mon serve...">
<link rel="canonical" href="https://static.rnmkcy.eu/2019/12/25/intel-14-nm-amd-7-nm-arm-7-nm-et-mon-serveur.html"><link rel="alternate" type="application/rss+xml" title="YannStatic" href="/feed.xml">
<!-- - include head/favicon.html - -->
<link rel="shortcut icon" type="image/png" href="/assets/favicon/favicon.png"><link rel="stylesheet" href="/assets/css/main.css"><link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.13/css/all.css" ><!-- start custom head snippets --><link rel="stylesheet" href="/assets/css/expand.css">
<!-- end custom head snippets --><script>(function() {
window.isArray = function(val) {
return Object.prototype.toString.call(val) === '[object Array]';
};
window.isString = function(val) {
return typeof val === 'string';
};
window.hasEvent = function(event) {
return 'on'.concat(event) in window.document;
};
window.isOverallScroller = function(node) {
return node === document.documentElement || node === document.body || node === window;
};
window.isFormElement = function(node) {
var tagName = node.tagName;
return tagName === 'INPUT' || tagName === 'SELECT' || tagName === 'TEXTAREA';
};
window.pageLoad = (function () {
var loaded = false, cbs = [];
window.addEventListener('load', function () {
var i;
loaded = true;
if (cbs.length > 0) {
for (i = 0; i < cbs.length; i++) {
cbs[i]();
}
}
});
return {
then: function(cb) {
cb && (loaded ? cb() : (cbs.push(cb)));
}
};
})();
})();
(function() {
window.throttle = function(func, wait) {
var args, result, thisArg, timeoutId, lastCalled = 0;
function trailingCall() {
lastCalled = new Date;
timeoutId = null;
result = func.apply(thisArg, args);
}
return function() {
var now = new Date,
remaining = wait - (now - lastCalled);
args = arguments;
thisArg = this;
if (remaining <= 0) {
clearTimeout(timeoutId);
timeoutId = null;
lastCalled = now;
result = func.apply(thisArg, args);
} else if (!timeoutId) {
timeoutId = setTimeout(trailingCall, remaining);
}
return result;
};
};
})();
(function() {
var Set = (function() {
var add = function(item) {
var i, data = this._data;
for (i = 0; i < data.length; i++) {
if (data[i] === item) {
return;
}
}
this.size ++;
data.push(item);
return data;
};
var Set = function(data) {
this.size = 0;
this._data = [];
var i;
if (data.length > 0) {
for (i = 0; i < data.length; i++) {
add.call(this, data[i]);
}
}
};
Set.prototype.add = add;
Set.prototype.get = function(index) { return this._data[index]; };
Set.prototype.has = function(item) {
var i, data = this._data;
for (i = 0; i < data.length; i++) {
if (this.get(i) === item) {
return true;
}
}
return false;
};
Set.prototype.is = function(map) {
if (map._data.length !== this._data.length) { return false; }
var i, j, flag, tData = this._data, mData = map._data;
for (i = 0; i < tData.length; i++) {
for (flag = false, j = 0; j < mData.length; j++) {
if (tData[i] === mData[j]) {
flag = true;
break;
}
}
if (!flag) { return false; }
}
return true;
};
Set.prototype.values = function() {
return this._data;
};
return Set;
})();
window.Lazyload = (function(doc) {
var queue = {js: [], css: []}, sources = {js: {}, css: {}}, context = this;
var createNode = function(name, attrs) {
var node = doc.createElement(name), attr;
for (attr in attrs) {
if (attrs.hasOwnProperty(attr)) {
node.setAttribute(attr, attrs[attr]);
}
}
return node;
};
var end = function(type, url) {
var s, q, qi, cbs, i, j, cur, val, flag;
if (type === 'js' || type ==='css') {
s = sources[type], q = queue[type];
s[url] = true;
for (i = 0; i < q.length; i++) {
cur = q[i];
if (cur.urls.has(url)) {
qi = cur, val = qi.urls.values();
qi && (cbs = qi.callbacks);
for (flag = true, j = 0; j < val.length; j++) {
cur = val[j];
if (!s[cur]) {
flag = false;
}
}
if (flag && cbs && cbs.length > 0) {
for (j = 0; j < cbs.length; j++) {
cbs[j].call(context);
}
qi.load = true;
}
}
}
}
};
var load = function(type, urls, callback) {
var s, q, qi, node, i, cur,
_urls = typeof urls === 'string' ? new Set([urls]) : new Set(urls), val, url;
if (type === 'js' || type ==='css') {
s = sources[type], q = queue[type];
for (i = 0; i < q.length; i++) {
cur = q[i];
if (_urls.is(cur.urls)) {
qi = cur;
break;
}
}
val = _urls.values();
if (qi) {
callback && (qi.load || qi.callbacks.push(callback));
callback && (qi.load && callback());
} else {
q.push({
urls: _urls,
callbacks: callback ? [callback] : [],
load: false
});
for (i = 0; i < val.length; i++) {
node = null, url = val[i];
if (s[url] === undefined) {
(type === 'js' ) && (node = createNode('script', { src: url }));
(type === 'css') && (node = createNode('link', { rel: 'stylesheet', href: url }));
if (node) {
node.onload = (function(type, url) {
return function() {
end(type, url);
};
})(type, url);
(doc.head || doc.body).appendChild(node);
s[url] = false;
}
}
}
}
}
};
return {
js: function(url, callback) {
load('js', url, callback);
},
css: function(url, callback) {
load('css', url, callback);
}
};
})(this.document);
})();
</script><script>
(function() {
var TEXT_VARIABLES = {
version: '2.2.6',
sources: {
font_awesome: 'https://use.fontawesome.com/releases/v5.0.13/css/all.css',
jquery: '/assets/js/jquery.min.js',
leancloud_js_sdk: '//cdn.jsdelivr.net/npm/leancloud-storage@3.13.2/dist/av-min.js',
chart: 'https://cdn.bootcss.com/Chart.js/2.7.2/Chart.bundle.min.js',
gitalk: {
js: 'https://cdn.bootcss.com/gitalk/1.2.2/gitalk.min.js',
css: 'https://cdn.bootcss.com/gitalk/1.2.2/gitalk.min.css'
},
valine: 'https://unpkg.com/valine/dist/Valine.min.js'
},
site: {
toc: {
selectors: 'h1,h2,h3'
}
},
paths: {
search_js: '/assets/search.js'
}
};
window.TEXT_VARIABLES = TEXT_VARIABLES;
})();
</script>
</head>
<body>
<div class="root" data-is-touch="false">
<div class="layout--page js-page-root"><!----><div class="page__main js-page-main page__viewport hide-footer has-aside has-aside cell cell--auto">
<div class="page__main-inner"><div class="page__header d-print-none"><header class="header"><div class="main">
<div class="header__title">
<div class="header__brand"><svg id="svg" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="400" height="478.9473684210526" viewBox="0, 0, 400,478.9473684210526"><g id="svgg"><path id="path0" d="M308.400 56.805 C 306.970 56.966,303.280 57.385,300.200 57.738 C 290.906 58.803,278.299 59.676,269.200 59.887 L 260.600 60.085 259.400 61.171 C 258.010 62.428,256.198 63.600,255.645 63.600 C 255.070 63.600,252.887 65.897,252.598 66.806 C 252.460 67.243,252.206 67.600,252.034 67.600 C 251.397 67.600,247.206 71.509,247.202 72.107 C 247.201 72.275,246.390 73.190,245.400 74.138 C 243.961 75.517,243.598 76.137,243.592 77.231 C 243.579 79.293,241.785 83.966,240.470 85.364 C 239.176 86.740,238.522 88.365,237.991 91.521 C 237.631 93.665,236.114 97.200,235.554 97.200 C 234.938 97.200,232.737 102.354,232.450 104.472 C 232.158 106.625,230.879 109.226,229.535 110.400 C 228.933 110.926,228.171 113.162,226.434 119.500 C 226.178 120.435,225.795 121.200,225.584 121.200 C 225.373 121.200,225.200 121.476,225.200 121.813 C 225.200 122.149,224.885 122.541,224.500 122.683 C 223.606 123.013,223.214 123.593,223.204 124.600 C 223.183 126.555,220.763 132.911,219.410 134.562 C 218.443 135.742,217.876 136.956,217.599 138.440 C 217.041 141.424,215.177 146.434,214.532 146.681 C 214.240 146.794,214.000 147.055,214.000 147.261 C 214.000 147.467,213.550 148.086,213.000 148.636 C 212.450 149.186,212.000 149.893,212.000 150.208 C 212.000 151.386,208.441 154.450,207.597 153.998 C 206.319 153.315,204.913 150.379,204.633 147.811 C 204.365 145.357,202.848 142.147,201.759 141.729 C 200.967 141.425,199.200 137.451,199.200 135.974 C 199.200 134.629,198.435 133.224,196.660 131.311 C 195.363 129.913,194.572 128.123,193.870 125.000 C 193.623 123.900,193.236 122.793,193.010 122.540 C 190.863 120.133,190.147 118.880,188.978 115.481 C 188.100 112.928,187.151 111.003,186.254 109.955 C 185.358 108.908,184.518 107.204,183.847 105.073 C 183.280 103.273,182.497 101.329,182.108 100.753 C 181.719 100.177,180.904 98.997,180.298 98.131 C 179.693 97.265,178.939 95.576,178.624 94.378 C 178.041 92.159,177.125 90.326,175.023 87.168 C 174.375 86.196,173.619 84.539,173.342 83.486 C 172.800 81.429,171.529 79.567,170.131 78.785 C 169.654 78.517,168.697 77.511,168.006 76.549 C 167.316 75.587,166.594 74.800,166.402 74.800 C 166.210 74.800,164.869 73.633,163.421 72.206 C 160.103 68.936,161.107 69.109,146.550 69.301 C 133.437 69.474,128.581 70.162,126.618 72.124 C 126.248 72.495,125.462 72.904,124.872 73.033 C 124.282 73.163,123.088 73.536,122.219 73.863 C 121.349 74.191,119.028 74.638,117.061 74.858 C 113.514 75.254,109.970 76.350,108.782 77.419 C 107.652 78.436,100.146 80.400,97.388 80.400 C 95.775 80.400,93.167 81.360,91.200 82.679 C 90.430 83.195,89.113 83.804,88.274 84.031 C 85.875 84.681,78.799 90.910,74.400 96.243 L 73.400 97.456 73.455 106.028 C 73.526 117.055,74.527 121.238,77.820 124.263 C 78.919 125.273,80.400 127.902,80.400 128.842 C 80.400 129.202,81.075 130.256,81.900 131.186 C 83.563 133.059,85.497 136.346,86.039 138.216 C 86.233 138.886,87.203 140.207,88.196 141.153 C 89.188 142.098,90.000 143.104,90.000 143.388 C 90.000 144.337,92.129 148.594,92.869 149.123 C 93.271 149.410,93.600 149.831,93.600 150.059 C 93.600 150.286,93.932 150.771,94.337 151.136 C 94.743 151.501,95.598 153.004,96.237 154.475 C 96.877 155.947,97.760 157.351,98.200 157.596 C 98.640 157.841,99.900 159.943,101.000 162.267 C 102.207 164.817,103.327 166.644,103.825 166.876 C 104.278 167.087,105.065 168.101,105.573 169.130 C 107.658 173.348,108.097 174.093,110.006 176.647 C 111.103 178.114,112.000 179.725,112.000 180.227 C 112.000 181.048,113.425 183.163,114.678 184.200 C 115.295 184.711,117.396 188.733,117.720 190.022 C 117.855 190.562,118.603 191.633,119.381 192.402 C 120.160 193.171,121.496 195.258,122.351 197.039 C 123.206 198.820,124.167 200.378,124.487 200.501 C 124.807 200.624,125.953 202.496,127.034 204.662 C 128.114 206.828,129.676 209.299,130.505 210.153 C 131.333 211.007,132.124 212.177,132.262 212.753 C 132.618 214.239,134.291 217.048,136.288 219.5
" href="/">YannStatic</a></div><!--<button class="button button--secondary button--circle search-button js-search-toggle"><i class="fas fa-search"></i></button>--><!-- <li><button class="button button--secondary button--circle search-button js-search-toggle"><i class="fas fa-search"></i></button></li> -->
<!-- Champ de recherche -->
<div id="searchbox" class="search search--dark" style="visibility: visible">
<div class="main">
<div class="search__header"></div>
<div class="search-bar">
<div class="search-box js-search-box">
<div class="search-box__icon-search"><i class="fas fa-search"></i></div>
<input id="search-input" type="text" />
<!-- <div class="search-box__icon-clear js-icon-clear">
<a><i class="fas fa-times"></i></a>
</div> -->
</div>
</div>
</div>
</div>
<!-- Script pointing to search-script.js -->
<script>/*!
* Simple-Jekyll-Search
* Copyright 2015-2020, Christian Fei
* Licensed under the MIT License.
*/
(function(){
'use strict'
var _$Templater_7 = {
compile: compile,
setOptions: setOptions
}
const options = {}
options.pattern = /\{(.*?)\}/g
options.template = ''
options.middleware = function () {}
function setOptions (_options) {
options.pattern = _options.pattern || options.pattern
options.template = _options.template || options.template
if (typeof _options.middleware === 'function') {
options.middleware = _options.middleware
}
}
function compile (data) {
return options.template.replace(options.pattern, function (match, prop) {
const value = options.middleware(prop, data[prop], options.template)
if (typeof value !== 'undefined') {
return value
}
return data[prop] || match
})
}
'use strict';
function fuzzysearch (needle, haystack) {
var tlen = haystack.length;
var qlen = needle.length;
if (qlen > tlen) {
return false;
}
if (qlen === tlen) {
return needle === haystack;
}
outer: for (var i = 0, j = 0; i < qlen; i++) {
var nch = needle.charCodeAt(i);
while (j < tlen) {
if (haystack.charCodeAt(j++) === nch) {
continue outer;
}
}
return false;
}
return true;
}
var _$fuzzysearch_1 = fuzzysearch;
'use strict'
/* removed: const _$fuzzysearch_1 = require('fuzzysearch') */;
var _$FuzzySearchStrategy_5 = new FuzzySearchStrategy()
function FuzzySearchStrategy () {
this.matches = function (string, crit) {
return _$fuzzysearch_1(crit.toLowerCase(), string.toLowerCase())
}
}
'use strict'
var _$LiteralSearchStrategy_6 = new LiteralSearchStrategy()
function LiteralSearchStrategy () {
this.matches = function (str, crit) {
if (!str) return false
str = str.trim().toLowerCase()
crit = crit.trim().toLowerCase()
return crit.split(' ').filter(function (word) {
return str.indexOf(word) >= 0
}).length === crit.split(' ').length
}
}
'use strict'
var _$Repository_4 = {
put: put,
clear: clear,
search: search,
setOptions: __setOptions_4
}
/* removed: const _$FuzzySearchStrategy_5 = require('./SearchStrategies/FuzzySearchStrategy') */;
/* removed: const _$LiteralSearchStrategy_6 = require('./SearchStrategies/LiteralSearchStrategy') */;
function NoSort () {
return 0
}
const data = []
let opt = {}
opt.fuzzy = false
opt.limit = 10
opt.searchStrategy = opt.fuzzy ? _$FuzzySearchStrategy_5 : _$LiteralSearchStrategy_6
opt.sort = NoSort
opt.exclude = []
function put (data) {
if (isObject(data)) {
return addObject(data)
}
if (isArray(data)) {
return addArray(data)
}
return undefined
}
function clear () {
data.length = 0
return data
}
function isObject (obj) {
return Boolean(obj) && Object.prototype.toString.call(obj) === '[object Object]'
}
function isArray (obj) {
return Boolean(obj) && Object.prototype.toString.call(obj) === '[object Array]'
}
function addObject (_data) {
data.push(_data)
return data
}
function addArray (_data) {
const added = []
clear()
for (let i = 0, len = _data.length; i < len; i++) {
if (isObject(_data[i])) {
added.push(addObject(_data[i]))
}
}
return added
}
function search (crit) {
if (!crit) {
return []
}
return findMatches(data, crit, opt.searchStrategy, opt).sort(opt.sort)
}
function __setOptions_4 (_opt) {
opt = _opt || {}
opt.fuzzy = _opt.fuzzy || false
opt.limit = _opt.limit || 10
opt.searchStrategy = _opt.fuzzy ? _$FuzzySearchStrategy_5 : _$LiteralSearchStrategy_6
opt.sort = _opt.sort || NoSort
opt.exclude = _opt.exclude || []
}
function findMatches (data, crit, strategy, opt) {
const matches = []
for (let i = 0; i < data.length && matches.length < opt.limit; i++) {
const match = findMatchesInObject(data[i], crit, strategy, opt)
if (match) {
matches.push(match)
}
}
return matches
}
function findMatchesInObject (obj, crit, strategy, opt) {
for (const key in obj) {
if (!isExcluded(obj[key], opt.exclude) && strategy.matches(obj[key], crit)) {
return obj
}
}
}
function isExcluded (term, excludedTerms) {
for (let i = 0, len = excludedTerms.length; i < len; i++) {
const excludedTerm = excludedTerms[i]
if (new RegExp(excludedTerm).test(term)) {
return true
}
}
return false
}
/* globals ActiveXObject:false */
'use strict'
var _$JSONLoader_2 = {
load: load
}
function load (location, callback) {
const xhr = getXHR()
xhr.open('GET', location, true)
xhr.onreadystatechange = createStateChangeListener(xhr, callback)
xhr.send()
}
function createStateChangeListener (xhr, callback) {
return function () {
if (xhr.readyState === 4 && xhr.status === 200) {
try {
callback(null, JSON.parse(xhr.responseText))
} catch (err) {
callback(err, null)
}
}
}
}
function getXHR () {
return window.XMLHttpRequest ? new window.XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP')
}
'use strict'
var _$OptionsValidator_3 = function OptionsValidator (params) {
if (!validateParams(params)) {
throw new Error('-- OptionsValidator: required options missing')
}
if (!(this instanceof OptionsValidator)) {
return new OptionsValidator(params)
}
const requiredOptions = params.required
this.getRequiredOptions = function () {
return requiredOptions
}
this.validate = function (parameters) {
const errors = []
requiredOptions.forEach(function (requiredOptionName) {
if (typeof parameters[requiredOptionName] === 'undefined') {
errors.push(requiredOptionName)
}
})
return errors
}
function validateParams (params) {
if (!params) {
return false
}
return typeof params.required !== 'undefined' && params.required instanceof Array
}
}
'use strict'
var _$utils_9 = {
merge: merge,
isJSON: isJSON
}
function merge (defaultParams, mergeParams) {
const mergedOptions = {}
for (const option in defaultParams) {
mergedOptions[option] = defaultParams[option]
if (typeof mergeParams[option] !== 'undefined') {
mergedOptions[option] = mergeParams[option]
}
}
return mergedOptions
}
function isJSON (json) {
try {
if (json instanceof Object && JSON.parse(JSON.stringify(json))) {
return true
}
return false
} catch (err) {
return false
}
}
var _$src_8 = {};
(function (window) {
'use strict'
let options = {
searchInput: null,
resultsContainer: null,
json: [],
success: Function.prototype,
searchResultTemplate: '<li><a href="{url}" title="{desc}">{title}</a></li>',
templateMiddleware: Function.prototype,
sortMiddleware: function () {
return 0
},
noResultsText: 'No results found',
limit: 10,
fuzzy: false,
debounceTime: null,
exclude: []
}
let debounceTimerHandle
const debounce = function (func, delayMillis) {
if (delayMillis) {
clearTimeout(debounceTimerHandle)
debounceTimerHandle = setTimeout(func, delayMillis)
} else {
func.call()
}
}
const requiredOptions = ['searchInput', 'resultsContainer', 'json']
/* removed: const _$Templater_7 = require('./Templater') */;
/* removed: const _$Repository_4 = require('./Repository') */;
/* removed: const _$JSONLoader_2 = require('./JSONLoader') */;
const optionsValidator = _$OptionsValidator_3({
required: requiredOptions
})
/* removed: const _$utils_9 = require('./utils') */;
window.SimpleJekyllSearch = function (_options) {
const errors = optionsValidator.validate(_options)
if (errors.length > 0) {
throwError('You must specify the following required options: ' + requiredOptions)
}
options = _$utils_9.merge(options, _options)
_$Templater_7.setOptions({
template: options.searchResultTemplate,
middleware: options.templateMiddleware
})
_$Repository_4.setOptions({
fuzzy: options.fuzzy,
limit: options.limit,
sort: options.sortMiddleware,
exclude: options.exclude
})
if (_$utils_9.isJSON(options.json)) {
initWithJSON(options.json)
} else {
initWithURL(options.json)
}
const rv = {
search: search
}
typeof options.success === 'function' && options.success.call(rv)
return rv
}
function initWithJSON (json) {
_$Repository_4.put(json)
registerInput()
}
function initWithURL (url) {
_$JSONLoader_2.load(url, function (err, json) {
if (err) {
throwError('failed to get JSON (' + url + ')')
}
initWithJSON(json)
})
}
function emptyResultsContainer () {
options.resultsContainer.innerHTML = ''
}
function appendToResultsContainer (text) {
options.resultsContainer.innerHTML += text
}
function registerInput () {
options.searchInput.addEventListener('input', function (e) {
if (isWhitelistedKey(e.which)) {
emptyResultsContainer()
debounce(function () { search(e.target.value) }, options.debounceTime)
}
})
}
function search (query) {
if (isValidQuery(query)) {
emptyResultsContainer()
render(_$Repository_4.search(query), query)
}
}
function render (results, query) {
const len = results.length
if (len === 0) {
return appendToResultsContainer(options.noResultsText)
}
for (let i = 0; i < len; i++) {
results[i].query = query
appendToResultsContainer(_$Templater_7.compile(results[i]))
}
}
function isValidQuery (query) {
return query && query.length > 0
}
function isWhitelistedKey (key) {
return [13, 16, 20, 37, 38, 39, 40, 91].indexOf(key) === -1
}
function throwError (message) {
throw new Error('SimpleJekyllSearch --- ' + message)
}
})(window)
}());
</script>
<!-- Configuration -->
<script>
SimpleJekyllSearch({
searchInput: document.getElementById('search-input'),
resultsContainer: document.getElementById('results-container'),
json: '/search.json',
//searchResultTemplate: '<li><a href="https://static.rnmkcy.eu{url}">{date}&nbsp;{title}</a></li>'
searchResultTemplate: '<li><a href="{url}">{date}&nbsp;{title}</a></li>'
})
</script>
<!-- Fin déclaration champ de recherche --></div><nav class="navigation">
<ul><li class="navigation__item"><a href="/archive.html">Etiquettes</a></li><li class="navigation__item"><a href="/htmldoc.html">Documents</a></li><li class="navigation__item"><a href="/liens_ttrss.html">Liens</a></li><li class="navigation__item"><a href="/aide-jekyll-text-theme.html">Aide</a></li></ul>
</nav></div>
</header>
</div><div class="page__content"><div class ="main"><div class="grid grid--reverse">
<div class="col-main cell cell--auto"><!-- start custom main top snippet --><div id="results-container" class="search-result js-search-result"></div><!-- end custom main top snippet -->
<article itemscope itemtype="http://schema.org/Article"><div class="article__header"><header><h1 style="color:Tomato;">intel-14-nm-amd-7-nm-arm-7-nm-et-mon-serveur</h1></header></div><meta itemprop="headline" content="intel-14-nm-amd-7-nm-arm-7-nm-et-mon-serveur"><div class="article__info clearfix"><ul class="left-col menu"><li>
<a class="button button--secondary button--pill button--sm"
href="/archive.html?tag=divers">divers</a>
</li></ul><ul class="right-col menu"><li>
<i class="far fa-calendar-alt"></i>&nbsp;<span title="Création" style="color:#FF00FF">25&nbsp;déc.&nbsp;&nbsp;2019</span>
<span title="Modification" style="color:#00FF7F">&nbsp;4&nbsp;déc.&nbsp;&nbsp;2019</span></li></ul></div><meta itemprop="datePublished" content="2019-12-04T00:00:00+01:00">
<meta itemprop="keywords" content="divers"><div class="js-article-content">
<div class="layout--article"><!-- start custom article top snippet -->
<style>
#myBtn {
display: none;
position: fixed;
bottom: 10px;
right: 10px;
z-index: 99;
font-size: 12px;
font-weight: bold;
border: none;
outline: none;
background-color: white;
color: black;
cursor: pointer;
padding: 5px;
border-radius: 4px;
}
#myBtn:hover {
background-color: #555;
}
</style>
<button onclick="topFunction()" id="myBtn" title="Haut de page">&#8679;</button>
<script>
//Get the button
var mybutton = document.getElementById("myBtn");
// When the user scrolls down 20px from the top of the document, show the button
window.onscroll = function() {scrollFunction()};
function scrollFunction() {
if (document.body.scrollTop > 20 || document.documentElement.scrollTop > 20) {
mybutton.style.display = "block";
} else {
mybutton.style.display = "none";
}
}
// When the user clicks on the button, scroll to the top of the document
function topFunction() {
document.body.scrollTop = 0;
document.documentElement.scrollTop = 0;
}
</script>
<!-- end custom article top snippet -->
<div class="article__content" itemprop="articleBody"><details>
<summary><b>Afficher/cacher Sommaire</b></summary>
<!-- affichage sommaire -->
<div class="toc-aside js-toc-root"></div>
</details><p>URL: https://linuxfr.org/users/oliver_h/journaux/intel-14-nm-amd-7-nm-arm-7-nm-et-mon-serveur
Title: Intel = 14nm, AMD = 7nm, ARM = 7nm… et mon serveur ?
Authors: Oliver
Date: 2019-12-03T23:49:17+01:00
License: CC by-sa
Tags: intel, amd, amd64, arm et serveur
Score: 24</p>
<p>Je me lance dans un projet personnel qui nécessite un serveur pour lequel je viens de faire le tour des actualités. Je vous partage ici mes découvertes et mes réflexions. Bonne lecture.</p>
<p>^(^Je ^place ^ce ^document ^sous ^licence ^CC0.)</p>
<h1 id="intel--14nm">Intel = 14 nm</h1>
<p>Intel avait lhabitude dadopter une nouvelle finesse de gravure tous les deux ans. Et avec chaque nouvelle finesse de gravure, les nouveaux processeurs étaient toujours plus véloces :</p>
<ul>
<li>45 nm en novembre 2007 (Penryn)</li>
<li>32 nm en janvier 2010 (Westmere, 2 ans après)</li>
<li>22 nm en avril 2012 (Ivy Bridge, 2 ans après)</li>
<li>14 nm en septembre 2014 (Broadwell, 2 ans après)</li>
<li>10 nm avec deux tentatives pas très concluantes au niveau des performances en 2018 (Cannon Lake) et 2019 (Ice Lake)</li>
</ul>
<p>Ou là, Intel a du mal à adopter pleinement le 10nm… Espérons que le troisième rafraîchissement <em>(optimization)</em> de la micro-architecture en 10nm (10nm++ <a href="https://en.wikipedia.org/wiki/Tiger_Lake_(microarchitecture)">Tiger Lake</a> prévu pour 2020) sera plus véloce que le quatrième rafraîchissement de celle en 14nm (14nm+++ <a href="https://en.wikipedia.org/wiki/Comet_Lake">Comet Lake</a>).</p>
<p>Par rapport à la régularité du cycle biennal, Intel stagne 6 années sur la gravure 14nm, et peut-être plus longtemps si on en croit des rumeurs tablant sur <a href="https://www.tweaktown.com/news/68127/intel-cancels-10 nm-desktop-14 nm-hold-until-2022/index.html">2022 pour voir enfin arriver des processeurs Intel 10 nm dans les ordinateurs fixes</a>.</p>
<p>Dailleurs, ces difficultés de passer à la gravure 10nm ont plutôt incité Intel à temporiser la pleine production en 10nm. Par conséquent, Intel a plutôt intérêt à sorienter vers des prévisions de vente pessimistes. Mais la conjoncture économique est au renouvellement des ordinateurs. Et fait rare, <a href="https://www.zdnet.fr/actualites/intel-s-excuse-pour-ses-retards-de-livraison-et-pointe-une-demande-excessive-de-cpu-39894299.htm">Intel sexcuse pour ses retards de livraison</a>. Face à la demande, Intel favorise les deux segments qui rapportent le plus : les Xeon haut de gamme (gros serveurs) et les i9 (<a href="https://fr.wikipedia.org/wiki/Gamer">Gamer</a>).</p>
<p>Attention, ne vous faites pas avoir, la dernière et 10ᵉ génération des processeurs Intel est en double gravure 14 nm et 10 nm : la publicité de Intel met en avant la finesse de gravure 10nm, mais leurs tests de vélocité utilisent des processeurs gravés en 14nm.</p>
<p>Ce qui me choque le plus est la compétitivité de mon vieil ordinateur portable acheté en 2012, chez <a href="https://pcubuntoo.fr/">pcubuntoo</a> avec un processeur i7-3610QM (22nm Ivy Bridge) et 8 Go DDR3, à 800€ sans disque dur. Ce bon vieux portable (7 ans) fonctionne toujours aussi bien et me semble dans la même gamme de prix que les portables équipés du i7-1060G7 (toujours le même nombre de cœurs et la même quantité de mémoire).</p>
<p>Néanmoins, au niveau consommation électrique et fréquence de fonctionnement, le dernier i7-1060G7 doit battre mon vieux i7-3610QM (2012). Jai bien limpression que cest seulement sur ces deux aspects que les processeurs de Intel se sont améliorés : consommation et fréquence. Rappelons que Intel a raté le marché des téléphones, et que depuis une dizaine dannées, Intel essaye de produire des processeurs capables de rivaliser avec ceux utilisés dans les téléphones. Une des priorités de Intel est la réduction de la consommation électrique.</p>
<p>Une autre amélioration des processeurs Intel est le paquet de nouvelles instructions. Mais bon, la plupart des logiciels sont compilés avec la compatibilité des premiers processeurs <a href="https://help.ubuntu.com/18.04/installation-guide/amd64/ch02s01.html">AMD64</a> (<a href="https://fedoraproject.org/wiki/Architectures/x86#Supported_Hardware">Pentium II</a>) de la fin des années 90 (il y a 20 ans).</p>
<p>Notons que Intel a changé sa <a href="https://fr.wikipedia.org/wiki/Intel#Stratégies_tic-tac_et_processus-architecture-optimisation">stratégie <em>tic-tac</em></a>. Avec la nouvelle stratégie <em>processus-architecture-optimisation</em>, Intel profite de la réduction de la taille de gravure pour réduire la consommation électrique. Puis, Intel apporte des rafraîchissements <em>(optimizations)</em> pour améliorer la vélocité.</p>
<p>Bref, tout ça pour dire, que jai du mal à justifier le renouvellement de mon vieil ordinateur, dautant plus que la mode est à la réutilisation, léconomie circulaire. À la rigueur, on peut installer un nouveau SSD plus volumineux en espérant pouvoir stocker toutes les vidéos que nous avons tendance à capturer avec nos ordiphones ! Mais on touche un autre sujet qui nécessite un article à part entière : comment bien stocker et protéger son patrimoine numérique avec les logiciels libres daujourdhui.</p>
<p>Pour ceux qui sont dans mon cas, on trouve des SSD SATA à des prix accessibles : 60€ pour 500Go, 110€ pour 1To et 230€ pour 2To.</p>
<h1 id="amd--7nm">AMD = 7 nm</h1>
<p>Alors que Intel essaye de passer à 10nm, AMD est déjà loin avec la gravure en 7nm. Jinvite les experts qui pensent que le 10nm de Intel correspond au 7nm de AMD à nous donner des explications dans les commentaires (jai la flegme de vérifier la taille des transistors dans la documentation de chacun des fondeurs).</p>
<p>Je naime pas les situations de quasi-monopôle (Intel, Microsoft, Google, YouTube…) et jessaye de ne pas cautionner ces monopôles et choisissant des alternatives. Mais bon, reconnaissons que Intel contribue au noyau Linux et à la pile graphique, ce qui garantie une certaine compatibilité avec leurs processeurs. AMD y contribue moins, favorise davantage le segment Windows… allez donnons lui une chance dans ce journal.</p>
<p>Pour avancer rapidement, AMD fait fondre ses processeurs par des sous-traitants. Et dici que Intel livrent enfin des processeurs 10nm pour les ordinateurs fixes, AMD en sera peut-être à létape 5 nm, car son sous-traitant <a href="https://en.wikipedia.org/wiki/5_nanometer#5_nm_process_nodes">TSMC est déjà prêt pour la production en 5 nm</a>.</p>
<p>De plus, AMD nessaye pas non plus de rivaliser avec la faible consommation électrique des processeurs de nos téléphones portables, une contrainte de moins que Intel. Le vrai débouché des processeurs x86 sont les serveurs, et ceux qui achètent les serveurs ne sont plus les grandes entreprises, mais les gestionnaires des centres de données <em>(datacenters)</em> : Amazon, Google, Microsoft… Historiquement HP et Dell étaient les plus gros acheteurs de processeurs pour serveur, mais les <em>cloud providers</em> ont leurs équipes dédiées pour la fabrication de leur matériel.</p>
<p>Les deux segments prioritaires de AMD ont été les <em>cloud providers</em> et les <em>gamers</em>. Donc, en plus de proposer des processeurs en 7nm, AMD propose aussi davantage de cœurs. Sa micro-architecture Zen (Zen+, Zen 2, Zen 3) est utilisée pour ses processeurs EPYC et Ryzen. Ces deux gammes de processeurs, peuvent embarquer jusquà 64 cœurs chacun !</p>
<p>Par conséquent, les processeurs AMD connaissent de plus en plus de succès. Le fait de passer par un fondeur multi-clients, AMD peut plus facilement dadapter la production à la demande. Récemment, des <a href="https://wccftech.com/amd-ryzen-9-3950x-entire-inventory-outsold-japan-worldwide/">japonais faisaient la queue avant louverture des boutiques pour acquérir le dernier processeur AMD Ryzen 9</a>.</p>
<p>Sur le lien précédent, deux images sont intéressantes :</p>
<h2 id="le-nombre-de-processeurs-vendus-par-amd-et-intel-sur-1-an">Le nombre de processeurs vendus par AMD et Intel sur 1 an</h2>
<p>Nous pouvons constater une envolée des ventes de AMD depuis cet été, alors que pour Intel ça stagne.</p>
<p><img src="https://cdn.wccftech.com/wp-content/uploads/2019/12/AMD-Mindfactory-Market-Share-November-2019-mMr8FET-1480x699.png" alt="Le nombre de processeurs vendus par AMD et Intel sur 1 an" /></p>
<h2 id="le-chiffre-daffaires">Le chiffre daffaires</h2>
<p>Nous pouvons remarquer que le chiffre daffaires de AMD est moindre pour le même volume de processeurs vendus. Certainement car AMD vend ses processeurs moins chers que Intel.</p>
<p><img src="https://cdn.wccftech.com/wp-content/uploads/2019/12/AMD-Mindfactory-Market-Share-November-2019-G1UqpYZ-1480x699.png" alt="Le chiffre daffaires de processeurs vendus par AMD et Intel sur 1 an" /></p>
<h2 id="exemples-de-serveurs-amd">Exemples de serveurs AMD</h2>
<h3 id="800--ryzen-72700-8-cœurs--hdd-2to">800 € = Ryzen 7 2700 (8 cœurs) + HDD 2To</h3>
<p>Configuration obtenue sur le site LDLC en optant pour le Ryzen 7 2700, un processeur dancienne génération (Zen+, 2018), qui se trouve moins cher que les Ryzen 5 de nouvelle génération (Zen 2, 2019). Le Ryzen 7 2700 permet dobtenir un petit ratio <strong>55€/cœur</strong> (coût par cœur sans compter RAM, SSD et HDD).</p>
<table>
<thead>
<tr>
<th style="text-align: right">Prix</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: right">210 </td>
<td>AMD Ryzen 7 2700 (8 cœurs 3.2 GHz)</td>
</tr>
<tr>
<td style="text-align: right">210 </td>
<td>32 Go DDR4 2933 MHz</td>
</tr>
<tr>
<td style="text-align: right">80 </td>
<td>SSD 500 Go M.2 PCI x4</td>
</tr>
<tr>
<td style="text-align: right">70 </td>
<td>HDD 2 To</td>
</tr>
<tr>
<td style="text-align: right">100 </td>
<td>Alimentation 80PLUS Platinium 550 W</td>
</tr>
<tr>
<td style="text-align: right">20 </td>
<td>Ventirad dentrée de gamme (pas besoin de lumière)</td>
</tr>
<tr>
<td style="text-align: right">80 </td>
<td>Carte mère dentrée de gamme avec 4 <em>slots</em> mémoire</td>
</tr>
<tr>
<td style="text-align: right">30 </td>
<td>Boîtier mini tour dentrée de gamme</td>
</tr>
</tbody>
</table>
<h3 id="2500--ryzem-93900x-12-cœurs--hdd-20to">2500 $ = Ryzem 9 3900X (12 cœurs) + HDD 20To</h3>
<p>Chez <a href="https://system76.com/desktops/thelio-r1/configure">System76</a> :</p>
<ul>
<li>Ryzem 9 3900X (12 cœurs 3.8GHz)</li>
<li>32 Go DDR4</li>
<li>SSD 500 Go M.2 PCI express</li>
<li>HDD 20 To</li>
</ul>
<p>Jestime le ratio à <strong>100$/cœur</strong> (sans prendre en compte les prix supposés des RAM, SSD et HDD).</p>
<h1 id="serveurs-arm">Serveurs ARM</h1>
<p>Depuis 20 ans, des constructeurs tentent de concurrencer les serveurs basés sur les processeurs x86 (AMD et Intel). Nous avions les PowerPC, mais quand Apple a abandonné les PowerPC pour les Duo-cœurs dIntel, lindustrie sest aussi orientée vers les processeurs Intel. La solution ARM devenaient la seule alternative crédible face au monopôle des x86, grâce à un prix de vente et une consommation électrique très faibles.</p>
<p>Mais il ne suffit pas de réduire le coût dachat et le coût dutilisation (factures électriques), il faut surtout avoir un haut ratio <code class="language-plaintext highlighter-rouge">vitesse dexécution / coût de possession</code>. Et sur ce point, la fabrication en masse de composant pour lécosystème x86 permettent aux constructeurs de serveurs x86 de proposer des solutions suffisamment performantes pour ne pas se faire trop distancer par les serveurs ARM qui natteignaient pas la taille critique.</p>
<p>Un autre élément en faveur des serveurs x86 qui est bien plus important : la rétro-compatibilité avec les anciens logiciels. Et oui, on migre pas dun claquement de doigt les logiciels (dont le système dexploitation) de larchitecture x86 vers ARM. Cest un argument similaire qui laisse <a href="https://www.extremetech.com/computing/286311-linus-torvalds-claims-arm-wont-win-in-the-server-space">Linus Torvalds penser à léchec des serveurs ARM</a> : Ce nest pas facile de développer/déboguer sur sa machine de dév. x86 et déployer sur une machine ARM.</p>
<p>Par contre, quand nous commençons un tout nouveau projet, on peut dès le début tout mettre en place pour faciliter le déploiement sur une architecture ARM.</p>
<p>Cest ce que fait Amazon depuis un an avec ses processeurs ARM, nommés Graviton. Et la <a href="https://siliconangle.com/2019/11/28/report-aws-developing-new-graviton-chip-32-cœurs-20-speed/">seconde génération Graviton est en cours de genèse</a> qui embarquent 32 cœurs. Amazon a la taille critique pour produire suffisamment de processeurs Graviton afin dobtenir des processeurs ARM deux fois moins coûteux que les équivalents chez AMD et Intel. Par contre, les meilleurs processeurs Intel et AMD restent plus véloces que les Graviton (pour un même nombre de cœurs).</p>
<p>Et cest possible de sen procurrer. \o/</p>
<p>System76 propose le <a href="https://system76.com/servers/stap1b/configure">Starling Pro ARM</a>.
Une configuration avec 96 cœurs et 128 Go RAM coûte dans les 6000$ pour un ratio <strong>65$/cœur</strong>.</p>
<p><a href="https://www.gigabyte.com/fr/ARM-Server/Marvell-ThunderX">Gigabyte propose aussi des serveurs ARM</a>, dénommés <em>“blockchain infrastructure”</em>.</p>
<h1 id="serveurs-risc-v">Serveurs RISC-V</h1>
<p>Le top du top, ce serait, quand même, dutiliser des processeurs RISC-V sous licence <em>open hardware</em>. Peut-être dans 10 ans…</p>
<h1 id="projet-personnel-nécessitant-un-gros-serveur">Projet personnel nécessitant un <em>gros</em> serveur</h1>
<p>Dans mon cas, je commence un projet personnel et jai besoin de développer, tester et laisser tourner mon logiciel plusieurs jours daffilée, voir plusieurs mois, avec haute disponibilité et mise à jour à chaud de nouvelles versions.</p>
<p>Jai cinq possibilités pour mon serveur :</p>
<ol>
<li>Louer une machine virtuelle dans les nuages ;</li>
<li>Louer une machine dédiée dans un centre de données <em>(datacenter)</em> ;</li>
<li>Acheter un serveur doccasion ;</li>
<li>Acheter son propre serveur neuf ;</li>
<li>Utiliser son ordinateur personnel.</li>
</ol>
<h2 id="la-location">La location</h2>
<p>La première possibilité <em>(cloud)</em> est intéressante pour une courte durée (de quelques heures à quelques jours).
La seconde est celle dune machine dédiée, cest-à-dire dune machine physique. Cette possibilité est plus avantageuse si la machine est utilisée plusieurs mois.</p>
<p>Exemple de prix pour une machine avec SSD 2 To :</p>
<ol>
<li>1112 €/mois pour AWS m5a.8xlarge (16 cœurs 2,5 GHz + RAM 128 Go)</li>
<li>  235 €/mois pour Online Core-5-S (20 cœurs 2,2 GHz + RAM 128 Go)</li>
</ol>
<p>Pour 6 mois dutilisation, nous avons les ratios suivant :</p>
<ol>
<li>417 €/cœur</li>
<li>  70 €/cœur</li>
</ol>
<p>Personnellement, je ne suis pas (encore) à laise à déboguer sur un serveur distant, je préfère avoir la machine physiquement à côté de moi. Apparemment, <a href="https://developers.facebook.com/blog/post/2019/11/19/facebook-microsoft-partnering-remote-development/?_fb_noscript=1">Facebook contribue à Visual Studio Code</a> afin de permettre de travailler à distance. Si vous le faite déjà, je veux bien avoir vos conseils dans les commentaires, merci.</p>
<h2 id="serveur-doccasion">Serveur doccasion</h2>
<p>Les petites annonces, comme sur leboncoin par exemple, proposent des serveurs doccasion, souvent vieux de plus de 5 ans, mais à des tarifs qui peuvent être intéressants. On peut même y trouver des serveurs pour <a href="https://fr.wikipedia.org/wiki/Baie_(centre_de_données)">baie</a> <em>(rack)</em>.</p>
<p>Je ne suis pas familier avec les serveurs au format 1U, 2U et 4U. Mais si vous avez lhabitude den installer, merci de partager vos conseils dans les commentaires, ils seront les bienvenus. :-)</p>
<h2 id="serveur-neuf">Serveur neuf</h2>
<p>Acheter du neuf est intéressant si on a vraiment besoin des technologies récentes.
Il se peut aussi les produits proposés en occasion ne correspondent pas à nos besoins, où à des prix moins intéressant que le neuf à performance égale.</p>
<table>
<thead>
<tr>
<th style="text-align: right">Prix</th>
<th>Processeur (cœurs)</th>
<th style="text-align: right">Stockage</th>
<th style="text-align: right">Ratio</th>
<th style="text-align: right">RAM</th>
<th style="text-align: right">SSD + HDD</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: right">800 </td>
<td>Ryzen 7 2700 (8)</td>
<td style="text-align: right">2To HDD</td>
<td style="text-align: right">55€/cœur</td>
<td style="text-align: right">4Go/cœur</td>
<td style="text-align: right">312Go/cœur</td>
</tr>
<tr>
<td style="text-align: right">2500 $</td>
<td>Ryzem 9 3900X (12)</td>
<td style="text-align: right">20To HDD</td>
<td style="text-align: right">100$/cœur</td>
<td style="text-align: right">3Go/cœur</td>
<td style="text-align: right">1700Go/cœur</td>
</tr>
<tr>
<td style="text-align: right">6240$</td>
<td>ThunderX ARMv8 2GHz (96)</td>
<td style="text-align: right">500 Go SSD</td>
<td style="text-align: right">65$/cœur</td>
<td style="text-align: right">1Go/cœur</td>
<td style="text-align: right">5Go/cœur</td>
</tr>
</tbody>
</table>
<h2 id="ordinateur-portable">Ordinateur portable</h2>
<p>La plupart des portables avec un gros processeur sont des portables pour <em>gamer</em> avec aussi de grandes capacités graphiques. Trouver un ordinateur portable de dév. sans Windows, sans carte graphique et sans processeur Intel, est un vrai challenge. Comment faites-vous ?</p>
<p>Par contre, si votre employeur achète des portables pour y installer GNU/Linux, vous pourriez le convaincre dacheter ces portables sans Windows, notamment via les boutiques suivantes :</p>
<ul>
<li>http://shop.ekimia.fr/</li>
<li>https://keynux.com/</li>
<li>https://pcubuntoo.fr/</li>
<li>https://www.ldlc-pro.com/ordinateurs/pc-portable/c5376/+fv403-937,5085,6718,15416.html</li>
<li>https://pilot.search.dell.com/laptops/9964/laptops</li>
</ul>
<p>Consulter aussi la liste des bons constructeurs et vendeurs dordinateurs :</p>
<ul>
<li>https://bons-constructeurs-ordinateurs.info/</li>
<li>https://bons-vendeurs-ordinateurs.info/</li>
</ul>
<h1 id="conseils-et-suggestions">Conseils et suggestions</h1>
<p>Merci de méclairer ma lanterne avec des astuces. :-D</p>
</div>
<div class="d-print-none"><footer class="article__footer"><meta itemprop="dateModified" content="2019-12-25T00:00:00+01:00"><!-- start custom article footer snippet -->
<!-- end custom article footer snippet -->
<!--
<div align="right"><a type="application/rss+xml" href="/feed.xml" title="S'abonner"><i class="fa fa-rss fa-2x"></i></a>
&emsp;</div>
-->
</footer>
<div class="article__section-navigator clearfix"><div class="previous"><span>PRÉCÉDENT</span><a href="/2019/12/25/installer-debian-9-2-1-stretch-depuis-le-disque-dur-avec-une-image-iso-et-grub2-sans-cle-usb-ni-dvd.html">installer-debian-9-2-1-stretch-depuis-le-disque-dur-avec-une-image-iso-et-grub2-sans-cle-usb-ni-dvd</a></div><div class="next"><span>SUIVANT</span><a href="/2019/12/25/ldap-Getting_started_with_OpenLDAP.html">ldap-Getting started with OpenLDAP</a></div></div></div>
</div>
<script>(function() {
var SOURCES = window.TEXT_VARIABLES.sources;
window.Lazyload.js(SOURCES.jquery, function() {
$(function() {
var $this ,$scroll;
var $articleContent = $('.js-article-content');
var hasSidebar = $('.js-page-root').hasClass('layout--page--sidebar');
var scroll = hasSidebar ? '.js-page-main' : 'html, body';
$scroll = $(scroll);
$articleContent.find('.highlight').each(function() {
$this = $(this);
$this.attr('data-lang', $this.find('code').attr('data-lang'));
});
$articleContent.find('h1[id], h2[id], h3[id], h4[id], h5[id], h6[id]').each(function() {
$this = $(this);
$this.append($('<a class="anchor d-print-none" aria-hidden="true"></a>').html('<i class="fas fa-anchor"></i>'));
});
$articleContent.on('click', '.anchor', function() {
$scroll.scrollToAnchor('#' + $(this).parent().attr('id'), 400);
});
});
});
})();
</script>
</div><section class="page__comments d-print-none"></section></article><!-- start custom main bottom snippet -->
<!-- end custom main bottom snippet -->
</div>
</div></div></div></div>
</div><script>(function() {
var SOURCES = window.TEXT_VARIABLES.sources;
window.Lazyload.js(SOURCES.jquery, function() {
var $body = $('body'), $window = $(window);
var $pageRoot = $('.js-page-root'), $pageMain = $('.js-page-main');
var activeCount = 0;
function modal(options) {
var $root = this, visible, onChange, hideWhenWindowScroll = false;
var scrollTop;
function setOptions(options) {
var _options = options || {};
visible = _options.initialVisible === undefined ? false : show;
onChange = _options.onChange;
hideWhenWindowScroll = _options.hideWhenWindowScroll;
}
function init() {
setState(visible);
}
function setState(isShow) {
if (isShow === visible) {
return;
}
visible = isShow;
if (visible) {
activeCount++;
scrollTop = $(window).scrollTop() || $pageMain.scrollTop();
$root.addClass('modal--show');
$pageMain.scrollTop(scrollTop);
activeCount === 1 && ($pageRoot.addClass('show-modal'), $body.addClass('of-hidden'));
hideWhenWindowScroll && window.hasEvent('touchstart') && $window.on('scroll', hide);
$window.on('keyup', handleKeyup);
} else {
activeCount > 0 && activeCount--;
$root.removeClass('modal--show');
$window.scrollTop(scrollTop);
activeCount === 0 && ($pageRoot.removeClass('show-modal'), $body.removeClass('of-hidden'));
hideWhenWindowScroll && window.hasEvent('touchstart') && $window.off('scroll', hide);
$window.off('keyup', handleKeyup);
}
onChange && onChange(visible);
}
function show() {
setState(true);
}
function hide() {
setState(false);
}
function handleKeyup(e) {
// Char Code: 27 ESC
if (e.which === 27) {
hide();
}
}
setOptions(options);
init();
return {
show: show,
hide: hide,
$el: $root
};
}
$.fn.modal = modal;
});
})();
</script><div class="modal modal--overflow page__search-modal d-print-none js-page-search-modal"><script>
(function () {
var SOURCES = window.TEXT_VARIABLES.sources;
window.Lazyload.js(SOURCES.jquery, function() {
// search panel
var search = (window.search || (window.search = {}));
var useDefaultSearchBox = window.useDefaultSearchBox === undefined ?
true : window.useDefaultSearchBox ;
var $searchModal = $('.js-page-search-modal');
var $searchToggle = $('.js-search-toggle');
var searchModal = $searchModal.modal({ onChange: handleModalChange, hideWhenWindowScroll: true });
var modalVisible = false;
search.searchModal = searchModal;
var $searchBox = null;
var $searchInput = null;
var $searchClear = null;
function getModalVisible() {
return modalVisible;
}
search.getModalVisible = getModalVisible;
function handleModalChange(visible) {
modalVisible = visible;
if (visible) {
search.onShow && search.onShow();
useDefaultSearchBox && $searchInput[0] && $searchInput[0].focus();
} else {
search.onShow && search.onHide();
useDefaultSearchBox && $searchInput[0] && $searchInput[0].blur();
setTimeout(function() {
useDefaultSearchBox && ($searchInput.val(''), $searchBox.removeClass('not-empty'));
search.clear && search.clear();
window.pageAsideAffix && window.pageAsideAffix.refresh();
}, 400);
}
}
$searchToggle.on('click', function() {
modalVisible ? searchModal.hide() : searchModal.show();
});
// Char Code: 83 S, 191 /
$(window).on('keyup', function(e) {
if (!modalVisible && !window.isFormElement(e.target || e.srcElement) && (e.which === 83 || e.which === 191)) {
modalVisible || searchModal.show();
}
});
if (useDefaultSearchBox) {
$searchBox = $('.js-search-box');
$searchInput = $searchBox.children('input');
$searchClear = $searchBox.children('.js-icon-clear');
search.getSearchInput = function() {
return $searchInput.get(0);
};
search.getVal = function() {
return $searchInput.val();
};
search.setVal = function(val) {
$searchInput.val(val);
};
$searchInput.on('focus', function() {
$(this).addClass('focus');
});
$searchInput.on('blur', function() {
$(this).removeClass('focus');
});
$searchInput.on('input', window.throttle(function() {
var val = $(this).val();
if (val === '' || typeof val !== 'string') {
search.clear && search.clear();
} else {
$searchBox.addClass('not-empty');
search.onInputNotEmpty && search.onInputNotEmpty(val);
}
}, 400));
$searchClear.on('click', function() {
$searchInput.val(''); $searchBox.removeClass('not-empty');
search.clear && search.clear();
});
}
});
})();
</script><div class="search search--dark">
<div class="main">
<div class="search__header">Recherche</div>
<div class="search-bar">
<div class="search-box js-search-box">
<div class="search-box__icon-search"><i class="fas fa-search"></i></div>
<input id="search-input" type="text" />
<div class="search-box__icon-clear js-icon-clear">
<a><i class="fas fa-times"></i></a>
</div>
</div>
<button class="button button--theme-dark button--pill search__cancel js-search-toggle">
Annuler</button>
</div>
<div id="results-container" class="search-result js-search-result"></div>
</div>
</div>
<!-- Script pointing to search-script.js -->
<script>/*!
* Simple-Jekyll-Search
* Copyright 2015-2020, Christian Fei
* Licensed under the MIT License.
*/
(function(){
'use strict'
var _$Templater_7 = {
compile: compile,
setOptions: setOptions
}
const options = {}
options.pattern = /\{(.*?)\}/g
options.template = ''
options.middleware = function () {}
function setOptions (_options) {
options.pattern = _options.pattern || options.pattern
options.template = _options.template || options.template
if (typeof _options.middleware === 'function') {
options.middleware = _options.middleware
}
}
function compile (data) {
return options.template.replace(options.pattern, function (match, prop) {
const value = options.middleware(prop, data[prop], options.template)
if (typeof value !== 'undefined') {
return value
}
return data[prop] || match
})
}
'use strict';
function fuzzysearch (needle, haystack) {
var tlen = haystack.length;
var qlen = needle.length;
if (qlen > tlen) {
return false;
}
if (qlen === tlen) {
return needle === haystack;
}
outer: for (var i = 0, j = 0; i < qlen; i++) {
var nch = needle.charCodeAt(i);
while (j < tlen) {
if (haystack.charCodeAt(j++) === nch) {
continue outer;
}
}
return false;
}
return true;
}
var _$fuzzysearch_1 = fuzzysearch;
'use strict'
/* removed: const _$fuzzysearch_1 = require('fuzzysearch') */;
var _$FuzzySearchStrategy_5 = new FuzzySearchStrategy()
function FuzzySearchStrategy () {
this.matches = function (string, crit) {
return _$fuzzysearch_1(crit.toLowerCase(), string.toLowerCase())
}
}
'use strict'
var _$LiteralSearchStrategy_6 = new LiteralSearchStrategy()
function LiteralSearchStrategy () {
this.matches = function (str, crit) {
if (!str) return false
str = str.trim().toLowerCase()
crit = crit.trim().toLowerCase()
return crit.split(' ').filter(function (word) {
return str.indexOf(word) >= 0
}).length === crit.split(' ').length
}
}
'use strict'
var _$Repository_4 = {
put: put,
clear: clear,
search: search,
setOptions: __setOptions_4
}
/* removed: const _$FuzzySearchStrategy_5 = require('./SearchStrategies/FuzzySearchStrategy') */;
/* removed: const _$LiteralSearchStrategy_6 = require('./SearchStrategies/LiteralSearchStrategy') */;
function NoSort () {
return 0
}
const data = []
let opt = {}
opt.fuzzy = false
opt.limit = 10
opt.searchStrategy = opt.fuzzy ? _$FuzzySearchStrategy_5 : _$LiteralSearchStrategy_6
opt.sort = NoSort
opt.exclude = []
function put (data) {
if (isObject(data)) {
return addObject(data)
}
if (isArray(data)) {
return addArray(data)
}
return undefined
}
function clear () {
data.length = 0
return data
}
function isObject (obj) {
return Boolean(obj) && Object.prototype.toString.call(obj) === '[object Object]'
}
function isArray (obj) {
return Boolean(obj) && Object.prototype.toString.call(obj) === '[object Array]'
}
function addObject (_data) {
data.push(_data)
return data
}
function addArray (_data) {
const added = []
clear()
for (let i = 0, len = _data.length; i < len; i++) {
if (isObject(_data[i])) {
added.push(addObject(_data[i]))
}
}
return added
}
function search (crit) {
if (!crit) {
return []
}
return findMatches(data, crit, opt.searchStrategy, opt).sort(opt.sort)
}
function __setOptions_4 (_opt) {
opt = _opt || {}
opt.fuzzy = _opt.fuzzy || false
opt.limit = _opt.limit || 10
opt.searchStrategy = _opt.fuzzy ? _$FuzzySearchStrategy_5 : _$LiteralSearchStrategy_6
opt.sort = _opt.sort || NoSort
opt.exclude = _opt.exclude || []
}
function findMatches (data, crit, strategy, opt) {
const matches = []
for (let i = 0; i < data.length && matches.length < opt.limit; i++) {
const match = findMatchesInObject(data[i], crit, strategy, opt)
if (match) {
matches.push(match)
}
}
return matches
}
function findMatchesInObject (obj, crit, strategy, opt) {
for (const key in obj) {
if (!isExcluded(obj[key], opt.exclude) && strategy.matches(obj[key], crit)) {
return obj
}
}
}
function isExcluded (term, excludedTerms) {
for (let i = 0, len = excludedTerms.length; i < len; i++) {
const excludedTerm = excludedTerms[i]
if (new RegExp(excludedTerm).test(term)) {
return true
}
}
return false
}
/* globals ActiveXObject:false */
'use strict'
var _$JSONLoader_2 = {
load: load
}
function load (location, callback) {
const xhr = getXHR()
xhr.open('GET', location, true)
xhr.onreadystatechange = createStateChangeListener(xhr, callback)
xhr.send()
}
function createStateChangeListener (xhr, callback) {
return function () {
if (xhr.readyState === 4 && xhr.status === 200) {
try {
callback(null, JSON.parse(xhr.responseText))
} catch (err) {
callback(err, null)
}
}
}
}
function getXHR () {
return window.XMLHttpRequest ? new window.XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP')
}
'use strict'
var _$OptionsValidator_3 = function OptionsValidator (params) {
if (!validateParams(params)) {
throw new Error('-- OptionsValidator: required options missing')
}
if (!(this instanceof OptionsValidator)) {
return new OptionsValidator(params)
}
const requiredOptions = params.required
this.getRequiredOptions = function () {
return requiredOptions
}
this.validate = function (parameters) {
const errors = []
requiredOptions.forEach(function (requiredOptionName) {
if (typeof parameters[requiredOptionName] === 'undefined') {
errors.push(requiredOptionName)
}
})
return errors
}
function validateParams (params) {
if (!params) {
return false
}
return typeof params.required !== 'undefined' && params.required instanceof Array
}
}
'use strict'
var _$utils_9 = {
merge: merge,
isJSON: isJSON
}
function merge (defaultParams, mergeParams) {
const mergedOptions = {}
for (const option in defaultParams) {
mergedOptions[option] = defaultParams[option]
if (typeof mergeParams[option] !== 'undefined') {
mergedOptions[option] = mergeParams[option]
}
}
return mergedOptions
}
function isJSON (json) {
try {
if (json instanceof Object && JSON.parse(JSON.stringify(json))) {
return true
}
return false
} catch (err) {
return false
}
}
var _$src_8 = {};
(function (window) {
'use strict'
let options = {
searchInput: null,
resultsContainer: null,
json: [],
success: Function.prototype,
searchResultTemplate: '<li><a href="{url}" title="{desc}">{title}</a></li>',
templateMiddleware: Function.prototype,
sortMiddleware: function () {
return 0
},
noResultsText: 'No results found',
limit: 10,
fuzzy: false,
debounceTime: null,
exclude: []
}
let debounceTimerHandle
const debounce = function (func, delayMillis) {
if (delayMillis) {
clearTimeout(debounceTimerHandle)
debounceTimerHandle = setTimeout(func, delayMillis)
} else {
func.call()
}
}
const requiredOptions = ['searchInput', 'resultsContainer', 'json']
/* removed: const _$Templater_7 = require('./Templater') */;
/* removed: const _$Repository_4 = require('./Repository') */;
/* removed: const _$JSONLoader_2 = require('./JSONLoader') */;
const optionsValidator = _$OptionsValidator_3({
required: requiredOptions
})
/* removed: const _$utils_9 = require('./utils') */;
window.SimpleJekyllSearch = function (_options) {
const errors = optionsValidator.validate(_options)
if (errors.length > 0) {
throwError('You must specify the following required options: ' + requiredOptions)
}
options = _$utils_9.merge(options, _options)
_$Templater_7.setOptions({
template: options.searchResultTemplate,
middleware: options.templateMiddleware
})
_$Repository_4.setOptions({
fuzzy: options.fuzzy,
limit: options.limit,
sort: options.sortMiddleware,
exclude: options.exclude
})
if (_$utils_9.isJSON(options.json)) {
initWithJSON(options.json)
} else {
initWithURL(options.json)
}
const rv = {
search: search
}
typeof options.success === 'function' && options.success.call(rv)
return rv
}
function initWithJSON (json) {
_$Repository_4.put(json)
registerInput()
}
function initWithURL (url) {
_$JSONLoader_2.load(url, function (err, json) {
if (err) {
throwError('failed to get JSON (' + url + ')')
}
initWithJSON(json)
})
}
function emptyResultsContainer () {
options.resultsContainer.innerHTML = ''
}
function appendToResultsContainer (text) {
options.resultsContainer.innerHTML += text
}
function registerInput () {
options.searchInput.addEventListener('input', function (e) {
if (isWhitelistedKey(e.which)) {
emptyResultsContainer()
debounce(function () { search(e.target.value) }, options.debounceTime)
}
})
}
function search (query) {
if (isValidQuery(query)) {
emptyResultsContainer()
render(_$Repository_4.search(query), query)
}
}
function render (results, query) {
const len = results.length
if (len === 0) {
return appendToResultsContainer(options.noResultsText)
}
for (let i = 0; i < len; i++) {
results[i].query = query
appendToResultsContainer(_$Templater_7.compile(results[i]))
}
}
function isValidQuery (query) {
return query && query.length > 0
}
function isWhitelistedKey (key) {
return [13, 16, 20, 37, 38, 39, 40, 91].indexOf(key) === -1
}
function throwError (message) {
throw new Error('SimpleJekyllSearch --- ' + message)
}
})(window)
}());
</script>
<!-- Configuration -->
<script>
SimpleJekyllSearch({
searchInput: document.getElementById('search-input'),
resultsContainer: document.getElementById('results-container'),
noResultsText: '<p>Aucun résultat!</p>',
json: '/search.json',
searchResultTemplate: '<li><a href="{url}">{date}&nbsp;{title}</a>&nbsp;(Création {create})</li>'
})
</script>
</div></div>
<script>(function() {
var SOURCES = window.TEXT_VARIABLES.sources;
window.Lazyload.js(SOURCES.jquery, function() {
function scrollToAnchor(anchor, duration, callback) {
var $root = this;
$root.animate({ scrollTop: $(anchor).position().top }, duration, function() {
window.history.replaceState(null, '', window.location.href.split('#')[0] + anchor);
callback && callback();
});
}
$.fn.scrollToAnchor = scrollToAnchor;
});
})();
(function() {
var SOURCES = window.TEXT_VARIABLES.sources;
window.Lazyload.js(SOURCES.jquery, function() {
function affix(options) {
var $root = this, $window = $(window), $scrollTarget, $scroll,
offsetBottom = 0, scrollTarget = window, scroll = window.document, disabled = false, isOverallScroller = true,
rootTop, rootLeft, rootHeight, scrollBottom, rootBottomTop,
hasInit = false, curState;
function setOptions(options) {
var _options = options || {};
_options.offsetBottom && (offsetBottom = _options.offsetBottom);
_options.scrollTarget && (scrollTarget = _options.scrollTarget);
_options.scroll && (scroll = _options.scroll);
_options.disabled !== undefined && (disabled = _options.disabled);
$scrollTarget = $(scrollTarget);
isOverallScroller = window.isOverallScroller($scrollTarget[0]);
$scroll = $(scroll);
}
function preCalc() {
top();
rootHeight = $root.outerHeight();
rootTop = $root.offset().top + (isOverallScroller ? 0 : $scrollTarget.scrollTop());
rootLeft = $root.offset().left;
}
function calc(needPreCalc) {
needPreCalc && preCalc();
scrollBottom = $scroll.outerHeight() - offsetBottom - rootHeight;
rootBottomTop = scrollBottom - rootTop;
}
function top() {
if (curState !== 'top') {
$root.removeClass('fixed').css({
left: 0,
top: 0
});
curState = 'top';
}
}
function fixed() {
if (curState !== 'fixed') {
$root.addClass('fixed').css({
left: rootLeft + 'px',
top: 0
});
curState = 'fixed';
}
}
function bottom() {
if (curState !== 'bottom') {
$root.removeClass('fixed').css({
left: 0,
top: rootBottomTop + 'px'
});
curState = 'bottom';
}
}
function setState() {
var scrollTop = $scrollTarget.scrollTop();
if (scrollTop >= rootTop && scrollTop <= scrollBottom) {
fixed();
} else if (scrollTop < rootTop) {
top();
} else {
bottom();
}
}
function init() {
if(!hasInit) {
var interval, timeout;
calc(true); setState();
// run calc every 100 millisecond
interval = setInterval(function() {
calc();
}, 100);
timeout = setTimeout(function() {
clearInterval(interval);
}, 45000);
window.pageLoad.then(function() {
setTimeout(function() {
clearInterval(interval);
clearTimeout(timeout);
}, 3000);
});
$scrollTarget.on('scroll', function() {
disabled || setState();
});
$window.on('resize', function() {
disabled || (calc(true), setState());
});
hasInit = true;
}
}
setOptions(options);
if (!disabled) {
init();
}
$window.on('resize', window.throttle(function() {
init();
}, 200));
return {
setOptions: setOptions,
refresh: function() {
calc(true, { animation: false }); setState();
}
};
}
$.fn.affix = affix;
});
})();
(function() {
var SOURCES = window.TEXT_VARIABLES.sources;
window.Lazyload.js(SOURCES.jquery, function() {
function toc(options) {
var $root = this, $window = $(window), $scrollTarget, $scroller, $tocUl = $('<ul class="toc toc--ellipsis"></ul>'), $tocLi, $headings, $activeLast, $activeCur,
selectors = 'h1,h2,h3', container = 'body', scrollTarget = window, scroller = 'html, body', disabled = false,
headingsPos, scrolling = false, hasRendered = false, hasInit = false;
function setOptions(options) {
var _options = options || {};
_options.selectors && (selectors = _options.selectors);
_options.container && (container = _options.container);
_options.scrollTarget && (scrollTarget = _options.scrollTarget);
_options.scroller && (scroller = _options.scroller);
_options.disabled !== undefined && (disabled = _options.disabled);
$headings = $(container).find(selectors).filter('[id]');
$scrollTarget = $(scrollTarget);
$scroller = $(scroller);
}
function calc() {
headingsPos = [];
$headings.each(function() {
headingsPos.push(Math.floor($(this).position().top));
});
}
function setState(element, disabled) {
var scrollTop = $scrollTarget.scrollTop(), i;
if (disabled || !headingsPos || headingsPos.length < 1) { return; }
if (element) {
$activeCur = element;
} else {
for (i = 0; i < headingsPos.length; i++) {
if (scrollTop >= headingsPos[i]) {
$activeCur = $tocLi.eq(i);
} else {
$activeCur || ($activeCur = $tocLi.eq(i));
break;
}
}
}
$activeLast && $activeLast.removeClass('active');
($activeLast = $activeCur).addClass('active');
}
function render() {
if(!hasRendered) {
$root.append($tocUl);
$headings.each(function() {
var $this = $(this);
$tocUl.append($('<li></li>').addClass('toc-' + $this.prop('tagName').toLowerCase())
.append($('<a></a>').text($this.text()).attr('href', '#' + $this.prop('id'))));
});
$tocLi = $tocUl.children('li');
$tocUl.on('click', 'a', function(e) {
e.preventDefault();
var $this = $(this);
scrolling = true;
setState($this.parent());
$scroller.scrollToAnchor($this.attr('href'), 400, function() {
scrolling = false;
});
});
}
hasRendered = true;
}
function init() {
var interval, timeout;
if(!hasInit) {
render(); calc(); setState(null, scrolling);
// run calc every 100 millisecond
interval = setInterval(function() {
calc();
}, 100);
timeout = setTimeout(function() {
clearInterval(interval);
}, 45000);
window.pageLoad.then(function() {
setTimeout(function() {
clearInterval(interval);
clearTimeout(timeout);
}, 3000);
});
$scrollTarget.on('scroll', function() {
disabled || setState(null, scrolling);
});
$window.on('resize', window.throttle(function() {
if (!disabled) {
render(); calc(); setState(null, scrolling);
}
}, 100));
}
hasInit = true;
}
setOptions(options);
if (!disabled) {
init();
}
$window.on('resize', window.throttle(function() {
init();
}, 200));
return {
setOptions: setOptions
};
}
$.fn.toc = toc;
});
})();
/*(function () {
})();*/
</script><script>
/* toc must before affix, since affix need to konw toc' height. */(function() {
var SOURCES = window.TEXT_VARIABLES.sources;
var TOC_SELECTOR = window.TEXT_VARIABLES.site.toc.selectors;
window.Lazyload.js(SOURCES.jquery, function() {
var $window = $(window);
var $articleContent = $('.js-article-content');
var $tocRoot = $('.js-toc-root'), $col2 = $('.js-col-aside');
var toc;
var tocDisabled = false;
var hasSidebar = $('.js-page-root').hasClass('layout--page--sidebar');
var hasToc = $articleContent.find(TOC_SELECTOR).length > 0;
function disabled() {
return $col2.css('display') === 'none' || !hasToc;
}
tocDisabled = disabled();
toc = $tocRoot.toc({
selectors: TOC_SELECTOR,
container: $articleContent,
scrollTarget: hasSidebar ? '.js-page-main' : null,
scroller: hasSidebar ? '.js-page-main' : null,
disabled: tocDisabled
});
$window.on('resize', window.throttle(function() {
tocDisabled = disabled();
toc && toc.setOptions({
disabled: tocDisabled
});
}, 100));
});
})();
(function() {
var SOURCES = window.TEXT_VARIABLES.sources;
window.Lazyload.js(SOURCES.jquery, function() {
var $window = $(window), $pageFooter = $('.js-page-footer');
var $pageAside = $('.js-page-aside');
var affix;
var tocDisabled = false;
var hasSidebar = $('.js-page-root').hasClass('layout--page--sidebar');
affix = $pageAside.affix({
offsetBottom: $pageFooter.outerHeight(),
scrollTarget: hasSidebar ? '.js-page-main' : null,
scroller: hasSidebar ? '.js-page-main' : null,
scroll: hasSidebar ? $('.js-page-main').children() : null,
disabled: tocDisabled
});
$window.on('resize', window.throttle(function() {
affix && affix.setOptions({
disabled: tocDisabled
});
}, 100));
window.pageAsideAffix = affix;
});
})();
</script><!---->
</div>
<script>(function () {
var $root = document.getElementsByClassName('root')[0];
if (window.hasEvent('touchstart')) {
$root.dataset.isTouch = true;
document.addEventListener('touchstart', function(){}, false);
}
})();
</script>
</body>
</html>