LINUX.ORG.RU
Форум — Desktop

Похоже я нащупал как обуздать Firefox и скармливать ему чуть-чуть памяти

 , , ,


7

4

Фокс конкретно достал своим прожорством. Шестнадцать гигов, а я постоянно вижу как всё свапится из-за этого гада. (и не гыкайте мне тут, все браузеры ведут себя одинаково) Ладно бы я что-то сложное делал. Но он явно не отпускает страницы из памяти, хотя уже и выставил кучу всяких уловок. Но вот что мне не давало покоя - этот гад видит сколько в компе памяти и не собирается останавливаться пока не выжрет всё. В результате все программы должны по стеночкам обходить. А тут вы со своими спорами про systemd. И придумал я гадкое, засунул фокса в персональную группу с ограничениями. Сделал так: Создал директорию ~/.config/systemd/user/app-firefox@.service.d/ В ней файл override.conf со следующим содержимым

[Service]
MemoryHigh=1.5G
MemoryMax=4G
MemorySwapMax=0

Перезапустил всё и стало хорошо на душе, фокс стоит на полтора гигах, как вкопанный. Но только включил ютуб, переключился на другое окно с другой вкладкой в другом фоксовском контейнере и всё дико тормозить стало. Я поднял до 2.5G, стало полегче, но всё равно, дойдёт до черты и тормоза лютые сразу. И тут я понял, что он смотрит куда-то в meminfo насчёт доступного рама, но не видит ограничений системды. И поэтому сходу влетает в ограничение, полагая, что все 16 гигов его. Тогда я создал фейковый ~/.fake_meminfo в домашней папке где заменил MemTotal: 4194304 kB и произошло чудо. Всё стало вполне сносно. Но вдруг внезапно он стал падать после нескольких видео на ютубе. Видимо недостаточно я ему наврал. Тога я попросил у ИИ сгенерить meminfo чтобы было похоже, что мы подходим к границе доступной памяти. Вот такой файл ~/.fake_meminfo в итогу получился

MemTotal:        4194304 kB
MemFree:          350000 kB
MemAvailable:     512000 kB
Buffers:           50000 kB
Cached:           600000 kB
SwapCached:            0 kB
Active:          2500000 kB
Inactive:         800000 kB
Active(anon):    2000000 kB
Inactive(anon):     4000 kB
Active(file):     500000 kB
Inactive(file):   800000 kB
SwapTotal:      15580020 kB
SwapFree:       15580020 kB
Dirty:              1000 kB
Writeback:             0 kB
AnonPages:       2000000 kB
Mapped:           400000 kB
Shmem:            150000 kB
Slab:             300000 kB
CommitLimit:    22656768 kB
Committed_AS:   15171448 kB
DirectMap4k:      800000 kB
DirectMap2M:     3000000 kB

а файл override.conf стал таким

[Service]
MemoryHigh=2.5G
MemoryMax=4G
MemorySwapMax=0

# "Обман" - подмена файла для Firefox
BindReadOnlyPaths=/home/pchelobiaka/.fake_meminfo:/proc/meminfo

И… иии… вроде работает. Полноценный Фокс с контейнерами, по собственной воле держит около 2 гигов и не больше.

Спешу поделиться наблюдением. Пробуйте кому интересно. И может что дельное подскажете.

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

Upd.: Важное дополнение. При рассчёте занимаемой памяти я беру не просто размер процесса firefox, но суммы всех процессов фокса вместе взятых. Как оказалось люди не поняли сразу и пфыкают :)



Последнее исправление: PcheloBiaka (всего исправлений: 4)

И тут я понял, что он смотрит куда-то в meminfo насчёт доступного рама

Ааа, я так и подозревал! После того как установил 16гб вместо 8гб - фф стал жрать больше памяти, при этом не улучшив никак свою работу.

Подозреваю, ты мог бы и без лимита памяти просто /proc/meminfo ему подменить. Сейчас попробую подменялку сделать без системдшных штук и посмотрю что выйдет.

firkax ★★★★★
()
Ответ на: комментарий от firkax

Добавлю почему я делал именно через cgroups - чтобы не менять лайнчера и не делать всякую хрень каждый раз когда запустил фокс. Особенно с учётом того, что при запуске компьютера восстанавливаются окна приложений, и восстаналиваются они по имении в /usr/bin/, а не твоих кастомных лайнчеров. А поскольку все окна Фокса являются одним головным приложением, то мешанина увеличится, если мы будем экспортировать переменные в лайнчере.

