Оптимизация веб-производительности: сократите загрузку контента и улучшите скорость ответа страницы.
Оптимизация веб-производительности: сократите загрузку контента и улучшите скорость ответа страницы.

введение

Оптимизация производительности веб-сайтов была распространенной темой в сообществе. В сообществе есть много отличных статей, посвященных методам оптимизации, таким как сильное сжатие, предварительная загрузка и распаковка статических ресурсов, таких как Css и Js.

Однако узкое место в производительности большинства сайтов веб-приложений обычно связано с большим количеством запросов на взаимодействие с данными в дополнение к загрузке статических ресурсов. Если мы хотим, чтобы наш веб-сайт был удобным для пользователей, помимо оптимизации статических ресурсов, необходима оптимизация взаимодействия с данными.

Сегодняшняя статья позволяет нам начать с другой точки зрения и поговорить о том, как улучшить взаимодействие с пользователем вашего сайта веб-приложения на уровне взаимодействия с данными.

фон

Прежде всего, прежде чем приступить к основному содержанию, давайте поговорим с вами о том, что такое «оптимизация производительности веб-сайта на уровне запроса данных».

Что такое «время загрузки ресурса»

Проще говоря, традиционные веб-страницы имеют несколько различных этапов инициирования запроса:

Если вам интересно узнать каждогоиндивидуальный Полеиз Вы можете уточнить значениекссылкаTiming breakdown phases explained

Здесь мы сосредоточимся на двух частях:

  • Waiting for server response: аббревиатура TTFB представляет собой время, в течение которого браузер ожидает ответа при получении первого ответа от сервера.
  • Загрузка контента: Как следует из названия, это время загрузки контента при передаче по сети.

Ожидание ответа сервера (TTFB) представляет собой время, необходимое серверу для обработки этого запроса. Как интерфейсному инженеру, оптимизация этой части времени часто должна выполняться совместно с соответствующим сервером.

Загрузка контента — это время загрузки ресурса, которое мы подчеркнули в заголовке. Оно представляет собой продолжительность времени, в течение которого браузер загружает данные ответа службы при этой сетевой передаче.

Нетрудно представить, что, будь то TTFB или загрузка контента, если мы максимально сократим время передачи этого запроса в ссылке запроса, элементы отображения страницы, которые полагаются на эту часть данных, будут представляется пользователю быстрее.

Нужно ли оптимизировать «загрузку ресурсов»?

Часто, когда мы открываем веб-сайт, время загрузки традиционных ресурсов приложения/json обычно находится в пределах 100 мс.

«Мой интерфейс реагирует очень быстро, так не нужно ли мне его оптимизировать?» Я думаю, большинство студентов зададутся вопросом, важен ли опыт оптимизации в 100 мс?

Обычно время передачи данных через Интернет обратно пропорционально фактической пропускной способности пользователя. Когда пропускная способность пользователя выше, скорость передачи данных увеличивается, и время загрузки соответственно сокращается. При более низкой пропускной способности скорость передачи данных снизится, что приведет к увеличению времени загрузки страниц.

Это означает, что оптимизация IOI для загрузки ресурсов не так уж важна, если у пользователя хорошая сеть. Но мы никогда не можем просить пользователей пойти на компромисс в отношении пропускной способности нашего веб-сайта.

Чаще всего так называемый метод оптимизации означает, что, когда разные группы конечных пользователей посещают наш веб-сайт, они надеются получить быструю обратную связь от страниц. Если мы оптимизируем производительность веб-сайта только для пользователей с хорошим оборудованием и сетями, это будет успешным. пустая трата времени. Давление, связанное с медленным доступом к веб-сайту, переносится с разработчиков на пользователей.

Следовательно, это не означает, что короткое время загрузки ресурса при бесперебойной сети означает, что мы отказываемся от его оптимизации. Более того, студенты, знакомые с фронтендом, обязательно столкнутся с некоторыми интерфейсами для передачи больших объемов данных и различными границами. плохой мобильной сети. Сцена правильная.

Web Streaming

концепция

