LINUX.ORG.RU

Сеть IP — когда писать программы лень

 


2

6

Автор этой статьи рассуждает о некоторых способах создания прикладных TCP/IP серверов, крайне редко, к сожалению, используемых в прикладном программировании, которые почти не требуют написания программного кода. Поводом для появления этих коротких заметок явилось намерение напомнить о том, что иногда для того, чтобы описать в программе нечто, по существу своему являющееся достаточно сложным, могут существовать способы выразить эти же вещи намного проще.

>>> Подробности

★★★

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

Проблема форка в линуксе - неизбежный оверкоммит.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#define BLSIZE 1024*1024
int main(int argc, char* argv[])
{
        printf("sizeof(void*)=%d\n",sizeof(void*));
        size_t i = 0;
        void* block_ptr;
        do {
                block_ptr = malloc(BLSIZE);
                if (block_ptr==NULL)
                {
                        printf("%d of megabyte blocks allocated\n",i);
                } else
                        memset(block_ptr,0,BLSIZE);
                ++i;
        } while (block_ptr!=NULL);
        return 0;
}

Этот нехитрый код в линуксе выдает

sizeof(void*)=4

Убито

а в винде он успешно завершается и выводит

sizeof(void*)=4

1914 of megabyte blocks allocated

В линуксе еще падает вот такое в dmesg

[657484.411108] smart invoked oom-killer: gfp_mask=0x201da, order=0, oom_adj=0
[657484.411136] smart cpuset=/ mems_allowed=0
[657484.411156] Pid: 2050, comm: smart Not tainted 2.6.32-41-generic-pae #88-Ubuntu
[657484.411166] Call Trace:
[657484.411257]  [<c01d7314>] oom_kill_process+0xa4/0x2b0
[657484.411268]  [<c01d7989>] ? select_bad_process+0xa9/0xe0
[657484.411277]  [<c01d7a11>] __out_of_memory+0x51/0xa0
[657484.411283]  [<c01d7ab8>] out_of_memory+0x58/0xb0
[657484.411288]  [<c01da3d8>] __alloc_pages_slowpath+0x498/0x4b0
[657484.411294]  [<c01da52a>] __alloc_pages_nodemask+0x13a/0x170
[657484.411305]  [<c01dcaea>] __do_page_cache_readahead+0xea/0x200
[657484.411311]  [<c01dcc26>] ra_submit+0x26/0x30
[657484.411316]  [<c01d5d8c>] filemap_fault+0x3dc/0x410
[657484.411333]  [<c01f07ac>] __do_fault+0x4c/0x520
[657484.411350]  [<c013127c>] ? pvclock_clocksource_read+0xfc/0x160
[657484.411356]  [<c01f1cf8>] handle_mm_fault+0x198/0x4a0
[657484.411374]  [<c02238e0>] ? poll_select_copy_remaining+0xb0/0x110
[657484.411405]  [<c05ba38d>] do_page_fault+0x10d/0x3a0
[657484.411411]  [<c0224eb2>] ? sys_select+0x42/0xc0
[657484.411416]  [<c05ba280>] ? do_page_fault+0x0/0x3a0
[657484.411421]  [<c05b8243>] error_code+0x73/0x80
[657484.411429] Mem-Info:
[657484.411439] DMA per-cpu:
[657484.411443] CPU    0: hi:    0, btch:   1 usd:   0
[657484.411450] Normal per-cpu:
[657484.411453] CPU    0: hi:  186, btch:  31 usd:  61
[657484.411460] active_anon:45515 inactive_anon:44547 isolated_anon:0
[657484.411462]  active_file:0 inactive_file:19 isolated_file:0
[657484.411464]  unevictable:8 dirty:0 writeback:5 unstable:0
[657484.411466]  free:961 slab_reclaimable:613 slab_unreclaimable:1243
[657484.411467]  mapped:3 shmem:0 pagetables:825 bounce:0
[657484.411481] DMA free:1556kB min:100kB low:124kB high:148kB active_anon:3216kB inactive_anon:3264kB active_file:0kB inactive_file:16kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:15852kB mlocked:0kB dirty:0kB writeback:0kB mapped:0kB shmem:0kB slab_reclaimable:4kB slab_unreclaimable:8kB kernel_stack:0kB pagetables:12kB unstable:0kB bounce:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? no
[657484.411490] lowmem_reserve[]: 0 365 365 365
[657484.411512] Normal free:2288kB min:2392kB low:2988kB high:3588kB active_anon:178844kB inactive_anon:174924kB active_file:0kB inactive_file:60kB unevictable:32kB isolated(anon):0kB isolated(file):0kB present:373876kB mlocked:32kB dirty:0kB writeback:20kB mapped:12kB shmem:0kB slab_reclaimable:2448kB slab_unreclaimable:4964kB kernel_stack:1432kB pagetables:3288kB unstable:0kB bounce:0kB writeback_tmp:0kB pages_scanned:47 all_unreclaimable? no
[657484.411539] lowmem_reserve[]: 0 0 0 0
[657484.411548] DMA: 1*4kB 0*8kB 1*16kB 0*32kB 0*64kB 0*128kB 2*256kB 0*512kB 1*1024kB 0*2048kB 0*4096kB = 1556kB
[657484.411561] Normal: 54*4kB 17*8kB 5*16kB 8*32kB 1*64kB 2*128kB 1*256kB 0*512kB 1*1024kB 0*2048kB 0*4096kB = 2288kB
[657484.411581] 2919 total pagecache pages
[657484.411587] 2894 pages in swap cache
[657484.411594] Swap cache stats: add 430176, delete 427282, find 17217/20577
[657484.411597] Free swap  = 0kB
[657484.411599] Total swap = 905208kB
[657484.413710] 98301 pages RAM
[657484.413717] 0 pages HighMem
[657484.413719] 3420 pages reserved
[657484.413725] 54 pages shared
[657484.413727] 93661 pages non-shared
[657484.413731] Out of memory: kill process 19800 (a.out) score 255605 or a child
[657484.430034] Killed process 19800 (a.out)

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

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