Надеюсь понятно написал.

PcheloBiaka
() автор топика

Да в принципе, это всё и через about:config в самом firefox можно обуздать, через параметры вроде browser.cache.memory.capacity и подобые, которые при дефолте (-1 обычно, хотя иногда может быть что-то вроде 10 — в процентах от количества RAM в системе) зависят об количества RAM в системе. Их можно установить в конкретные желаемые значения (в байтах, иногда в процентах).

CrX ★★★★★
()
Последнее исправление: CrX (всего исправлений: 2)
Ответ на: комментарий от PcheloBiaka

хм… Странно. По идее должно. Но справедливости ради, я никогда не пробовал играться с ними в сторону уменьшения. Обычно наоборот — в сторону увеличения.

Ну а так вообще по идее это и без systemd можно сделать, через cgroups v2.

CrX ★★★★★
()
Ответ на: комментарий от PcheloBiaka

Не совсем. Я использую сэндбоксинг с помощью bwrap.

upd: а, ты меешь в виду контейнеры внутри самого firefox? Да, я использую, но в основном чисто чтоб куки разные были. Они по-моему, только для этого и годятся.

CrX ★★★★★
()
Последнее исправление: CrX (всего исправлений: 1)

Лучше бы сделать группу для системных приложений, и как-нибудь её так настроить, чтобы они в своп не выгружались…

Saakx
()
Ответ на: комментарий от CrX

Ой, я думал про bwrap, но там какое-то слишком всё. Я даже с помощью ИИ не понял :)) А если я это не понимаю, то и контролировать не смогу. Ограничения же я сам придумал, сам разобрался. И значит пойму что дальше делать. А дальше надо сделать всё более менее по уму. Надо в /tmp вывесить такой ложный meminfo и зеркалировать в него реальные значения если памяти реально осталось меньше, чем я выставил. Тогда это будет лучше и правильнее. Только надо найти такую висюльку, которая это будет делать без накладных расходов.

PcheloBiaka
() автор топика

Оригинальный подход, однако.

Будет время поиграюсь с конфигом firejail. Там тоже можно файлы системы подменять. :)

Только я бы в фейковом meminfo SwapTotal в 0 выставил. Нехер фаерфоксу в свап лазать.

Дожили - браузеру приходится фейковый /proc/meminfo подсовывать, чтобы он просто, жёваный крот, работал нормально, а не выжирал всю память. :) И после этого всякие дебилы будут рассказывать сказки про то, как никаких заговоров не существует. Подонки.

Stanson ★★★★★
()
Ответ на: комментарий от firkax

Хм, файрфокс не делает ни open() ни openat() на путь /proc/meminfo, по крайней мере в начале своей работы. Может быть он его делает потом или открывает сначала proc а потом из него уже файл. При этом куча других открываний файлов в том числе из /proc/ перехватывается успешно.

Или он делает ему openat2() или ещё что-то? fopen() вроде должно на open() само заворачиваться.

firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 1)
Ответ на: комментарий от firkax

Хм. А у меня блогодааать… уже несколько часов не поднималось выше 2 гигов, и вообще держится в районе 1.7-1.8. Хотя даже это какой-то зашквар, конечно.

PcheloBiaka
() автор топика
Ответ на: комментарий от CrX

Ну тогда наливай чай, рассказывай :) И примерный конфиг давай, может я живого человека пойму :) Хотя про баблврап я без всяких ИИ читал и только запутался окончательно. Меня давно подмывает это всё.

PcheloBiaka
() автор топика
Ответ на: комментарий от PcheloBiaka

Ну тогда наливай чай, рассказывай :)

Да что там особо рассказывать? Для ограничения памяти я его не юзал (как сразу и сказал). В основном, главные аргументы это --bind и --ro-bind соответственно. С их помощью можно забиндить в песочницу нужные файлы или каталоги (можно сразу весь корень, если пофиг, а можно прям выборочно только нужное). Особенно полезно забиндить $HOME на что-то другое (специальный каталог, который является хомяком именно только для этого сэндбокса) — по-моему, это прям самое нужное. Ну и caps’ы всякие, а также --unshare-net для отключения доступа к сети. Это простое, но при этом самое часто нужное. Ну а про более продвинутое в мане всё есть. Не знаю, там вроде всё понятно написано довольно.