привычный NodeJs одноклассники для Streaming изконцепция должна быть вам знакома,существовать Web Среда выполнения также предоставляет набор Stream API позволять JavaScript Возможность доступа к потокам данных из сети.

При передаче по сети HTTP2 Передача данных через уровень двоичного кадрирования поддерживается по умолчанию при передаче данных по сети. Streaming способ прочитать ответ, в HTTP 1.1 Мы можем установить Transfer-Encoding: chunked Заголовок ответа указывает, что «лучшее» передается в формате фрагментов данных.

Проще говоря, Streams API позволяет нам программно получать доступ к потокам данных, получаемым по сети, посредством JavaScript, при этом настраивая обработку возвращаемых потоков данных в соответствии с собственными потребностями.

  1. обработка данных в реальном времени:когдаданныеккусокиз Когда придет форма,Не нужно ждать полногоиндивидуальный Полезная нагрузка может быть обработана。Это можетк Значительно улучшеноданныеизгрузоподъемностьа Также медленное сетевое соединение из-за воспринимаемой производительности.
  2. Детальный контроль:Web Streaming Позволяет нам контролировать, как данные считываются и обрабатываются в соответствии с конкретными потребностями и сценариями.

Здесь мы в основном фокусируемся на ReadableStream а также WritableStream

о Streaming Для получения подробной информации и использования вы можете обратиться к MDN - Web Streaming или Vercel - An Introduction to Streaming on the Web

ReadableStream/WritableStream Пример

  • ReadableStream предоставляет возможности асинхронного чтения.
  • WritableStream Предоставлено для Воли Streaming данные о назначении записи из возможности.

Давайте посмотриминдивидуальныйо ReadableStream а также WritableStream Простой пример:

Язык кода:javascript
копировать
const decoder = new TextDecoder();
const encoder = new TextEncoder();

// Создайте читаемый поток
const readableStream = new ReadableStream({
  // Когда будет создан читаемый поток, он будет выполнен немедленно, и читаемый поток будет поставлен в очередь через метод доступа для Whenfront, когда text
  start(controller) {
    const text = 'hello, Welcome to flow my Github: 19Qingfeng.';
    controller.enqueue(encoder.encode(text));
    controller.close();
  }
});

// Создайте отдельный записываемый поток
const writableStream = new WritableStream({
  // Каждый раз есть что-то новое chunk Доступный для записи поток создается, когда он готов к записи. write метод
  write(chunk) {
    console.log(decoder.decode(chunk));
  }
});

readableStream.pipeTo(writableStream); // hello, Welcome to flow my Github: 19Qingfeng.

В приведенном выше коде мы передаем TextEncoder Воля hello, Welcome to flow my Github: 19Qingfeng. преобразован в stream отисуществоватьсоздавать Читабельный поток Воляон врезается в поток。

В то же время позже мы создали writableStream Записываемый объект потока, содержимое потока, доступное для чтения через pipeTo Перенос метода в записываемый поток.

writableStream Каждый раз будут новые chunk Срабатывает, когда готов к записи write метод, в write В методе,который мы использовали TextEncoder идти Воля stream Раскодируйте, и консоль естественным образом выведет hello, Welcome to flow my Github: 19Qingfeng

о WritableStream/ReadableStream изконцепцияа Также Углубленное использование: друзья, которым интересно узнать больше, могут проверить это самостоятельно. MDN Документация.

Web Fetch

концепция

API Fetch предоставляет интерфейс для получения ресурсов, а Web Fetch больше похож на замену XMLHttpRequest.

Fetch Ядро лежит в HTTP Абстракция интерфейса, включая Request,Response,Headers,Body,а также используется для инициализации асинхронных запросов из global fetch

Проще говоря, принеси Api предоставляет очень мощный набор Api Может кпозволять нам пройти JavaScript оперировать этими абстрактными HTTP модуль.

Основное использование

Обычно мы используем Fetch Api с файлом response.json для получения данных, полученных от интерфейса удаленной службы:

Язык кода:javascript
копировать
async function getUserJSON() {
  let url = 'https://api.github.com/users/19Qingfeng';
  try {
    let response = await fetch(url);
    return await response.json();
  } catch (error) {
    console.log('Request Failed', error);
  }
}