/proc/sys/vm/overcommit_memory
              This file contains the kernel virtual memory accounting mode.  Values
              are:

                     0: heuristic overcommit (this is the default)
                     1: always overcommit, never check
                     2: always check, never overcommit

              In mode 0, calls of mmap(2) with MAP_NORESERVE are not checked, and the
              default check is very weak, leading to the risk of getting a process
              "OOM-killed".  Under Linux 2.4 any nonzero value implies mode 1.  In
              mode 2 (available since Linux 2.6), the total virtual address space on
              the system is limited to (SS + RAM*(r/100)), where SS is the size of
              the swap space, and RAM is the size of the physical memory, and r is
              the contents of the file /proc/sys/vm/overcommit_ratio.

       /proc/sys/vm/overcommit_ratio
              See the description of /proc/sys/vm/overcommit_memory.
То, что винда никогда не оверкоммитит, это спорное преимущество, поскольку может влиять на performance. В линуксе можно и так и этак.

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

В линуксе использование fork() практически обязывает использовать оверкоммит. Вот у меня на серваке крутится демон, который сначала маллочит 2 гига памяти, а потом форкается 8 раз. Без оверкоммита это 16 гиг памяти, но реально они никогда не занимаются. И да, этот тест на винде проходит быстрее чем на линуксе в разы.

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

Не-а... :)

Проблема форка в линуксе - неизбежный оверкоммит.

Это не проблема fork(), не проблема linux. Это прежде всего проблема программиста, который допускает выделение памяти явно не понимая зачем именно она ему нужна. Он же её всё-равно не использует... При грамотном подходе память достаточно быстро возвращается системе.

а в винде он успешно завершается и выводит

А подольше подождать? Вообще-то, уважаемый Casus уже дал ответ... Но я только могу добавить что oom_killer (см. комментарии в коде /usr/src/linux-3.3.4-gentoo/mm/oom_kill.c) начнёт свою работу _почти_ при полном исчерпании вирт. памяти (можно почитать как именно он работает, не в том суть). Вирт. память это RAM+swap. В linux раздел swap это отдельный раздел (в принципе, можно и в файл свопиться) а в винде — это спец. файл в пределах файловой системы. Отсюда совет — просто подождите по-дольше. Но только я за работоспособность оффтопа не ручаюсь в конце эксперимента.

anonymous
()
Ответ на: Не-а... :) от anonymous