CrX ★★★★★
()
Ответ на: комментарий от CrX

С ограничениями домашнего каталога я когда-то игрался, да. Но потом подумал, что проблем больше чем пользы. Особенно семье было непонятно, почему из любой папки файл не закинуть? И я сдался. А фокс был ещё тот, старый, 3.6.чегото :)

А ограничение сети - чтоб локалку не сканировал? Вроде же это отключили в фоксе? Или нет?

PcheloBiaka
() автор топика
Ответ на: комментарий от mamina_radost

Не поверишь, до сих пор хочется руки помыть и рот. с мылом. Я системду трогал… фууу…

PcheloBiaka
() автор топика
Ответ на: комментарий от PcheloBiaka

Но потом подумал, что проблем больше чем пользы.

Кому как. По-моему, очень удобно для многих приложений: можно и несколько конфигов иметь там, где путь захардкожен и нельзя задать, и доступ к приватным данным (а это всё не от этого приложения) заркыть, и много чего такого. Даже банально узнать, куда срёт очередная проприетарная игра — в пустом хомяке очень удобно получается :)

Особенно семье было непонятно, почему из любой папки файл не закинуть?

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

А ограничение сети - чтоб локалку не сканировал?

Чтоб в интернет ничего не слало. Я ж не только для firefox юзаю, но и например для игр. А им точно (сингловым) в интернет ни к чему — только лишнее шпиёнство.

CrX ★★★★★
()
Последнее исправление: CrX (всего исправлений: 1)
Ответ на: комментарий от PcheloBiaka

Особенно семье было непонятно, почему из любой папки файл не закинуть?

У меня есть извращённая идея на этот счёт. Диалог открывания файла превращаем в сервис в отдельном полноправном процессе. Когда какая-то огороженная прога хочет открыть файл - она не показывает диалог сама (у самой вообще никуда кроме своих файлов доступа нет), а отправляет сетевой запрос этому сервису. Сервис показывает безопасный диалог, юзер выбирает файл. Потом сервис этот файл пересылает запросившей диалог проге. Или может быть не файл а его открытый на read-only дескриптор. С диалогом сохранения аналогично.

firkax ★★★★★
()
Ответ на: комментарий от PcheloBiaka

Не, там не xdg-open а как минимум патчить gtk придётся (он же диалог показывает?). Или может быть и сам фф. Как устроен драгдроп я не знаю, мне даже проверить его негде. Подозреваю тоже что-то тулкитовое.

xdg-open это когда ты скачал файл (из инета) и хочешь его запустить после этого из браузерного гуи.

firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 3)
Ответ на: комментарий от firkax

а, точно. тогда что-то из xdg-desktop-portal. там выбирается диалог которым выбирать файлы. Вот это и надо обманывать.

PcheloBiaka
() автор топика
Ответ на: комментарий от James_Holden

Я подозревал что где-то такое уже есть. Хотя думал что скорее в смартфонах.

Но я не зря подписал это как «извращённая».

firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 1)
Ответ на: комментарий от firkax

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

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

James_Holden ★★★★★
()
Последнее исправление: James_Holden (всего исправлений: 1)

И… иии… вроде работает. Полноценный Фокс с контейнерами, по собственной воле держит около 2 гигов и не больше.

Так а что произойдет, когда вкладок открыто больше, чем стоит лимит? Скорей всего он выгрузит их в .cache(ахахах). А оно в 99% случаев на nvme. И будет елозить весь веб по накопителю

bryak ★★★★
()
Последнее исправление: bryak (всего исправлений: 2)
Ответ на: комментарий от bryak

Чего ахах? Именно это от фф и требуется, вместо жора памяти. А ссд быстрые, это не жёсткий диск который тормозить будет, так что всё в порядке. Хотя даже с жёстким диском давно неиспользованные вкладки желательно на него выгружать.

firkax ★★★★★
()
Ответ на: комментарий от x22

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

firkax ★★★★★
()
Ответ на: комментарий от firkax

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

Ну а кому сейчас легко?

x22 ★★★
()
Ответ на: комментарий от firkax