fetch Возвращаемое значение метода — это Promise<Response> объект, мы можем использовать fetch вернулся response в объекте json метод из Response Залезай json Форматированный ответ данных.

Streaming Fetch

На самом деле, принеси Api вернулся Response Есть еще один на body свойство.

Мы можем пройти назад response из body Недвижимость Получить индивидуальный ответ из ReadableStream Пример.

Это означает, что мы можем сразу прочитать содержимое ответа с помощью метода json, не дожидаясь загрузки всех ответов во время передачи по сети.

Вместо этого вы можете пройти response.body к методу ReadableStream для пакетного чтения данных из и для повышения скорости ответа данных интерфейса.

Чтение данных res.body напрямую

Далее давайте посмотрим, как использовать Fetch Response из body свойство.

Сначала мы используем экспресс для быстрого создания NodeServer для размещения серверного приложения:

Язык кода:javascript
копировать
// express код степени обслуживания
const express = require('express');
const data = require('./data.json');
const path = require('path');

const app = express();

app.use(express.static(path.resolve(__dirname, '../public')));

app.post('/api/data', (req, res) => {
  res.json(data);
});

app.listen(3000, () => {
  console.log('start server on 3000;');
});

здесь из ./data.json Вы можете разместить любой абзац json содержание.

В то же время нам также необходимо public Поместите один под html Файл взят со страницы отображения Также Выполнить клиентскую часть логики:

Язык кода:javascript
копировать
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <div id="root"></div>
  <script src="./index.js"></script>
</body>

</html>
Язык кода:javascript
копировать
// index.js
setTimeout(() => {
  fetchUserDataByStreaming();
}, 100);

async function fetchUserDataByStreaming() {
  const response = await fetch('/api/data', {
    method: 'post'
  });

  const body = response.body;
  // Получите читаемую программу чтения потоковых объектов.
  const reader = body.getReader();

  // создавать TextDecoder декодирование
  const textReader = new TextDecoder();

  function getValueFromReader() {
    reader.read().then((res) => {
      if (res.done) {
        console.log('reader done');
        return;
      }

      if (res.value) {
        const text = textReader.decode(res.value);
        const element = document.getElementById('root');
        element.innerHTML = element.innerHTML + text;

        console.log(textReader.decode(res.value));
        // Если он не закончился, продолжите вызов getValueFromReader Рекурсивное чтение fetch содержание
        getValueFromReader();
      }
    });
  }

  getValueFromReader();
}

В приведенной выше логике мы передаем Express Создал NodeServer, пока Создан /api/data из post интерфейс.

Доступ после запуска приложения localhost:3000 будет загружен позже html файлы, выполняемые одновременно ./index.js из клиентской логики.

Клиент будет внутри 100ms позвони после fetchUserDataByStreaming метод.

fetchUserDataByStreaming Есть несколько основных шагов:

  • Первое использование Fetch Api вызов NodeServer из /api/data интерфейс.
  • когда /api/data При ответе (HTTP Status Code для 200 ), мы будем использовать response.body Получите читаемый поток этого ответа.
  • После этого проходим body.getReader а также new TextDecoder Получен ответ, читаемый потоком объектов из средства чтения и декодирования.
  • наконец,существовать fetchUserDataByStreaming В нашем рекурсивном вызове getValueFromReader Заходите, Воля, реагируйте на возвращенные обновления на странице.

getReader() метод создаст reader,и Воля Stream блокировка. только текущий reader Воля Стрим вышел после других reader можно использовать. в то же время,getReader() Возвращаемое значение методиз используется точно так же, как и функция-генератор.

  • ReadableStream Если есть какие-либо chuck Доступно, вызов reader.read() вернулся promise буду использовать { value: chunk, done: false } done выражать stream Еще не конец, и value На этот раз там написано изсодержание.
  • ReadableStream Если оно закончилось (закрылось), вызовите reader.read() вернулся promise буду использовать { value: undefined, done: true } ,природа done Выразитьreadable закрыто.

