- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
#include <malloc.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
typedef struct {
char * begin;
uint64_t size, data_size;
} str_t;
inline uint64_t max(uint64_t a, uint64_t b) {
return (a > b) ? a : b;
}
inline str_t correct_data_size(str_t str, uint64_t new_size) {
if(str.data_size < new_size) {
str.data_size = (max(str.data_size, new_size) << 1);
str.begin = realloc(str.begin, str.data_size);
}
return str;
}
inline str_t concat(str_t dest, str_t src) {
uint64_t new_size = (dest.size + src.size - 1);
dest = correct_data_size(dest, new_size);
memcpy((dest.begin + dest.size - 1), src.begin, src.size);
dest.size = new_size;
return dest;
}
inline str_t create_str(char * str, uint64_t size) {
return (str_t){.begin = strcat(malloc(size), str), .size = size, .data_size = size};
}
inline void print_str_t(str_t str) {
fprintf(stderr, "str = %ssize = %lu, data_size = %lu\n", str.begin, str.size, str.data_size);
}
uint64_t test(uint64_t star_n, uint64_t n, str_t str, str_t * gstr) {
uint64_t end = (star_n + n);
do {
*gstr = concat(*gstr, str);
char * pos = gstr->begin;
while((pos = strstr(pos, "efgh")))
memcpy(pos,"____",4);
} while((++star_n) != end);
return star_n;
}
int main(void) {
char data[] = "abcdefghefghefgh";
str_t str = create_str(data, sizeof(data));
str_t gstr = create_str("", 1);
time_t starttime = time(NULL);
uint64_t block_c = 0;
while((block_c = test(block_c, ((256/16) * 1024), str, &gstr)) != (((256/16) * 1024) * 20))
printf("%ldsec\t\t%lukb\n",time(NULL)-starttime,gstr.size/1024);
}
Минимально оптимизированный вариант в царь-стиле теста из предыдущего ГК. Никто не увидел и начали на меня кукарекать. То ещё ГК, давайте объясняйте что здесь говно.
kipar 11.07.2013 23:45 # 0
Он выдает у меня результаты процентов на 25 быстрее твоего, при этом вдвое короче. Хотя возможно он просто что-то не то делает, я не проверял.
inkanus-gray 11.07.2013 23:48 # 0
kipar 11.07.2013 23:53 # +1
Вывод теста superhackkiller1997:
Вывод вражеского теста:
Система: intel i3 M370, Win7.
gcc 4.5.2
Тестить под линуксом и под новым gcc лень.
superhackkiller1997 12.07.2013 00:06 # 0
Вывод вражеского теста:
Система: 3.8.6-gentoo #2 SMP PREEMPT Sun Apr 21 15:21:31 UTC 2013 x86_64 Intel(R) Core(TM)2 CPU 6320 @ 1.86GHz GenuineIntel GNU/Linux
gcc версия 4.9.0-pre9999 20130708 (experimental) commit fda9f85fe1d91f9b64ebf10816e3365aa01c5a74 (Gentoo 4.9.0_pre9999)
И чем дальше - тем больше он сливать будет, а так сливает он просто в хлам, но ты увидишь это лишь на тысячах секунд, ибо 99.93% делается тот вайл.
kipar 12.07.2013 01:01 # +1
superhackkiller1997 12.07.2013 01:22 # 0
Берём, выкидываем реплейс и смотрим за сколько оно делает вставки:
Мой пацанский вариант:
Это говно:
superhackkiller1997 12.07.2013 01:27 # 0
Иное:
kipar 12.07.2013 01:38 # 0
kipar 12.07.2013 01:44 # +1
superhackkiller1997 12.07.2013 01:50 # 0
И да, это не оригинальный код - я этого кода даже не видел, оригинал в ГК ниже.
kipar 12.07.2013 01:58 # +1
superhackkiller1997 12.07.2013 02:04 # 0
Далее, это не даст перфоманса, ибо strstr() так работает.
Разница уже в пределах погрешности - поэтому профита нет.
kipar 12.07.2013 02:17 # 0
superhackkiller1997 12.07.2013 02:26 # 0
Покажи -S - я погляжу.
kipar 12.07.2013 03:04 # 0
Выхлоп gcc:http://pastebin.com/LBcp9x7F
Их код: http://pastebin.com/Ki0Kc5y3
Выхлоп gcc: http://pastebin.com/CxKKrT0S
superhackkiller1997 12.07.2013 04:52 # −2
Значит это что-то у вас там нитого.
kipar 12.07.2013 11:34 # +1
bormand 12.07.2013 05:23 # +1
Да, согласен Но там есть и баг - этот алгоритм никогда не заменяет первые 4 символа строки. На этой задаче канает, на более общей - хуй. Если хочется сделать +4, то это надо делать после memcpy, а не в аргументе strstr's.
kipar 12.07.2013 11:31 # 0
superhackkiller1997 12.07.2013 01:55 # 0
Мой:
Его:
Значит я в прошлый раз чего-то нитого намерил. Пропитушился.
superhackkiller1997 11.07.2013 23:58 # 0
anonimb84a2f6fd141 12.07.2013 00:24 # −1
bormand 12.07.2013 05:47 # +1
Код superhackkiller1997, в котором uint64_t заменены на uint32_t:
3sec 256kb
10sec 512kb
22sec 768kb
39sec 1024kb
61sec 1280kb
88sec 1536kb
120sec 1792kb
Код с ideone:
2sec 256kb
10sec 512kb
26sec 768kb
50sec 1024kb
81sec 1280kb
116sec 1536kb
157sec 1792kb
И чем дальше - тем больше разница. По идее из-за realloc'а на каждую строку.
superhackkiller1997 12.07.2013 05:53 # −1
superhackkiller1997 12.07.2013 22:04 # 0
Тормазит тут strcat(), ибо стоит n в лучшем случае, n^3 в худшем. два strlen() + один мемкопи. У меня же только мемкопи, без стрлена. У меня конкатенация стоит O(1) в данном случае. В твоей портянке оно стоит в районе n.
blackhearted 15.07.2013 13:42 # 0
guest 13.07.2013 01:56 # −6
superhackkiller1997 11.07.2013 23:56 # −1
Он медленнее моего кода по определению, даже если выпилить тот вайл, о котором я сказал выше - у меня идеальная реализация, а то говно.
Поэтому у тебя там что-то врёт.
blackhearted 15.07.2013 13:43 # 0
superhackkiller1997 12.07.2013 00:08 # 0
myaut 12.07.2013 01:36 # +2
Деаллокация для анскиллед питухов?
superhackkiller1997 12.07.2013 01:58 # +1
bormand 12.07.2013 06:21 # +1
superhackkiller1997 12.07.2013 16:30 # 0
an0nym 12.07.2013 06:31 # +1
guest 12.07.2013 09:56 # 0
TarasB 12.07.2013 11:42 # +2
bormand 12.07.2013 12:00 # 0
http://raid6.com.au/~onlyjob/posts/arena/
Задача звучит примерно так - до посинения приклеивать в конец строки "ghjk", а затем пробегая по всей строке(!) заменять "ghjk" на "____".
guest 12.07.2013 12:08 # 0
DBdev 12.07.2013 14:04 # 0
myaut 12.07.2013 17:12 # 0
anonimb84a2f6fd141 12.07.2013 17:16 # 0
myaut 13.07.2013 15:09 # 0
str.replace
Python 2.7.2 @ Core i7-860
bormand 13.07.2013 17:33 # 0
anonimb84a2f6fd141 13.07.2013 19:25 # 0
bormand 13.07.2013 19:34 # 0
inkanus-gray 13.07.2013 22:34 # 0
Никого не запутал?
anonimb84a2f6fd141 13.07.2013 23:49 # 0
inkanus-gray 14.07.2013 03:32 # 0
anonimb84a2f6fd141 14.07.2013 04:00 # 0
myaut 14.07.2013 00:04 # 0
Ибо O(n) обозначает, что время выполнения равно C * n, где C та самая константа. В нашем случае - где-то O(e^n), что соответствует C1 * e ^ (C2 * n), и речь идет о C1
anonimb84a2f6fd141 14.07.2013 04:02 # 0
П.С. Ты не мяут с сырцов?
myaut 14.07.2013 08:11 # +2
anonimb84a2f6fd141 14.07.2013 18:14 # 0
Получается, С2 будет гораздо важнее С1. Разница между n^x и n^(x/2) будет гораздо больше, чем между k*(n^x) и n^x.
anonimb84a2f6fd141 14.07.2013 01:02 # 0
anonimb84a2f6fd141 12.07.2013 17:19 # 0
Блядь они ебанаты, ну ясен хуй ява будет сливать, там нет никаких оптимизаций и будет O(n^2). Там совсем макаки сидят, которые про StringBuilder не слышали?
Кстати, а почему в яве нет оптимизаций? В цпитоне это давно оптимизировано, хотя лучше список / bytearray.
> а затем пробегая по всей строке(!)
А, так O(n^2) там запрограммировано.
superhackkiller1997 12.07.2013 18:13 # 0
Даже ущербная реализация ан сишке, которая O(n^3) - мои стрки стоят меньше, чем O(n) - во всех языках тоже. Реплейс в сишке сделан по-ущербснки - во всех других ЯП это реализованно лучше.
Но даже несмотря на тотальный слив по O() у сишки - она в хламину рвёт всё живое.
anonimb84a2f6fd141 12.07.2013 20:45 # 0
superhackkiller1997 12.07.2013 21:14 # 0
gstr=realloc(gstr,lngth+str_len); - стоит n, но тут не стоит.
strcat(gstr,str); - стоит n^2.
while(pos=strstr(pos,"efgh")) memcpy(pos,"____",4); - стоит в районе n, ералеьно чуть больше.
bormand 12.07.2013 22:33 # 0
Не, strcat тупо O(n), где n суммарная длина строк. Тут же сначала пробегают по одной строке, замеряя ее длину, а потом пробегают по другой, копируя символы. O(n^2) было бы если бы там был бы двойной цикл.
Твой код в целом все-таки O(n^2).
superhackkiller1997 12.07.2013 23:05 # 0
Да, некоторые вариации strcat() работают почти за O(n). Но они по вашему не безопасны, ибо они могут залезть в память за концом вашей строки. Хотя почему могут - они залезают.
Безопасный strcat() стоит дорого.
А так да, ты даже в чём-то прав. И да, копирование стоит O(n*2), а не n.
bormand 12.07.2013 23:12 # +1
O(n+m) если быть точным, где n и m длины исходных строк.
> Мой код O(n).
У тебя внешний цикл, растущий пропорционально n. И внутри него цикл поиска\замены, который тоже растет пропорционально n. Отсюда O(n^2). Если построишь график по числам, которые выводит код - должно получиться что-то типа параболы.
superhackkiller1997 12.07.2013 23:25 # 0
O(min(n, m)*2). Это понимают все, поэтому n*2.
Внешний цикл мы не учитываем - мы учитываем общую сложность конката и реплейса.
bormand 12.07.2013 23:20 # 0
bormand 12.07.2013 23:07 # 0
superhackkiller1997 12.07.2013 23:22 # −1
bormand 12.07.2013 21:52 # +3
Так тут задача специально хитровыебанная, чтобы яву слить (и любой другой язык с иммутабельными строками)... Заметь как построены итерации - добавляем чуть-чуть хуйни, прогоняем реплейс по всей строке. В итоге на каждом шаге клеятся всего 2 строки, стрингбилдер здесь не поможет.
anonimb84a2f6fd141 13.07.2013 23:50 # 0
crastinus 12.07.2013 20:46 # 0
Вместо
pos=gstr;
сделал
pos=gstr+(i-1)*16;
а в тесте c++ сделал
end = (i-1)*16
И все вышло как я и полагал C:
0sec 256kb
1sec 512kb
2sec 768kb
4sec 1024kb
7sec 1280kb
12sec 1536kb
16sec 1792kb
21sec 2048kb
29sec 2304kb
39sec 2560kb
52sec 2816kb
68sec 3072kb
85sec 3328kb
105sec 3584kb
127sec 3840kb
150sec 4096kb
cpp:
0sec 256kb
0sec 512kb
0sec 768kb
1sec 1024kb
1sec 1280kb
1sec 1536kb
1sec 1792kb
1sec 2048kb
1sec 2304kb
1sec 2560kb
1sec 2816kb
1sec 3072kb
1sec 3328kb
1sec 3584kb
1sec 3840kb
1sec 4096kb
без потери качества обработки строки, лол
superhackkiller1997 12.07.2013 21:15 # −3
crastinus 12.07.2013 21:20 # +1
В том то и дело, что ничего не потерялось. Мой код просто не перебирает лишние мегабайты, чтобы заменить 12 байт.
>ты идиот
будь проще затупок
superhackkiller1997 12.07.2013 21:29 # −2
Ты упоролся? Животное. Ты вообще понимаешь, что такое бенчмарк? Животное, ты понимаешь, что такое реплейс, животное? Реплейс обязан пройти ВСЮ строку, животное.
http://pastebin.com/XxY3urQx - на тебе, питушок:
>будь проще затупок
Питушок должен знать своё место.
crastinus 12.07.2013 21:53 # 0
superhackkiller1997 12.07.2013 21:55 # −3
crastinus 12.07.2013 22:04 # −1
Вот дай ссылку на код, где он выводит полностью строки до и после изменения. Выведи мне хотя бы 4 строки так. М.б. если тупо скопировать из libc и сделать как инлайн, хотя не надо нихрена так делать, т.к. они нормально скомпонуются как функции, тогда может будет нормально работать.
В течении часа не дашь ссылку на адекватный вывод засчитываю слив.
superhackkiller1997 12.07.2013 22:07 # −1
Ты несёшь какую-то херню, животинушка. Ты уже тотально слился и можешь не кукарекать.
crastinus 12.07.2013 22:13 # 0
http://ideone.com/6YNxIo
bormand 12.07.2013 22:15 # 0
crastinus 12.07.2013 22:19 # 0
bormand 12.07.2013 22:19 # 0
crastinus 12.07.2013 22:21 # 0
bormand 12.07.2013 22:04 # +1
Тем самым ты нарушил условие задачи, читер хренов. Прочти уже оригинальную статью, чтобы понять почему все пишут такую херню, вместо того чтобы 1 раз прогнать реплейс после всех конкатенаций.
bormand 12.07.2013 22:11 # 0
crastinus 12.07.2013 22:19 # 0
bormand 12.07.2013 22:21 # 0
P.S. У царя, кстати, память выделяется примерно как в с++. Не на каждую конкатенацию.
defecate-plusplus 12.07.2013 22:24 # 0
кому не лень - сличите указатели после каждого роста
bormand 12.07.2013 22:27 # +1
guest 12.07.2013 22:30 # −5
crastinus 12.07.2013 21:23 # 0
Cause c++ superior in everything
superhackkiller1997 12.07.2013 21:30 # −2
crastinus 12.07.2013 21:53 # +3
superhackkiller1997 12.07.2013 21:55 # −3
crastinus 12.07.2013 22:01 # 0
superhackkiller1997 12.07.2013 22:08 # −3
crastinus 12.07.2013 22:31 # 0
guest 13.07.2013 01:56 # −7
guest 12.07.2013 18:45 # −6
]Делаю минеты
wvxvw 12.07.2013 21:19 # 0
Что-то мне аж прям как-то не по себе... как-то очень по-читерски это :)
wvxvw 12.07.2013 21:37 # 0
И код с сайта:
Компилировал с -O3 gcc 4.6.3 Линукс 64 бит.
crastinus 12.07.2013 21:57 # −1
superhackkiller1997 12.07.2013 21:59 # 0
wvxvw 12.07.2013 22:33 # 0
crastinus 12.07.2013 22:35 # 0
bormand 12.07.2013 22:42 # 0
superhackkiller1997 12.07.2013 22:58 # −1
Так действуют 99% питушков, пытаясь доказать, что мой код не работает.
crastinus 12.07.2013 23:01 # −1
superhackkiller1997 12.07.2013 23:28 # −1
Поэтому Си - это ЯП, а остальные ЯП - это говно. Исключения с вариациями - это плюсы и асм.
bormand 12.07.2013 23:57 # +2
Да в сишной либе на строки вообще хуй положен ;) Строки с ноликом на конце, это, пожалуй, самый эпичный фейл. Набор функций в той же либц - коллекция разношерстного говна, часть из которого "забывает" приклеить тот самый нолик... Если не писать свои функции, и не использовать сторонние либы, работать со строками очень неудобно. С этим можно поспорить, но это факт.
С другой стороны - сишка и проектировалась как минималистичный язык, не навязывающий своих законов. И для тех мест, где сишка действительно нужна - от этого только профит.
anonimb84a2f6fd141 13.07.2013 00:07 # 0
bormand 13.07.2013 00:13 # +2
anonimb84a2f6fd141 13.07.2013 01:26 # +1
Вот тот ответ, которого я ждал :)
superhackkiller1997 13.07.2013 00:22 # −1
bormand 13.07.2013 00:54 # +2
А вот с точки зрения удобства нультерминейтед строки говно. Постоянная возня с ручным хранением длин, strlen'ом, дописыванием ноликов к strncpy и т.п.
superhackkiller1997 13.07.2013 01:21 # +1
Сейчас это не сильно актуально, но в некоторых случаях си-строки реально удобней.
Даже длинну строки мы знаем и т.п. strlen() не нужен, копирование не нужно - всё быстро, круто - в кеше.
guest 13.07.2013 01:57 # −5
wvxvw 13.07.2013 01:40 # +2
Почти!
inkanus-gray 12.07.2013 23:52 # +1
exec.tm.sec str.length
1 sec 256 kb
6 sec 512 kb
14 sec 768 kb
25 sec 1024 kb
40 sec 1280 kb
58 sec 1536 kb
80 sec 1792 kb
105 sec 2048 kb
133 sec 2304 kb
166 sec 2560 kb
201 sec 2816 kb
240 sec 3072 kb
282 sec 3328 kb
327 sec 3584 kb
376 sec 3840 kb
428 sec 4096 kb
На той же машине немодифицированный cpp_test.cpp выдал:
exec.tm.sec str.length
4sec 256kb
15sec 512kb
34sec 768kb
60sec 1024kb
95sec 1280kb
138sec 1536kb
^C
Царский код выдал:
3sec 256kb
11sec 512kb
25sec 768kb
44sec 1024kb
70sec 1280kb
101sec 1536kb
138sec 1792kb
^C Результат:
superhackkiller1997 13.07.2013 00:19 # −1
3.8.6-gentoo #2 SMP PREEMPT Sun Apr 21 15:21:31 UTC 2013 x86_64 Intel(R) Core(TM)2 CPU 6320 @ 1.86GHz GenuineIntel GNU/Linux
Твоё говно в 10раз медленнее, чем на моём коре2 за 500рублей. Меня твои говнобенчи не интересуют - вбрасывай и дальше, сравнивая на говноОСи, говно х86 и говноконпеляторе.
inkanus-gray 13.07.2013 00:22 # 0
superhackkiller1997 13.07.2013 00:23 # −1
Цифры того, что показал борманд:
inkanus-gray 13.07.2013 00:28 # 0
http://govnokod.ru/13408#comment187596
http://govnokod.ru/13408#comment187601
http://govnokod.ru/13408#comment187603
http://govnokod.ru/13408#comment187608
http://govnokod.ru/13408#comment187839
Я хочу уточнить, в каком состоянии сейчас код.
superhackkiller1997 13.07.2013 00:30 # −1
bormand 13.07.2013 00:32 # 0
superhackkiller1997 13.07.2013 00:33 # 0
inkanus-gray 13.07.2013 00:43 # 0
Этот код?
На моей маздайке и недопроцессоре:
exec.tm.sec str.length
3sec 256kb
12sec 512kb
29sec 768kb
Ещё раз для сравнения царский:
3sec 256kb
11sec 512kb
25sec 768kb
И ещё раз для сравнения Delphi с prefixed-length strings:
exec.tm.sec str.length
1 sec 256 kb
6 sec 512 kb
14 sec 768 kb
superhackkiller1997 13.07.2013 00:57 # 0
Это производительность памяти в районе второго пня. На чём ты собирал мой код, какая у тебя либц, где исходники strstr().
И да, менять 64битные инты на 32битные тебя не учили?
http://pastebin.com/XxY3urQx - собери это - это просто конкатенация без реплайса - выпили из своего кода реплейс, оставь просто добавление в конец строки.
inkanus-gray 13.07.2013 01:16 # +2
0sec 256kb
0sec 512kb
0sec 768kb
0sec 1024kb
...
4sec 239616kb
...
После замены интов:
0sec 256kb
1sec 512kb
...
3sec 239616kb
...
Delphi без реплейса:
0 sec 256 kb
...
1 sec 239616 kb
...
2 sec 277248 kb
Итого: мне нужно оптимизировать поиск и замену.
Кстати, вариант с zero-ended strings + ReallocMem в Delphi тормозил страшно:
9 sec 256 kb
Короче, дальше можно не смотреть.
Вывод такой: строки с завершающим нулём не нужны, потому что конкатенация строк с префиксом длины работает быстрее.
superhackkiller1997 13.07.2013 01:07 # 0
http://pastebin.com/5N7XBD45 - вот тебе вариант на 64/32 битных интах в зависимости от типа х86.
guest 13.07.2013 01:57 # −5