Чего ахах? Именно это от фф и требуется, вместо жора памяти. А ссд быстрые, это не жёсткий диск который тормозить будет, так что всё в порядке. Хотя даже с жёстким диском давно неиспользованные вкладки желательно на него выгружать.

Я понял. Так-то оно и так. Кстати, я смог ограничить ff и без этих шаманств с помощью

systemd-run --user --scope -p MemoryMax=2G firefox

У меня cache on disk == off. На фишках.нет открыл туеву хучу вкладок - потребление до 2гб. Интересно, всё-таки куда он дату из вкладок складывает?

bryak ★★★★
()
Последнее исправление: bryak (всего исправлений: 2)

А настройки понастраивать? Всякие кэши,предзагрузки? Ublock origin установить? Хотя, кто может поспорить, что автогеном через зад онт прикольнее конечно.

anonymous
()
Ответ на: комментарий от x22

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

PcheloBiaka
() автор топика
Ответ на: комментарий от Tanger

и каждый раз переключаясь на вкладку она опять загружается. А всё что ты писал на лорчик стёрлось и надо начинать заново. А у меня всё работает :))

PcheloBiaka
() автор топика

Хммм, это что же в магазине так же можно стену убрать? Звучит прямо интересно. С ФФ непонятно что вы с ним делаете

cobold ★★★★★
()
Ответ на: комментарий от bryak

Этот способ подразумевает изменение лаунчера. А следовательно, не подходит, потому что фокс запущеный не через этот лаунчер будет жрать. И если бы ты сам понял что я сделал у себя, ты бы понял, что ты выставил то же ограничение, жёсткое, о которое слёту разбивается мой фокс. Наверное всё зависит от слишком многих факторов чтобы понять почему тебе этого достаточно, а мне нет. Но вот так у меня. Если у кого-то сработает твоё ограничение выставленное моим способом, то и хорошо. Но мне пришлось аж так вывернуться.

PcheloBiaka
() автор топика
Ответ на: комментарий от cobold

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

PcheloBiaka
() автор топика
Ответ на: комментарий от PcheloBiaka

Познайте две благородные истины!

  1. Работа с браузером это страдание

  2. Есть путь избавления от страданий, и заключается он в отказе от открытия триллионов дурацких вкладок! Ибо, смиряя себя до двух вкладок максимум, я могу работать даже на Raspberry Pi 3! Покайтесь

James_Holden ★★★★★
()
Последнее исправление: James_Holden (всего исправлений: 1)
Ответ на: комментарий от James_Holden

Никаких трилионов вкладок. Из постоянно открытых вкладок - лор, ютуб. Вообще может быть всё закрыто кроме лора, но я точно понимаю, что в памяти всё также и висит этот ютуб. ublock origin включён. И всё в контейнерах. Хотя вижу, что ютуб везде видит мой аккаунт, значит контейнеры эти дырявые. Но всё равно, привык к ним, разные задачи, и даже учётки разные в разных контейнерах. Может контейнеры и заставляют его себя так вести, но думаю, он просто не может чего-то там отпустить, очистить. А может в gpu чего застряло, не знаю. Но так как это извращение мне помогло, я уверен, что это именно поведение работы фокса с памятью, видит её много и насрать на ограничения.

Завидую тем у кого всё просто работает.

PcheloBiaka
() автор топика
Ответ на: комментарий от James_Holden

что я делаю не так? открываю по 50+ вкладок

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

unclestephen ★★★
()

Обнаружил вкладку about:memory - там можно посмотреть детализацию расхода памяти. Правда расчёт этой детализации занял занимает несколько минут. Но там какое-то враньё получается, если верить его репорту то у каждого из трёх запущеных фф потребление в пределах 2-3гб. При том что по факту сожрано почти 16гб памяти+7гб свапа.

firkax ★★★★★
()
Ответ на: комментарий от firkax

Вот мой перехватчик meminfo без задействования внешних инструментов и повышенных привилегий

#define _GNU_SOURCE
#include <sys/socket.h>
#include <linux/netlink.h>
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>
#include <errno.h>

/* real stdio.h and fcntl.h can't be included */
typedef struct FILE FILE;
extern FILE *stderr;
extern int fprintf(FILE *stream, const char *format, ...);
#define AT_FDCWD -100 /* this constanct may be Linux-specific */
#define WRITABLE_MODE 01103 /* 01000=O_TRUNC, 0100=O_CREAT, 3=non-O_RDONLY modes; may be Linux-specific */