винде — это спец. файл в пределах файловой системы

Как этот факт может создать какие-то проблемы при запуске этой программы?

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

А с чего Вы взяли?

Как этот факт может создать какие-то проблемы при запуске этой программы?

Что факт того, что файл подкачки в винде размещён в стандартном дисковом пространстве создаст какие-то проблемы? При _запуске_?

Вот при работе вполне может. Если малость подождать, то со временем этот файл сможет занять оооочень большой объём диска. Дело в том, что этот файл как правило, является динамическим по своему размеру. Оффтоп использует собственные «умолчания», а юзер об этом как правило не в курсе. Если я не ошибаюсь, то минимальный размер своп-файла по умолчанию равен 1.5*RAM, но верхний предел по-моему, то ли 16, то ли 32TB. Программа будет мало-помалу отжирать «память», но уже из рабочего пространства диска.

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

Гораздо лучше ограничить принудительно размер своп-файла (где-то в настройках это есть). В этом случае оффтоп разместит файл с минимальной фрагментацией. Но тогда получится ограничение по размеру виртуальной памяти. И чем это лучше Linux? А! Да! Ещё можно вынести такой файл на отдельный раздел. Но тогда это совсем не лучше Linux.

anonymous
()
Ответ на: А с чего Вы взяли? от anonymous

этот файл как правило, является динамическим по своему размеру

точно, совсем забыл про это... если приходится пользоваться виндой, всегда настраиваю определённый размер

unC0Rr ★★★★★
()
Ответ на: Не-а... :) от anonymous

Что значит подождать подольше? Я привел код, программа успешно выполнилась и завершилась с кодом 0. После этого система была полностью работоспособна, правда чуть замедлилась (из-за сброса дискового кэша).

Что значит проблема в программистах?

10757 www-data  20   0  282M 53968  9340 S  1.0  0.3  0:00.54 /usr/sbin/apache2 -k start
10758 www-data  20   0  282M 53968  9340 S  0.0  0.3  0:00.00 /usr/sbin/apache2 -k start
10814 www-data  20   0  281M 52816  8512 S  0.0  0.3  0:00.18 /usr/sbin/apache2 -k start
10815 www-data  20   0  281M 52816  8512 S  0.0  0.3  0:00.00 /usr/sbin/apache2 -k start
10811 www-data  20   0  332M 42576  8460 S  0.0  0.3  0:00.32 /usr/sbin/apache2 -k start
10812 www-data  20   0  332M 42576  8460 S  0.0  0.3  0:00.00 /usr/sbin/apache2 -k start
29882 root      20   0  258M 26256  5800 S  0.0  0.2  4:10.84 /usr/sbin/apache2 -k start

Апач выделяет НА МНОГО больше памяти чем использует. Это именно архитектурная проблема, потому что overcommit это часть механизма copy on write. Если бы этот апач был с потоками, он бы не требовал оверкоммита, а сейчас он выделил больше памяти, чем есть на хосте.

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

Тут всё запущено. И сильно...

Если по-просту, то это просто ... п*ц!!!

Я привел код, программа успешно выполнилась и завершилась с кодом 0.

Во-первых, я не имею оффтопа (в последнее время вообще от него избавлен) чтобы подтвердить или опровергнуть Ваши слова.

В Linux (просто гентушный десктоп) у меня Ваш же код вывел:

noone@nonamehost ~/tests $ ./test
sizeof(void*)=4
3056 of megabyte blocks allocated

В dmesg девственно чисто. ЧЯДНТ?

Во-вторых, касаемо оффтопа, я всего-навсего говорю о том, что при отсутствии ограничения на верхнюю границу выделяемой памяти Вы можете получить полный п*ц. Скорее всего и получите в корректно написанном коде. В Linux всё несколько проще.

Что значит проблема в программистах?

А здесь (в Вашем случае) проблема не в программистах. С ними-то всё ровно. Апач берёт памяти ровно столько, чтобы обслужить запросы со стороны пользователей. Причём, даже с учётом того, что там может быть куча модулей, которые по непоняткам иной раз врубают в режиме ALL (а потом жалуются что всё плохо).

Рекомендую взглянуть на то, что есть у меня:

