Как вы можете помнить, я написал свою скачивалку с ютуба. Ютуб хранит каждое видео в нескольких форматах. По-этому, их приходится парсить. Вот парсер:
Сейчас переписываю код в виде библиотеки. Дело дошло до переписывания этого парсера. И в последний момент обнаружилась странная хрень - обновлённый парсер стал жрать невероятно много памяти.
Вот код нового парсера:
ООПшность ещё надо допиливать. Но сейчас не об этом.
Память кушают строчки:
И только в этом месте. То есть, у DASH (когда видео на чанки разбито). Не пойму, почему столько памяти уходит? Примерно на 25 видео уходит 700mb оперативы.
Сначала было подозрение на LinkedList. Потом перечитал код и понял, что не в нем дело. А в чём - непонятно
Попробовал в методе ParseDashManifest убрать строчки resList.AddLast(video) и resList.AddLast(audio). Память жрать перестало. Видимо, потому что объекты никуда не сохраняются и сразу освобождаются.
Но почему при добавлении их в список сжирается так дофига памяти? И почему это происходит только в методе ParseDashManifest?
Метод Parse делает то же самое, но память не съедает
Заменил LinkedList на List - не помогло.
Кто-нибудь пробовал у себя запускать? У всех так же?
Сделал ещё один тест:
internal class Program
{
static void Main(string[] args)
{
List<YouTubeMediaTrack> list = new List<YouTubeMediaTrack>();
for (int i = 0; i < 9999; ++i)
{
YouTubeMediaTrack trackVideo = new YouTubeMediaTrackVideo(
0, 0, 0, 0, 0, 0, null, 0L, null, null, 0, null, null, null,
null, null, null, null, null, false, false, false, null, null, null);
list.Add(trackVideo);
}
Console.ReadLine();
10000 объектов, а память не жрёт. То есть, проблема именно в методе ParseDashManifest, почему-то
Кстати, если в консольный тест забить ссылку на DASH-видео, то сжирается 124 мегабайта (на одно видео, Карл!). А если без DASH - всего 20мб. Тоже не мало! Но это в 6 раз меньше! Откуда такая большая разница?
В GUI-тесте можно 4 страницы по 30 видео загрузить, а памяти около 170мб съедает (если без DASH)
dashChunkUrls занимает 80МБ в текущем виде (в консольном тесте). Не знаю, есть ли в NET контейнер, который сам будет разруливать хранение похожих строк компактно. Может не стоит склеивать baseUrl и media в segmentUrl, а хранить их отдельно и склеивать только при использовании ссылки?
UPD. Проверил: сохранение baseUrl в отдельном атрибуте сократило потребление с 128МБ до 39МБ.
LinkedList<LinkedList<string>> lists = new LinkedList<LinkedList<string>>();
int max2 = 10;
for (int j = 0; j < max2; ++j)
{
LinkedList<string> list = new LinkedList<string>();
int max = 9999;
string baseUrl = "https://rr4---sn-gvnuxaxjvh-c5me.googlevideo.com/videoplayback/expire/1668947932/ei/fMt5Y5zuGIbB7QShoYOwDA/ip/1.1.1.1/id/67d73d49b7c6bde7/itag/133/source/yt_otf/requiressl/yes/mh/bD/mm/31,29/mn/sn-gvnuxaxjvh-c5me,sn-n8v7znsy/ms/au,rdu/mv/m/mvi/4/pcm2cms/yes/pl/24/initcwndbps/376250/spc/SFxXNgg-X045EmVcrMC7MO09vdsbnok/vprv/1/ratebypass/yes/mime/video%2Fmp4/otfp/1/otf/1/lmt/1657236427614659/mt/1668925969/fvip/14/keepalive/yes/fexp/24001373,24007246/sparams/expire,ei,ip,id,itag,source,requiressl,spc,vprv,ratebypass,mime,otfp,otf,lmt/sig/AOq0QJ8wRQIhAL430GkSS1p3sz1aPHiq0CYNY1U6WZvOc7fw4OoTDPkbAiA841JjPG1BNdA0ZG5NNh1eZgaqjwR-2PI4ovG5e0Hn8A%3D%3D/lsparams/mh,mm,mn,ms,mv,mvi,pcm2cms,pl,initcwndbps/lsig/AG3C_xAwRAIgDoCIUdpxSzcE6V5XU363b4kH5mp77U_rdNwMMYGUHqsCIAFCGEsItvDgvYyqjhPt6N-0CPMJkhrWu2toAxD1tj44/";
for (int i = 0; i < max; ++i)
{
list.AddLast($"{baseUrl}/{i}.ts");
}
lists.AddLast(list);
Console.WriteLine($"{j + 1} / {max2}: Completed {max + 1} strings");
}
Console.ReadLine();
Сожрало 193мб памяти. Действительно, строчки текста жрут как-то слегка так многовато памяти
Но тогда почему старый парсер вообще не жрёт память? Там же всё точно так же. Разница только в том, что все поля открытые и в конструктор передаётся только 3 параметра. Сейчас вот запустил свой YouTube downloader (со старым парсером) и вставил в него эту ссылку (Z9c9SbfGvecg). Вижуалка показывает, что сожрано 42мб. А в диспетчере винды написано - 19,9мб. Наверное, если оптимизировать вашим способом - было бы ещё меньше. Но, всё равно, откуда такая разница (в 3 раза! )? Код ведь почти тот же самый. Только в новом инкапсуляция (вроде так называется) соблюдена.
А когда я получал большой список видео канала и их скачивал (было очень много DASH), я вообще не замечал, что память ушла. У меня индикатор RAM уже очень много кучу лет отдельным окошком постоянно выведен. И я, обычно, замечаю, если память куда-то сожралась
Тоже попробовал. В разделе “Поиск видео по ссылке или ID” вбил Z9c9SbfGvec и нажал “Искать” - потребление 38МБ. После нажатия “Скачать” (и подтягивания доступных форматов) потребление возрастает до 145МБ. Так что не вижу разницы с текущим ConsoleTest.
Хм, действительно Очень странно. Никогда не замечал
Но тогда проблема ясна Это потому что старая версия получает список форматов только при нажатии кнопки “Скачать” и не хранит его постоянно. Так что сборщик мусора просто удаляет эти объекты. А в новой версии список хранится всегда.
Спасибо, оч помогли!
Надо будет этот момент продумать