Здесь мы напрямую используем res.body Волявернулсяданные безмозглый пропуск innerHTML добавлено на страницу.

На фото выше для Воля network Отрегулируйте slow 3g дело из performance frames。

Внимательные студенты, возможно, обнаружили, что дело обстоит иначе. XMLHTTPRequest изинтерфейс ожиданиясодержание Только после завершения всех загрузоккполучатьданныедругой。

Fetch Api из Response.body вернулся readableStream для Мы предоставляем доступныекшаг за шагомполучатьданныеи Не нужно ждать всехизсодержание Загрузка завершена。

объединить Freames Приходите и посмотрите,на страницеизсодержание Он отображается по частям.и Не прямо на одном экране Волясодержаниепровести грубыйиззаменять。

существования Если вы будете осторожны, то можете обнаружить, что на странице разбросано множество искаженных слов:

Фактически, это связано с тем, что по умолчанию TextDecoder анализирует Response.body в соответствии с кодировкой utf-8 (один байт представляет 8 бит).

существовать ReadableStream разделит данные в соответствии с минимальной единицей байтов и вызовет body.getReader() вернулся res.value для Uint8Array Тип: Uint8Array это автор 8 битовое беззнаковое целое число(Это одининдивидуальныйбайт)композицияизмножество。

Страница для написана на чистом английском языке (utf-8 Следующий код — индивидуальный английский дляодининдивидуальныйбайт), который, естественно, можно передать напрямую. TextDecoder При прямом чтении не будет искаженных символов.

Но на китайской сцене обычно существуют UTF-8 Китайцы будут оккупированы следующим 3 индивидуальныйбайт,грубыйизиспользовать TextDecoder идтидекодированиевернулся Uint8Array Может привести к частичному обрезанию индивидуального китайского иероглифа «Воляодинизмногобайт», uft-8. Кодировка не может распознать часть китайских иероглифов байт и природа, а также приводит к искажению символов.

Правила синтаксического анализа различных текстов в кодировке utf-8: проблема, нам нужно понять кодировку utf-8:

Проще говоря, utf-8 — это метод кодирования байтов переменной длины.

  • Для определенного индивидуального персонажа из utf-8 Кодировка, если имеется только один индивидуальныйбайт, то его старшая двоичная цифра 0。
  • Если это несколько байтов, то его первый индивидуальный байт начинается со старшего бита, а последующие из значений двоичных битов для 1 Число индивидуальных байтов определяет количество цифр в его кодировке, а остальные байты равны. 10 В начале, когдаран utf-8 Доступно до 6 индивидуальныйбайт。

байт

Пример

1байт

0xxxxxxx

2байт

110xxxxx 10xxxxxx

3байт

1110xxxx 10xxxxxx 10xxxxxx

4байт

11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

5байт

111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

6байт

1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

Это означает, что каждый раз существование читается stream Нам нужно опираться на Uint8Array из Хвост сам движется вперед, чтобы определить, можно ли из хвостового байта сформировать полноценного индивидуального utf-8 Кодируем, если есть возможность то вызываем TextDecoder руководитьдекодирование,если это невозможнокмы должнысуществовать На этот разиз stream Неполныйизбайт Сноваруководитьдекодирование Предотвратить искажение символов в браузере。

Проще говоря Мы можем согласно uft-8 из правил кодирования, Воля Uint8Array типпреобразован в двоичном формате определяет, соответствует ли хвостовой байт единственному индивидуальному символу из и.

Язык кода:javascript
копировать
setTimeout(() => {
  fetchUserDataByStreaming();
}, 100);

