AlekXL
Advanced Member | Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору kaz_av Цитата: Цитата: Покажи мне пример, когда, проблема фрагментации стала для натива стала критичной. Гуглиться на раз. | там чел коммитит 6-7 блоков по 380 мегабайт, это идет в обход MM. А потом освобождает. В 32-битном режиме! идиот.. Такая задача либо для 64-разрядных машин, где ,большой фрагментации не будет, либо для специаированного MM. Он сам виноват. Не такая и проблема: следить чтобы 6-7 блоков не фрагментировались. Это и ежу понятно. У тебя все примеры такие дурацкие?? Цитата: Что работает быстрее: последовательный просмотр памяти или прыжки по разным участкам? Так вот первый сценарий это GC, второй - подсчет ссылок. | В плане кэша, ведь ты говоришь о нем: если участок больше 64 байт, линейки кеша, то разницы нет. Конечно есть префетч, и накладные расходы на стороне RAM для пересылки и вычисления адреса: там, действительно, несколько последовательных чтений или записей выгоднее (DRAM burst). Но это не поможет : выигрыш невелик по сравнению с ценой кэшевого промаха. Другими словами, рандомные адреса, не влияют на обработку длинных в массивах(так как там все последовательно), ни на локальные переменные(то все последовательно). Напротив, наличие активного GC в отдельном потоке, потребляет невеликие ресурсы кэша 3-го уровня. А в процессорах Интел, и вовсе активный GC может вызвать обнуление кэша L2 в другом ядре. Что же до остального, типа строк, то не даст последовательное размещение особых преимуществ, если объекты больше 64-байт. Ручное управление памятью тоже не серебряная пуля, но там намного больше контроля. Больше возможностей. А крохотные объекты обходятся дорого везде: причем GC с ними работает хуже: приходится вычислять достижимость каждого из целой тучи. Цитата: а того, что при вычислении размера буфера, программисты чаще всего ошибаются на 1 элемент, как в том случае, который ты упоминал. Опыт, батенька Цитата: Я тебе предлагал уже самому посмотреть на счетчики любого дотнетовского приложения. Всё от ситуации зависит, когда я мониторил одну софтину там GC кушал сотые доли процента. | мы далее рассмотрим время GC, только поскольку ты использовал JVM в своем примере, то о ней и будем говорить. Цитата: Кроме того, что не пригоден для использования в продакшене? Ничем. | Кто сказал? Форк ScaleMM включен даже в дистрибуцию mORMot. Он вполне юзабелен. Цитата: Сравнивать iOS и Android, для поисков истины в споре ARC vs. GC, вообще глупо т.к. iOS является оптимизированным решением для железа единственного вендора, а Android универсальная ОС работающая на диком зоопарке разношерстного говна. У меня аппарат далеко не флагман, скорее середнячек. . | iOs приложения тоже вынуждены работать с разными версиями iPhone, которые различаются железом. Цитата: Памяти там 2Gb, но свободной почти гигабайт | вот тебе и ответ. GC может быть хорош, когда памяти вдвое более требуемой. в покое есть половина, а как начинается нагрузка, GC забирает эту память своим оверхедом. --------- теперь по примеру. У меня нет оксиджена, да и вообще писать на нем, таргетируя под JVM, -- имхо извращение, так что я написал аналогичный код на жабе. Прежде всего скажу, что в твоем коде в итерации забирает не более 30 мегабайт=(12букв*2*10+48(размер объекта) )*100'000. Так не пойдет. Нужно создать близкую к предельной нагрузку. Второе, нужно условиться, сколько же памяти мы разрешаем JVM. Как раз для того, чтобы рассчитать нагрузку. И третье, код , который ты привел на оксиджене, ужасен. Ну зачем пересоздавать StringBuilder? Это замедляет код почти в два раза! За такое нужно увольнять с формулировкой "нахер". JVM, которую я использовал Код: java version "1.8.0_25" Java(TM) SE Runtime Environment (build 1.8.0_25-b18) Java HotSpot(TM) Client VM (build 25.25-b02, mixed mode, sharing) | вот код Код Delphi Проект iDea, как и проект Delphi, с бинарниками доступны по ссылке https://yadi.sk/d/7K10xzn3dpbF2 Я сейчас на слабой машине, поэтому все под XP/32 ключ Xmx400m задает предел кучи 400 Мб, ключ Xms200m задает начальный размер кучи в 200 мегабайт(это дает фору JVM) Код: >java -Xms200m -Xmx400m -Xmn300m -jar untitled.jar 100000 20 1 cached sb 3 args, 20 tries string size:36, element size:408 Press enter to start Memory 387 973 120, using 100 000 elements=39 843Kb(10 % of free heap) total:184 384Kb, free:174 549Kb used? memory:9 834Kb done pass in 266 (13 per 5000 el) done pass in 234 (11 per 5000 el) done pass in 375 (18 per 5000 el) done pass in 235 (11 per 5000 el) done pass in 875 (43 per 5000 el) done pass in 234 (11 per 5000 el) done pass in 1 453 (72 per 5000 el) done pass in 203 (10 per 5000 el) done pass in 235 (11 per 5000 el) done pass in 406 (20 per 5000 el) done pass in 219 (10 per 5000 el) done pass in 968 (48 per 5000 el) done pass in 219 (10 per 5000 el) done pass in 875 (43 per 5000 el) done pass in 219 (10 per 5000 el) done pass in 219 (10 per 5000 el) done pass in 500 (25 per 5000 el) done pass in 218 (10 per 5000 el) done pass in 703 (35 per 5000 el) done pass in 204 (10 per 5000 el) --------------------------------- total:280 120Kb, free:140 528Kb used? memory:139 591Kb, delta:129 757Kb --------------------------------- Done: 8 875 time done; --------------------------------- --------------------------------- 8 875 time collected; --------------------------------- total:280 120Kb, free:276 339Kb used? memory:3 780Kb, delta:-6 054Kb total:280 120Kb, free:208 528Kb used? memory:71 591Kb, delta:61 756Kb | итак, 8.56 секунд для 100K элементов в 20 итерациях замечу на полях, Xmn300m форсирует пул молодых объектов до 300 метров, что увеличивает скорость вдвое: без этого свитча время будет около 16с. теперь Delphi-32 Код: >untitled 100000 20 1 400m Limit Memory to 400MB Acquire priviledge:TRUE handle:1972 Result:TRUE Using elements:100000; Directly Allocated: 52343Kb --------- Done in 719; 35 per 5000 el Done in 703; 35 per 5000 el Done in 719; 35 per 5000 el Done in 719; 35 per 5000 el Done in 687; 34 per 5000 el Done in 719; 35 per 5000 el Done in 719; 35 per 5000 el Done in 703; 35 per 5000 el Done in 718; 35 per 5000 el Done in 704; 35 per 5000 el Done in 703; 35 per 5000 el Done in 718; 35 per 5000 el Done in 704; 35 per 5000 el Done in 718; 35 per 5000 el Done in 719; 35 per 5000 el Done in 703; 35 per 5000 el Done in 703; 35 per 5000 el Done in 719; 35 per 5000 el Done in 719; 35 per 5000 el Done in 703; 35 per 5000 el Done in 734; 36 per 5000 el Done: 14953 | 14.85 секунд. Delphi медленнее Но это -- при том, что размер тестового массива очень мал, в сравнении с размером доступной кучи. По моим подсчетам, яве требуется от 38 для работы с массивом: около 360 байт на 10 строк плюс 48 байт на объект, ну и 4 байта на список. Для Delphi требуется не менее 60мегабайт, из-за оверхеда строк по 12байт на каждую. По моим вычислениям, именно 60 метров использовала JVM, чтобы хранить этот массив. Но!, судя по тесту, JVM держала около 128 мегабайт, когда при завершении внешнего цикла. Так что я удвоил количество элементов: не количество прогонов, а количество элементов. Код: total:286 720Kb, free:147 103Kb used? memory:139 616Kb, delta:129 782Kb --------------------------------- Done: 23 953 time done; --------------------------------- --------------------------------- 23 953 time collected; --------------------------------- total:276 664Kb, free:272 865Kb used? memory:3 798Kb, delta:-6 035Kb total:276 664Kb, free:138 537Kb used? memory:138 126Kb, delta:128 292Kb | 24 секунды, а ведь, должно быть 8.5*2=17 Что же Delphi? Код: почти линейно удвоилось, 30 против 14.85. А тем временем JVM на выходе из цикла сожрала уже 276 664Kb=270 Мб. Что же произошло? Запустим еще раз JVM, с ключом -verbose:gc Код: >java -Xms200m -Xmx400m -Xmn300m -verbose:gc -jar untitled.jar 200000 20 1 cached sb 3 args, 20 tries string size:36, element size:408 Press enter to start Memory 387 973 120, using 200 000 elements=79 687Kb(21 % of free heap) total:184 384Kb, free:174 549Kb used? memory:9 834Kb done pass in 515 (12 per 5000 el) [GC (Allocation Failure) 163904K->19872K(184384K), 0.1618317 secs] done pass in 594 (14 per 5000 el) [GC (Allocation Failure) 183776K->43280K(207296K), 0.3533835 secs] [Full GC (Allocation Failure) 43280K->43280K(207296K), 0.2921022 secs] done pass in 1 125 (28 per 5000 el) [GC (Allocation Failure) , 1.4949862 secs] [Full GC (Allocation Failure) 286719K->49966K(286720K), 0.6880628 secs] done pass in 2 641 (66 per 5000 el) [Full GC (Allocation Failure) 213870K->76672K(267600K), 0.7981438 secs] done pass in 1 219 (30 per 5000 el) [Full GC (Allocation Failure) 240576K->103234K(286720K), 1.0608103 secs] done pass in 1 515 (37 per 5000 el) done pass in 531 (13 per 5000 el) [Full GC (Allocation Failure) 286719K->14523K(286720K), 0.3241174 secs] done pass in 969 (24 per 5000 el) [GC (Allocation Failure) , 1.4938817 secs] [Full GC (Allocation Failure) 286719K->41358K(286720K), 0.6118239 secs] done pass in 2 563 (64 per 5000 el) [Full GC (Allocation Failure) 205262K->67860K(286720K), 0.7302461 secs] done pass in 1 156 (28 per 5000 el) [Full GC (Allocation Failure) 231764K->94394K(286720K), 0.9640220 secs] done pass in 1 406 (35 per 5000 el) [Full GC (Allocation Failure) 258298K->121496K(286720K), 1.2126902 secs] done pass in 1 656 (41 per 5000 el) done pass in 532 (13 per 5000 el) [Full GC (Allocation Failure) 286719K->14524K(286720K), 0.3204992 secs] done pass in 984 (24 per 5000 el) [Full GC (Allocation Failure) 178428K->41359K(286720K), 0.4725040 secs] done pass in 906 (22 per 5000 el) [Full GC (Allocation Failure) 205263K->67861K(286720K), 0.7336974 secs] done pass in 1 172 (29 per 5000 el) [Full GC (Allocation Failure) 231765K->94422K(286720K), 0.9798696 secs] done pass in 1 422 (35 per 5000 el) [Full GC (Allocation Failure) 258326K->121524K(286720K), 1.2060775 secs] done pass in 1 656 (41 per 5000 el) done pass in 532 (13 per 5000 el) [Full GC (Allocation Failure) 286719K->14524K(286720K), 0.3246451 secs] done pass in 968 (24 per 5000 el) --------------------------------- total:286 720Kb, free:147 103Kb used? memory:139 616Kb, delta:129 782Kb --------------------------------- | 15 полных сборок, и еще 4 частичных! А было? А было шесть полных и 4 частичных. Ну а по времени? я запустил jstat -gkutil PID 500 10000 и выходит, что 14.54 секунд было потрачено на сборку, из них 11 - на полную. В случае со 100000 элементов, цифры совсем другие 4.6 / 2.6 Ну а какие цифры будут при 400 000 элементов, когда под данные придется отвести 280 из 400 мегабайт? Код: А Delphi? Код: g:\devsoft\myprojects\lab\untitled\delphi\Win32\Release>untitled 400000 20 1 400m Limit Memory to 400MB Acquire priviledge:TRUE handle:1972 Result:TRUE Using elements:400000; Directly Allocated: 209375Kb --------- Done in 2875; 35 per 5000 el Done in 2922; 36 per 5000 el Done in 2937; 36 per 5000 el Done in 2922; 36 per 5000 el Done in 2875; 35 per 5000 el Done in 2875; 35 per 5000 el Done in 2859; 35 per 5000 el Done in 2860; 35 per 5000 el Done in 2844; 35 per 5000 el Done in 2843; 35 per 5000 el Done in 2860; 35 per 5000 el Done in 2890; 36 per 5000 el Done in 2875; 35 per 5000 el Done in 2907; 36 per 5000 el Done in 2906; 36 per 5000 el Done in 2859; 35 per 5000 el Done in 2875; 35 per 5000 el Done in 2860; 35 per 5000 el Done in 2875; 35 per 5000 el Done in 2875; 35 per 5000 el Done in 2890; 36 per 5000 el Done: 60500 | 60.5 секунд, против 69.6 секунд у JVM. Delphi выигрывает там, где это и нужно: в высоконагруженных сценариях. При этом она потребляет меньше памяти, не больше 300метров, точнее сказать затрудняюсь При этом она работает ровнее, обработка 5000 строк занимает одно и то же время, всегда, н-р у меня 35ms, против разброса 10-70 у JVM. То есть гарантированная отзывчивость у Delphi вдвое выше, чем JVM. |