static int (*libc_real_open)(char const *path, int flags, mode_t mode);
static int (*libc_real_openat)(int dfd, char const *path, int flags, mode_t mode);
static FILE * (*libc_real_fopen)(char const *path, char const *mode);
static FILE * (*libc_real_freopen)(char const *path, char const *mode, FILE *fp);
static char const *file;
static int verbose;

static void check_init(void) {
  static int called;
  if(called) return;
  called = 1;
  if(!(file = getenv("MEMINFO"))) fprintf(stderr, "ff-memory: missing env var MEMINFO\n");
  verbose = !!getenv("FAKEFILE_VERBOSE");
  if(!(libc_real_open=dlsym(RTLD_NEXT,"open"))) fprintf(stderr, "glibc open() missing?!\n");
  if(!(libc_real_openat=dlsym(RTLD_NEXT,"openat"))) fprintf(stderr, "glibc openat() missing?!\n");
  if(!(libc_real_fopen=dlsym(RTLD_NEXT,"fopen"))) fprintf(stderr, "glibc fopen() missing?!\n");
  if(!(libc_real_freopen=dlsym(RTLD_NEXT,"freopen"))) fprintf(stderr, "glibc freopen() missing?!\n");
}

static int get_replacement(char const *path, int w, char const **newpath) {
  if(!strcmp(path,"/proc/meminfo") && file) {
    if(w) { fprintf(stderr, "fakefile: denied write access to %s\n", path); errno=EPERM; return -1; }
    fprintf(stderr, "fakefile: fixing path %s -> %s\n", path, file);
    *newpath = file;
    return 1;
  }
  return 0;
}

int open(char const *path, int flags, mode_t mode) {
  check_init();
  if(verbose) fprintf(stderr, "fakefile: open(): %s\n", path);
  if(!libc_real_open) { errno=ENOSYS; return -1; }
  if(get_replacement(path, !!(mode&WRITABLE_MODE), &path)<0) return -1;
  return libc_real_open(path, flags, mode);
}

int openat(int dfd, char const *path, int flags, mode_t mode) {
  check_init();
  if(verbose) fprintf(stderr, "fakefile: openat(): %s\n", path);
  if(!libc_real_openat) { errno=ENOSYS; return -1; }
  if(dfd==AT_FDCWD) if(get_replacement(path, !!(mode&WRITABLE_MODE), &path)<0) return -1;
  return libc_real_openat(dfd, path, flags, mode);
}

FILE * fopen(char const *path, char const *mode) {
  check_init();
  if(verbose) fprintf(stderr, "fakefile: fopen(): %s\n", path);
  if(!libc_real_fopen) { errno=ENOSYS; return NULL; }
  if(!mode || !*mode) { errno=EINVAL; return NULL; }
  if(get_replacement(path, *mode!='r' || strchr(mode,'+'), &path)<0) return NULL;
  return libc_real_fopen(path, mode);
}

FILE * freopen(char const *path, char const *mode, FILE *fp) {
  check_init();
  if(verbose) fprintf(stderr, "fakefile: freopen(): %s\n", path);
  if(!libc_real_freopen) { errno=ENOSYS; return NULL; }
  if(!mode || !*mode) { errno=EINVAL; return NULL; }
  if(get_replacement(path, *mode!='r' || strchr(mode,'+'), &path)<0) return NULL;
  return libc_real_freopen(path, mode, fp);
}

/*
  gcc -shared -o fake-meminfo.so fake-meminfo.c -ldl -lc -fPIC
  [FAKEFILE_VERBOSE=1] MEMINFO=/path/to/fake/meminfo LD_PRELOAD=./fake-meminfo.so exec /path/to/program
  */

На самом деле там ещё функции есть (fopen64, __fopen_2 итд), но фф, по крайней мере у меня, открывает meminfo с помощью fopen().

firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 2)
  • Markdown
Пустая строка (два раза Enter) начинает новый абзац. Знак '>' в начале абзаца выделяет абзац курсивом цитирования.
Внимание: прочитайте описание разметки Markdown.
Используйте Ctrl-Enter для размещения комментария