async function fetchUserDataByStreaming() {
  const response = await fetch('/api/data', {
    method: 'post'
  });

  const body = response.body;
  // Получить читаемый объект потока
  const reader = body.getReader();

  // создавать TextDecoder декодирование
  const textReader = new TextDecoder();
  // создаватьодининдивидуальный На этот разответизобщая ситуация buffer Используется для сохранения уже полученных изданных
  // Типдля Uint8Array[]
  let buffer = [];

  function getValueFromReader() {
    reader.read().then((res) => {
      if (res.done) {
        console.log('reader done');
        return;
      }

      if (res.value) {
        const chunk = res.value;
        // Воля Эти возвращаемые данные добавляются к возвращаемым данным
        buffer.push(chunk);
        // Отформатированный Uint8Array[] Получите полные изданные
        const completeBuffer = mergeArrays(...buffer);
        // Определите, нужно ли отбрасывать искаженные символы,получать На этот разможет быть полнымдекодированиеизданные
        const finallyBuffer = splitValidBuffer(completeBuffer);
        // декодирование
        const textBufferString = textReader.decode(finallyBuffer);

        const element = document.getElementById('root');
        // Заменить всю сумму
        element.innerHTML = textBufferString;
        // Если он не закончился, продолжите вызов getValueFromReader Рекурсивное чтение fetch содержание
        getValueFromReader();
      }
    });
  }

  getValueFromReader();
}

function splitValidBuffer(buffer) {
  const reg = /^1*/;
  let count = 0;
  let shouldCount = 0;

  for (let i = buffer.length - 1; i >= 0; i--) {
    const byte = buffer[i];
    // Волябайтпреобразован в двоичном формате
    const value = byte.toString(2).padStart(8, '0');
    // Определите, является ли этот байт частью для
    if (!`${value}`.startsWith('10')) {
      // Не для части
      shouldCount = `${value}`.match(reg)[0].length;
      break;
    } else {
      // Начало байт
      count++;
    }
  }

  if (shouldCount === count) {
    return buffer;
  } else {
    return buffer.slice(0, buffer.length - (count + 1));
  }
}

function mergeArrays(...arrays) {
  let out = new Uint8Array(
    arrays.reduce((total, arr) => total + arr.length, 0)
  );
  let offset = 0;
  for (let arr of arrays) {
    out.set(arr, offset);
    offset += arr.length;
  }
  return out;
}

В приведенном выше коде мы существуем Fetch Response После возвращениясоздаватьодининдивидуальныймножествоспасти всехвернулся buffer содержание,Затемсуществоватькаждый раз reader.read() Вызывается в методе decode Воляот response.body 已получатьизвсесодержаниеруководить decode。

При этом мы существуем каждый раз decode методза хвостбайтруководитьсуждение об эффективности,Удаление приведет к искажению символов и неполным байтам.

Таким образом, можно гарантировать согласованность окончательного возвращаемого текста и решить проблему искаженного кода окончательного текста.

в это время,Пересмотрите каждый кадр страницы.,Искаженный текст на странице исчез:

статьясерединаиз Код, который вы можетексуществоватьСмотрите здесь

Отображение res.body в срезах данных

когда Ран,Часто в традиционных приложениях изданные серверной части, возвращаемые во внешний интерфейс, имеют определенный формат, означающий изданные. Итак, к,Легко пройти res.body Получение сегментированного отображения данных не может удовлетворить большинство форматов данных в бизнес-сценариях.

Простой пример индивидуального,Обычно мы заключаем клиентское и серверное соглашение. Возвращенные будут хранить данные верхнего уровня существования внизу, а также содержит ошибку, связанную с тем, хранит ли атрибут верхнего уровня ошибку существования.,Таким образом, формат возвращенных может измениться:

Язык кода:javascript
копировать
{
    "data": "real response Data",
    "error": null,
}

Столкнувшись с этой частью формата, мы не можем бездумно получить ответ из readableStream с помощью описанного выше метода.

в то же время,Один индивидуальный сценарий из бизнес-сценария: сервер вернул реальные данные для одного индивидуального типа массива из формата.,Интерфейсная страница должна отображать один индивидуальный элемент на основе каждого индивидуального элемента в данных.,например:

Язык кода:javascript
копировать
{
  "data": [
    {
      "title": "title1",
      "desc": "desc"
    },
    {
      "title": "title2",
      "desc": "desc2"
    },
    {
      "title": "title3",
      "desc": "desc3"
    }
  ],
  "error": null
}