apache2 -t -D DUMP_MODULES
Вырезана незначащая строка.
Loaded Modules:
 core_module (static)
 mpm_worker_module (static)
 http_module (static)
 so_module (static)
 actions_module (shared)
 authz_host_module (shared)
 deflate_module (shared)
 dir_module (shared)
 env_module (shared)
 expires_module (shared)
 filter_module (shared)
 mime_module (shared)
Syntax OK

Но вот тут явная проблема в недоадмине. Это кто же там у вас такой «умный», чтобы зарядить Апач с MPM prefork?

Так же рекомендую ознакомиться:

apache2 -V
Server version: Apache/2.2.22 (Unix)
Server built:   Apr 27 2012 01:32:17
Server's Module Magic Number: 20051115:30
Server loaded:  APR 1.4.6, APR-Util 1.4.1
Compiled using: APR 1.4.6, APR-Util 1.4.1
Architecture:   32-bit
Server MPM:     Worker
  threaded:     yes (fixed thread count)
    forked:     yes (variable process count)
Server compiled with....
 -D APACHE_MPM_DIR="server/mpm/worker"
 -D APR_HAS_SENDFILE
 -D APR_HAS_MMAP
 -D APR_HAVE_IPV6 (IPv4-mapped addresses enabled)
 -D APR_USE_SYSVSEM_SERIALIZE
 -D APR_USE_PTHREAD_SERIALIZE
 -D APR_HAS_OTHER_CHILD
 -D AP_HAVE_RELIABLE_PIPED_LOGS
 -D DYNAMIC_MODULE_LIMIT=128
 -D HTTPD_ROOT="/usr"
 -D SUEXEC_BIN="/usr/sbin/suexec"
 -D DEFAULT_SCOREBOARD="logs/apache_runtime_status"
 -D DEFAULT_ERRORLOG="logs/error_log"
 -D AP_TYPES_CONFIG_FILE="/etc/apache2/mime.types"
 -D SERVER_CONFIG_FILE="/etc/apache2/httpd.conf"

Ну и под завязку небольшой hint...

Choosing an MPM

...

* The worker MPM uses multiple child processes with many threads each. Each thread handles one connection at a time. Worker generally is a good choice for high-traffic servers because it has a smaller memory footprint than the prefork MPM.

* The prefork MPM uses multiple child processes with one thread each. Each process handles one connection at a time. On many systems, prefork is comparable in speed to worker, but it uses more memory. Prefork's threadless design has advantages over worker in some situations: it can be used with non-thread-safe third-party modules, and it is easier to debug on platforms with poor thread debugging support.

Вот всегда улыбает, когда говорят что что-то там плохо работает/тормозит. Может проще — плохо готовим?

Если бы этот апач был с потоками

Сделайте одолжение — расстреляйте админа? :)

overcommit это часть механизма copy on write

Не. Про overcommit... Это Вам рано. Поверьте наслово... :)))

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

Дааа....

Винда сама определяет пределы роста этого файла каким-то образом.

Это такая специальная уличная магия... :)))

anonymous
()
Ответ на: Тут всё запущено. И сильно... от anonymous

Очевидно, вы используете >4 гб памяти на 32х разрядной системе.

Так работает апач в пакетной системе дебиана - если поставить php5, автоматически ставится mpm_prefork и сносятся все остальные mpm. Предлагаю вырвать руки у мейнтейнеров пакетов, а заодно и у всего дебиан сообщества.

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

Отомстите им...

Так работает апач в пакетной системе дебиана - если поставить php5, автоматически ставится mpm_prefork и сносятся все остальные mpm. Предлагаю вырвать руки у мейнтейнеров пакетов, а заодно и у всего дебиан сообщества.

... просто перейдите на Gentoo. Там все эти проблемы разруливаются проще...

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

А им-то зачем?

У них все вроде как хорошо. У меня — то же. Наличие/отсутствие похапе не влияет на мрм апача. Кстати. В понедельник к нам в прозекторскую угодит битрикс новый, который 17 мая выпустили (11.5, по-моему). Будет в чем поколупаться, да поржать. Порядка 200 мегабайт в распакованном виде похапе-поделия... Это уже смешно.

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

Битрикс?

Ну что... так и запишем — 200 мегов сплошной гибкости и косяков. :-)

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.