В приведенном выше формате данных data Массив из каждого элемента, который нам может понадобиться отобразить для одного человека на странице, существует. Карта, естественно пройти не думая TextDecoder rea методполучатьданныедаодинсвоего рода ошибкаиз Способ。

Чтобы соответствовать описанному выше бизнес-сценарию, если мы читаем ResponseBody в пакетном режиме и возвращаем его клиенту, на самом деле это неправильный путь.

Более грубый метод заключается в том, что мы используем TextEncoder/TextDecoder для перехвата возвращенного формата данных json в соответствии с определенными правилами.

Автор: Воля stream серединавернулсябайтпреобразован в json Часть перехвата строксодержаниеиз Способиз Это действительно возможнокудовлетворить насизнуждаться,Но на самом деле это не имеет никакой общности.

Мы можем попробовать другой, более общий способ:

  • Каждый раз, когда сервер (NodeServer) возвращает ответ, мы можем использовать специальный заголовок запроса/ответа для определения ответа.

Если этот запрос содержит специальный заголовок запроса, сервер вернет соглашение о внешнем и внутреннем интерфейсах из специальной структуры «изданные». Если этот запрос не содержит специального заголовка запроса, природа возвращает общий заголовок application/json. Просто отформатируйте.

например,То же самое касается и вышеизданных. Мы можем к Воля вернуть индивидуальный формат, отличный от JSON.,напримермы можемк Волявышеизданныесуществовать Сервер обрабатывает его вдля:

Язык кода:javascript
копировать
   "error": null
   
   
   "data": [
    {
      "title": "title1",
      "desc": "desc"
    },
    
    {
      "title": "title2",
      "desc": "desc2"
    },
    
    {
      "title": "title3",
      "desc": "desc3"
    }
  ]

существуют К серверу можно легко получить доступ через \n (число) Правила и клиент договариваются о том, как анализировать эту структуру данных.

  • После этого существующий клиент осуществляет обработку данных согласно соглашению. ResponseHeader чтобы распознать этот формат данных, прочитайте исуществовать ReadableStream При сегментировании в соответствии с едиными стандартами внешнего и внутреннего интерфейса можно достичь определенного формата и условностей.

Хотя этот метод реализации звучит немного причудливо, на самом деле некоторые зрелые фреймворки с открытым исходным кодом в сообществе уже использовали этот метод, чтобы значительно улучшить скорость отклика изданных страниц.

напримерсуществовать Remix серединаиз Defer Эта идея реализуется путем соответствия SPA Режим перехода под из LoaderData данные, полученные от пользователя, значительно снизили скорость ответа страницы.

Однако эта идея реализации требует, чтобы одноклассники на стороне сервера вносили изменения вместе.,Заинтересованные студенты могут попробовать эту идею самостоятельно.,Здесь я не буду это демонстрировать в статье.

Подробно расскажу в следующей статье Remix как использовать fetch Чтобы добиться оптимизации скорости перехода страниц, заинтересованные друзья могут ксосредоточиться Последующие статьи.

Когда, конечно, вы также можете прочитать это сами Remix readStreamSections метод.

Fetch Steam & Content download

частосуществовать XMLHttpRequest в, для Content download Студенты, изучающие фронт-энд, редко имеют возможность эффективно сократить эту часть времени.

и WebFetch Api из Появляться Сотрудничать chunk из Сетевой метод передачи, для нас из Web Применить сетевой запрос на Content download оптимизация обеспечивает более эффективный способ групповой обратной связи с пользователем.

когда Ран За исключением слабой сетидело из Content download Оптимизация пространства, Fetch Api Также существуют другие места, потому что мы приносим больше возможностей.

Если весь фон изданный можно переключить на streaming (аналогично передаче больших файлов), то теоретически его можно использовать на всех сайтах ваших приложений. Web Fetch Оптимизация отклика интерфейса приводит к задержке отображения. Any data request does not need to wait for the interface to fully respond before it can be displayed !

окончание

В статье мы говорим о веб-оптимизации с точки зрения производительности, я надеюсь, что она поможет каждому.

Хотя в статье упоминается, что взгляды Иза относительно радикальны,,Но в целом,Web Stream изWAYS Действительно для Наша страница предлагает возможность быстрого ответа на данныеиз.

boy illustration
Углубленный анализ переполнения памяти CUDA: OutOfMemoryError: CUDA не хватает памяти. Попыталась выделить 3,21 Ги Б (GPU 0; всего 8,00 Ги Б).
boy illustration
[Решено] ошибка установки conda. Среда решения: не удалось выполнить первоначальное зависание. Повторная попытка с помощью файла (графическое руководство).
boy illustration
Прочитайте нейросетевую модель Трансформера в одной статье
boy illustration
.ART Теплые зимние предложения уже открыты
boy illustration
Сравнительная таблица описания кодов ошибок Amap
boy illustration
Уведомление о последних правилах Points Mall в декабре 2022 года.
boy illustration
Даже новички могут быстро приступить к работе с легким сервером приложений.
boy illustration
Взгляд на RSAC 2024|Защита конфиденциальности в эпоху больших моделей
boy illustration
Вы используете ИИ каждый день и до сих пор не знаете, как ИИ дает обратную связь? Одна статья для понимания реализации в коде Python общих функций потерь генеративных моделей + анализ принципов расчета.
boy illustration
Используйте (внутренний) почтовый ящик для образовательных учреждений, чтобы использовать Microsoft Family Bucket (1T дискового пространства на одном диске и версию Office 365 для образовательных учреждений)
boy illustration
Руководство по началу работы с оперативным проектом (7) Практическое сочетание оперативного письма — оперативного письма на основе интеллектуальной системы вопросов и ответов службы поддержки клиентов
boy illustration
[docker] Версия сервера «Чтение 3» — создайте свою собственную программу чтения веб-текста
boy illustration
Обзор Cloud-init и этапы создания в рамках PVE
boy illustration
Корпоративные пользователи используют пакет регистрационных ресурсов для регистрации ICP для веб-сайта и активации оплаты WeChat H5 (с кодом платежного узла версии API V3)
boy illustration
Подробное объяснение таких показателей производительности с высоким уровнем параллелизма, как QPS, TPS, RT и пропускная способность.
boy illustration
Удачи в конкурсе Python Essay Challenge, станьте первым, кто испытает новую функцию сообщества [Запускать блоки кода онлайн] и выиграйте множество изысканных подарков!
boy illustration
[Техническая посадка травы] Кровавая рвота и отделка позволяют вам необычным образом ощипывать гусиные перья! Не распространяйте информацию! ! !
boy illustration
[Официальное ограниченное по времени мероприятие] Сейчас ноябрь, напишите и получите приз
boy illustration
Прочтите это в одной статье: Учебник для няни по созданию сервера Huanshou Parlu на базе CVM-сервера.
boy illustration
Cloud Native | Что такое CRD (настраиваемые определения ресурсов) в K8s?
boy illustration
Как использовать Cloudflare CDN для настройки узла (CF самостоятельно выбирает IP) Гонконг, Китай/Азия узел/сводка и рекомендации внутреннего высокоскоростного IP-сегмента
boy illustration
Дополнительные правила вознаграждения амбассадоров акции в марте 2023 г.
boy illustration
Можно ли открыть частный сервер Phantom Beast Palu одним щелчком мыши? Супер простой урок для начинающих! (Прилагается метод обновления сервера)
boy illustration
[Играйте с Phantom Beast Palu] Обновите игровой сервер Phantom Beast Pallu одним щелчком мыши
boy illustration
Maotouhu делится: последний доступный внутри страны адрес склада исходного образа Docker 2024 года (обновлено 1 декабря)
boy illustration
Кодирование Base64 в MultipartFile
boy illustration
5 точек расширения SpringBoot, супер практично!
boy illustration
Глубокое понимание сопоставления индексов Elasticsearch.
boy illustration
15 рекомендуемых платформ разработки с нулевым кодом корпоративного уровня. Всегда найдется та, которая вам понравится.
boy illustration
Аннотация EasyExcel позволяет экспортировать с сохранением двух десятичных знаков.