purebasic.info

PureBasic forum
Текущее время: Ср ноя 21, 2018 9:12 pm

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 60 ]  На страницу Пред.  1, 2, 3, 4  След.
Автор Сообщение
 Заголовок сообщения: Re: Как ускорить конкатенацию?
СообщениеДобавлено: Пн окт 08, 2018 11:00 am 
Не в сети
профессор

Зарегистрирован: Пн июл 22, 2013 11:00 pm
Сообщений: 656
Благодарил (а): 2 раз.
Поблагодарили: 34 раз.
Пункты репутации: 9
balex1978 писал(а):
Сергейчик писал(а):


Я просил вас написать кусочек кода, наверное неполучилось. :roll:
Цитата:
Мож мне написать на асме простую проверку достижения конца строки-проверка на ноль для одного байта(анси) и для двух(уникод), для ускорения просчета длинны.
Только ненужно заворачивать код и в процедуру бросать.
Входящие даные:
адрес начала
адрес конца или длинна участка памяти
берем байт по адресу и сравниваем на ноль кажется TEST
потом проверка результата на ноль jz или jnz уже непомню.
На выходе адрес где нашел ноль, признак конца строки.
Тебе это легко, а мне вспоминать то что лет 20 назад было...


И cmp нормально проверяется не хуже чем тест !TEST word[ebx],0FFFFh
если сразу 2 символа смотреть и пересылать то можно попробывать но скорость скорее вырастит на длинных строках а короткие примерно так и будут примерно по скорости сцепляться. :roll:


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Как ускорить конкатенацию?
СообщениеДобавлено: Пн окт 08, 2018 12:25 pm 
Не в сети
профессор

Зарегистрирован: Вс июл 05, 2009 5:55 pm
Сообщений: 313
Благодарил (а): 1 раз.
Поблагодарили: 10 раз.
Пункты репутации: 0
да я не за то что чем заменить.
Я давно писал на АСМе и вспоминать как это делается да еще подганять под пурик, короче трудновато и долго, а у тебя это пару минут и готово

_________________
искатель истины


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Как ускорить конкатенацию?
СообщениеДобавлено: Вт окт 09, 2018 4:57 pm 
Не в сети
профессор

Зарегистрирован: Пн июл 22, 2013 11:00 pm
Сообщений: 656
Благодарил (а): 2 раз.
Поблагодарили: 34 раз.
Пункты репутации: 9
balex1978 писал(а):
да я не за то что чем заменить.
Я давно писал на АСМе и вспоминать как это делается да еще подганять под пурик, короче трудновато и долго, а у тебя это пару минут и готово

Есть новая задумка по коду(меньше кодовых инструкций асма)но я не могу запустить этот код через стандартную пуриковскую процедуру. :roll:
раньше в предыдущих версиях не было такого. :roll:
Не входя в процедуру код работает,в ней нет!Собственно и у вас видимо по этой причине виснет прога.
Суть видимо в том что ,пурик при компиляции напихивает в стек всякие дополнительные сохранения регистров.
По этой же причине на верное не создашь нормально либу с своими процедурами.
PS:Видимо нужно скомпилить либу на fasme или другом языке программирования(поддерживающем асм) и выложить вам для теста. :roll:


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Как ускорить конкатенацию?
СообщениеДобавлено: Вс окт 14, 2018 9:47 am 
Не в сети
профессор

Зарегистрирован: Вс июл 05, 2009 5:55 pm
Сообщений: 313
Благодарил (а): 1 раз.
Поблагодарили: 10 раз.
Пункты репутации: 0
Сергейчика,знаеш я был немного в шоке когда тестить на скорость редим и получив быстрый результат и уже сделав для тебя прогу, вдруг обнаружил жутчайший тормоз :shock: .

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

Когда доберусь до компа кину куски кода которые тестил.

Если выделять большие куски памяти то работает быстро, переделаю код брошу на форум.

_________________
искатель истины


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Как ускорить конкатенацию?
СообщениеДобавлено: Вс окт 14, 2018 3:37 pm 
Не в сети
профессор

Зарегистрирован: Пн июл 22, 2013 11:00 pm
Сообщений: 656
Благодарил (а): 2 раз.
Поблагодарили: 34 раз.
Пункты репутации: 9
Оказывается виновник ломки стека макрос фасма(он подсовывает push)
Давно бы уж сделал фред типа asmprocedure(что бы нормально сворачивалась,подсветка была и что бы пользователь сам писал что там заносится в стек и как выходить с неё) :roll:


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Как ускорить конкатенацию?
СообщениеДобавлено: Вс окт 14, 2018 9:40 pm 
Не в сети
профессор

Зарегистрирован: Вс июл 05, 2009 5:55 pm
Сообщений: 313
Благодарил (а): 1 раз.
Поблагодарили: 10 раз.
Пункты репутации: 0
Сергейчик Да, о чем ты говориш. Фред хоть и вроде нормальную справку сделал так иногода не понятно, что команда делает, множество команд неимеют примеров.
Ты только посмотри на вкладку - Memory и там не то что половина команд неимею примера, как этим пользоваться там например все пеек и поке ниодного примера.
Мне нужно чегото по интерфейсу в дудущем, а в справке код да еще и НЕРАБОЧИЙ, и Фред говорит о какихто перспективах развития если в это вникнуть..., а как это сначала понять?

С асемблером такая самая лажа, нет нормально примера и толкового текста. Пока с асемблером немного повозился, чегото понимаю, и опять проблема, на разных версиях пурика все по разному.
Вот сейчас к переменной нужно прибавить загадочную приставку 'v_', ну и где про нее хоть слово написано в справке. В какойто старой версии бех этой приставки и все работает.

Вот обещаный код для теста скорости и понимания где тормоз, прикинь так замаскировался, что долго непроявлял себя.
тут две строки указывают на размер прироста буфера масива, одну строку закоментируй,
ln=200;
ln=2000;
а потом проверь со вторым числом,
посмотри какая разница в скорости, жесть, все аналогично как со строками, поэтому все предыдущие тесты хоть и давали впечатляющие результаты, а подводный камень вот где.

тут я всунул две проверки по времени, потому что пурик недает точное время меньше 15 милисек.
Код:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
; при очень малых размерах времени стандартная функция выдает погрешность начииная с ноля и 10-15
; поэтому маленькие размеры времени будут сильно розбегаться
maxfreq.q: a.q: b.q
QueryPerformanceFrequency_(@maxfreq)
maxfreq / 1000
 
 
 
t=ElapsedMilliseconds()
QueryPerformanceCounter_(@a.q);это для вычисления точного времени
 
MemSize=100000
 
ln=200; сколько приращивать за один цикл, скорость дает 0.0037-0.015
ln=2000; 2000 дает у меня 0.799 сек, разница гдето в среднем 53 раза
 
Dim qwe.b(MemSize):
 
 
For i=0 To 1000
    ReDim qwe.b(MemSize2):
    MemSize2+ln
Next
Debug MemSize2-ln;сколько выделено памяти всего
 
QueryPerformanceCounter_(@b.q);это для вычисления точного времени
Debug ElapsedMilliseconds()-t
 
Debug StrD((b - a) / maxfreq, 3) + " - скорость разделения" + #LF$; подсчитываем результат
 
 



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


Вот код который по идее должен работать быстро, НО через даный прикол который описан выше неработает быстро.
Нужно оптимизировать его так, чтобы редим вызывался тогда когда будет выделено достаточно количество памяти, либо число выделения MemSize+40000, должно былть достаточно большим.
:idea: Я думаю просле проверки в условии нужно крутить цикл и увеличивать MemSize+40000 пока достигнет достаточного числа чтобы сделать редим.
Код:
1
2
3
4
5
6
7
8
9
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
;генерим длинную строку
For k=0 To 1000;0
S.s+"123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"
Next
 
Debug Len(S)
 
len_limit=10000000
   MemSize=2000000;0
Dim qwe.b(MemSize)
 
*start = @qwe.b(0) ; AllocateMemory(100000);000);ln2);180000);
 
*stop =*start+MemSize :Debug "сколько выделили памяти:"+Str(MemSize )
 
*mesto_vstavki = *start
 
;DisableDebugger
 
c=ElapsedMilliseconds()
For i=0 To 1000;100 тут может быть большое число
    Debug i
        ln2=StringByteLength(S.s)
    for_start:
   If *stop-(*mesto_vstavki+ln2 )<1:
       If MemSize>len_limit:Debug "достигли лимита, запрос="+Str(MemSize):Break:EndIf
        MemSize+40000
;MemSize+(MemSize/5)
        kursor=*mesto_vstavki-*start; сохраняем положение курсора(на основании смещения относительно адреса начала)
        ReDim qwe.b(MemSize):
        *start = @qwe.b(0); после изменения адреса переносим даные курсора и стартового адреса
        *mesto_vstavki=*start+kursor
        *stop =*start+MemSize
        ;Debug "+++"
        Goto for_start
        Break
    EndIf
   
    *mesto_vstavki2=CopyMemoryString(S.s, @*mesto_vstavki)
Next
 
EnableDebugger
 
Debug Str(i)+" циклов"
Debug "время:"+Str(ElapsedMilliseconds()-C)
 
Debug "всего занято:"+Str(*mesto_vstavki - *start ); получаем размер строки
 


При лимите в 10 метров тратит 2 секунды.

ХОТЯ ЕСТЬ ПРОСТОЕ РЕШЕНИЕ :arrow:
А вот уже при приращивании в десютую часть MemSize+(MemSize/10);40000, результат резко радует всего 157 милисекунд 8) , НУ ЭТО ЖЕ НЕ 2000 :lol: , а вот пятая часть приблизительно гдето 80-110 милисек :D .

ВОТ ПРИ 100МЕТРАХ секунда, а чё нормательно все, думаю можно непариться чегото менять(приращиваю пятую часть памяти).
вот результат теста:
достигли лимита, запрос=110412248
612 циклов
время:1125
всего занято:110270160
22 (это вставил сколько раз вызывается редим)

или при 100 метрах но при такой строке MemSize+(ln2*100) длинна строки в 100 раз больше и этот размер запрашиваю то время снизилось до 750 милисекунд.
сколько выделили памяти:2000000:
достигли лимита, запрос=110108000
611 циклов
время:750
всего занято:110089980
6 запросов на увеличение памяти

Как по мне цель достигнута.
По крайней мере
Сергейчик писал(а):
...данные в виде теста,например окно skintilly,GetGadgetText()
они принимают данные в виде текста и отдают их в буфер в виде строки,вот и нужно для отображения в них
собрать определённую строку .
С учетом взглядов
jobless писал(а):
Самое узкое место в данном случае это не экономить память не наращивать буфер по каждому чиху а найти компромиссный размер для первоначального захвата и последующих.

Есть , еще прикол который подмечен если выделять памяти более 200 метров при лимите, для 300 МБ прога кушает более 600 МБ потом освобождает половину, что у меня привело к небольшому тормозу в пол минуты :? . При 200 метрах такого неувидел.

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

jobless что скажеш по поводу кода, или чегото еще можно оптимизировать?

_________________
искатель истины


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Как ускорить конкатенацию?
СообщениеДобавлено: Вс окт 14, 2018 11:21 pm 
Не в сети
МОДЕРАТОР
Аватар пользователя

Зарегистрирован: Пн апр 09, 2007 4:53 pm
Сообщений: 11325
Благодарил (а): 4 раз.
Поблагодарили: 441 раз.
balex1978 писал(а):
Вот сейчас к переменной нужно прибавить загадочную приставку 'v_', ну и где про нее хоть слово написано в справке.
https://www.purebasic.com/documentation ... edasm.html

balex1978 писал(а):
Если к редиму прибавлять нечасто и достаточно большие размеры, например в среднем около десятой части од того что уже заняли то скорость приемлема.
А причем здесь PB? Это функция HeapReAlloc медленно выделяет память. https://docs.microsoft.com/en-us/window ... eaprealloc

balex1978 писал(а):
Есть , еще прикол который подмечен если выделять памяти более 200 метров при лимите, для 300 МБ прога кушает более 600 МБ потом освобождает половину, что у меня привело к небольшому тормозу в пол минуты
Нужно отключить файл подкачки чтобы туда ничего не попадало.

_________________
Компьютер позволяет решать все те проблемы, которые до его изобретения не существовали. :) :)


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Как ускорить конкатенацию?
СообщениеДобавлено: Пн окт 15, 2018 8:26 pm 
Не в сети
профессор

Зарегистрирован: Вс июл 05, 2009 5:55 pm
Сообщений: 313
Благодарил (а): 1 раз.
Поблагодарили: 10 раз.
Пункты репутации: 0
Пётр спасибо, правда именно в таком варианте как я говорил тут https://www.purebasic.com/documentation ... tives.html
Код:
1
2
3
4
5
6
7
8
9
; x86 assembly example
  ;
  Test = 10
 
  EnableASM
    MOV dword [v_Test],20
  DisableASM
 
  Debug Test ; Will be 20



Цитата:
А причем здесь PB? Это функция HeapReAlloc медленно выделяет память
Ну, от части согласен, без форточек никуда. :)

Пётр писал(а):
balex1978 писал(а):
Есть , еще прикол который подмечен если выделять памяти более 200 метров при лимите, для 300 МБ прога кушает более 600 МБ потом освобождает половину, что у меня привело к небольшому тормозу в пол минуты
Нужно отключить файл подкачки чтобы туда ничего не попадало.
О каком файле подкачки и где и как одключать(надеюсь не виндовский :lol: )

_________________
искатель истины


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Как ускорить конкатенацию?
СообщениеДобавлено: Пн окт 15, 2018 8:47 pm 
Не в сети
МОДЕРАТОР
Аватар пользователя

Зарегистрирован: Пн апр 09, 2007 4:53 pm
Сообщений: 11325
Благодарил (а): 4 раз.
Поблагодарили: 441 раз.
Код:
1
2
3
4
5
6
7
Test = 10
 
EnableASM
MOV Test, 20
DisableASM
 
Debug Test


_________________
Компьютер позволяет решать все те проблемы, которые до его изобретения не существовали. :) :)


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Как ускорить конкатенацию?
СообщениеДобавлено: Пн окт 15, 2018 9:30 pm 
Не в сети
профессор

Зарегистрирован: Вс июл 05, 2009 5:55 pm
Сообщений: 313
Благодарил (а): 1 раз.
Поблагодарили: 10 раз.
Пункты репутации: 0
Странно когда чегото подобное хотел написать, точнее скопировал с рабочего варианта(и это из справки что ну точно должен работать :? ), так ругался и ни в какую незапускался.(наверное пурик тогда перегрелся :lol: ). А тут сразу столько вариантов и главное подозрительно абсолютно все работает. :roll: Спасибо Пётр.

_________________
искатель истины


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Как ускорить конкатенацию?
СообщениеДобавлено: Вт окт 16, 2018 3:10 pm 
Не в сети
профессор

Зарегистрирован: Пн июл 22, 2013 11:00 pm
Сообщений: 656
Благодарил (а): 2 раз.
Поблагодарили: 34 раз.
Пункты репутации: 9
balex1978 писал(а):
Сергейчик Да, о чем ты говориш. Фред хоть и вроде нормальную справку сделал так иногода не понятно, что команда делает, множество команд неимеют примеров.
Ты только посмотри на вкладку - Memory и там не то что половина команд неимею примера, как этим пользоваться там например все пеек и поке ниодного примера.
Мне нужно чегото по интерфейсу в дудущем, а в справке код да еще и НЕРАБОЧИЙ, и Фред говорит о какихто перспективах развития если в это вникнуть..., а как это сначала понять?

С асемблером такая самая лажа, нет нормально примера и толкового текста. Пока с асемблером немного повозился, чегото понимаю, и опять проблема, на разных версиях пурика все по разному.
Вот сейчас к переменной нужно прибавить загадочную приставку 'v_', ну и где про нее хоть слово написано в справке. В какойто старой версии бех этой приставки и все работает.

Вот обещаный код для теста скорости и понимания где тормоз, прикинь так замаскировался, что долго непроявлял себя.
тут две строки указывают на размер прироста буфера масива, одну строку закоментируй,
ln=200;
ln=2000;
а потом проверь со вторым числом,
посмотри какая разница в скорости, жесть, все аналогично как со строками, поэтому все предыдущие тесты хоть и давали впечатляющие результаты, а подводный камень вот где.

тут я всунул две проверки по времени, потому что пурик недает точное время меньше 15 милисек.
Код:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
; при очень малых размерах времени стандартная функция выдает погрешность начииная с ноля и 10-15
; поэтому маленькие размеры времени будут сильно розбегаться
maxfreq.q: a.q: b.q
QueryPerformanceFrequency_(@maxfreq)
maxfreq / 1000
 
 
 
t=ElapsedMilliseconds()
QueryPerformanceCounter_(@a.q);это для вычисления точного времени
 
MemSize=100000
 
ln=200; сколько приращивать за один цикл, скорость дает 0.0037-0.015
ln=2000; 2000 дает у меня 0.799 сек, разница гдето в среднем 53 раза
 
Dim qwe.b(MemSize):
 
 
For i=0 To 1000
    ReDim qwe.b(MemSize2):
    MemSize2+ln
Next
Debug MemSize2-ln;сколько выделено памяти всего
 
QueryPerformanceCounter_(@b.q);это для вычисления точного времени
Debug ElapsedMilliseconds()-t
 
Debug StrD((b - a) / maxfreq, 3) + " - скорость разделения" + #LF$; подсчитываем результат
 
 



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


Вот код который по идее должен работать быстро, НО через даный прикол который описан выше неработает быстро.
Нужно оптимизировать его так, чтобы редим вызывался тогда когда будет выделено достаточно количество памяти, либо число выделения MemSize+40000, должно былть достаточно большим.
:idea: Я думаю просле проверки в условии нужно крутить цикл и увеличивать MemSize+40000 пока достигнет достаточного числа чтобы сделать редим.
Код:
1
2
3
4
5
6
7
8
9
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
;генерим длинную строку
For k=0 To 1000;0
S.s+"123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"
Next
 
Debug Len(S)
 
len_limit=10000000
   MemSize=2000000;0
Dim qwe.b(MemSize)
 
*start = @qwe.b(0) ; AllocateMemory(100000);000);ln2);180000);
 
*stop =*start+MemSize :Debug "сколько выделили памяти:"+Str(MemSize )
 
*mesto_vstavki = *start
 
;DisableDebugger
 
c=ElapsedMilliseconds()
For i=0 To 1000;100 тут может быть большое число
    Debug i
        ln2=StringByteLength(S.s)
    for_start:
   If *stop-(*mesto_vstavki+ln2 )<1:
       If MemSize>len_limit:Debug "достигли лимита, запрос="+Str(MemSize):Break:EndIf
        MemSize+40000
;MemSize+(MemSize/5)
        kursor=*mesto_vstavki-*start; сохраняем положение курсора(на основании смещения относительно адреса начала)
        ReDim qwe.b(MemSize):
        *start = @qwe.b(0); после изменения адреса переносим даные курсора и стартового адреса
        *mesto_vstavki=*start+kursor
        *stop =*start+MemSize
        ;Debug "+++"
        Goto for_start
        Break
    EndIf
   
    *mesto_vstavki2=CopyMemoryString(S.s, @*mesto_vstavki)
Next
 
EnableDebugger
 
Debug Str(i)+" циклов"
Debug "время:"+Str(ElapsedMilliseconds()-C)
 
Debug "всего занято:"+Str(*mesto_vstavki - *start ); получаем размер строки
 


При лимите в 10 метров тратит 2 секунды.

ХОТЯ ЕСТЬ ПРОСТОЕ РЕШЕНИЕ :arrow:
А вот уже при приращивании в десютую часть MemSize+(MemSize/10);40000, результат резко радует всего 157 милисекунд 8) , НУ ЭТО ЖЕ НЕ 2000 :lol: , а вот пятая часть приблизительно гдето 80-110 милисек :D .

ВОТ ПРИ 100МЕТРАХ секунда, а чё нормательно все, думаю можно непариться чегото менять(приращиваю пятую часть памяти).
вот результат теста:
достигли лимита, запрос=110412248
612 циклов
время:1125
всего занято:110270160
22 (это вставил сколько раз вызывается редим)

или при 100 метрах но при такой строке MemSize+(ln2*100) длинна строки в 100 раз больше и этот размер запрашиваю то время снизилось до 750 милисекунд.
сколько выделили памяти:2000000:
достигли лимита, запрос=110108000
611 циклов
время:750
всего занято:110089980
6 запросов на увеличение памяти

Как по мне цель достигнута.
По крайней мере
Сергейчик писал(а):
...данные в виде теста,например окно skintilly,GetGadgetText()
они принимают данные в виде текста и отдают их в буфер в виде строки,вот и нужно для отображения в них
собрать определённую строку .
С учетом взглядов
jobless писал(а):
Самое узкое место в данном случае это не экономить память не наращивать буфер по каждому чиху а найти компромиссный размер для первоначального захвата и последующих.

Есть , еще прикол который подмечен если выделять памяти более 200 метров при лимите, для 300 МБ прога кушает более 600 МБ потом освобождает половину, что у меня привело к небольшому тормозу в пол минуты :? . При 200 метрах такого неувидел.

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

jobless что скажеш по поводу кода, или чегото еще можно оптимизировать?

REDIM это пуриковская команда и когда пишиш код на асме и вставляешь её то стек при входе в такую процедуру ломается значит создать как либу или просто запустить нужное не вникая в ломку стека нет возможности. :roll:
Так примерно накидал код конкатенации на подобии CopyMemoryString ,длинных строках примерно одинаково работает(но ведь возможно что CopyMemoryString апишная и типа приоритет её работы выше?)
собственно код и либа скомпилинная на фасме в архиве.
Код:
1
2
3
4
5
6
7
8
9
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
64
65
66
67
68
69
70
71
72
 
Prototype.i Concatenaciy(*stroka)
Prototype.i Concatenaciy2(*stroka)
Prototype.i SetAdresKursora(Adresbufera)
Prototype.i GetAdresKursora()
 
If OpenLibrary(0,"C:\Users\d\Desktop\Conkatenaciy.dll")
 
  Global Concatenaciy.Concatenaciy=GetFunction(0,"Concatenaciy")
  Global Concatenaciy2.Concatenaciy2=GetFunction(0,"Concatenaciy2")
  Global  SetAdresKursora. SetAdresKursora=GetFunction(0," SetAdresKursora")
  Global  GetAdresKursora. GetAdresKursora=GetFunction(0," GetAdresKursora")
 
  Global ss.s="23455677778"
  Global s.s="                                                                                                                                  "
 
 
   SetAdresKursora(@s)
  Debug @s
  Debug GetAdresKursora()
 
  Concatenaciy(@"3")
   Debug GetAdresKursora()
  Debug s
 
 
 
   
     Else
       Debug "Conkatenaciy.dll не найдена"
       End
  EndIf  
  ;DisableDebugger
 
 
  If OpenWindow(0, 0, 0,600,600, "EditorGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    EditorGadget(0, 8, 8,560, 580)
   
    Global Dim stroka2${1}(300000005)
       SetAdresKursora(@stroka2$(0));во внутреннею перременную длл устанавливаем адрес буфера
       
    MessageRequester("", "Начало теста")
   time = GetTickCount_()
   For q=1 To 1000000;00
         Concatenaciy2(@"25555555555555555555555555555555555555tyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy")
   Next  
   t.l = (GetTickCount_() - time);/1000
  MessageRequester("", "Количество  циклов=" + q + #CR$ + "Время теста= " + t)
        ;SetGadgetText(0,PeekS(@stroka2$(0),-1,#PB_UTF16))
   
  CloseLibrary(0)
 
 
*Pointer = @stroka2$(0)
CopyMemoryString("Hello", @*Pointer);также видимо первоначально ставит адрес(2 аргумента)
 
 
     MessageRequester("", "Начало теста")
   time = GetTickCount_()
   For q=1 To 1000000;00
         CopyMemoryString("25555555555555555555555555555555555555tyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy")
   Next  
   t.l = (GetTickCount_() - time);/1000
  MessageRequester("", "Количество  циклов=" + q + #CR$ + "Время теста= " + t)
  ;SetGadgetText(0,PeekS(@stroka2$(0),-1,#PB_UTF16))
 
 
   ReDim stroka2${1}(0)
 
     Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
  EndIf    
 



Вложения:
конкат.rar [549 байт]
Скачиваний: 8
Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Как ускорить конкатенацию?
СообщениеДобавлено: Вт окт 16, 2018 4:29 pm 
Не в сети
профессор

Зарегистрирован: Вс июл 05, 2009 5:55 pm
Сообщений: 313
Благодарил (а): 1 раз.
Поблагодарили: 10 раз.
Пункты репутации: 0
Сергейчик
Цитата:
Так примерно накидал код конкатенации на подобии CopyMemoryString ,длинных строках примерно одинаково работает
Ну незнаю по поводу одинаково, как по мне так твой цикл с Concatenaciy2() дал 51 секунду, а CopyMemoryString() всего 0.656.

Я тож непойму зачем так CopyMemoryString("Hello", @*Pointer)
@*Pointer
Я думаю что это указатель на указатель

Вот в строковом масиве который ты используеш s${1}(10) он линеен и адреса масива и первого элемента совпадают, а не фиксированой длинны различаются
Код:
1
2
3
4
5
6
7
8
9
10
11
 
Dim s${1}(10):s$(0)="1"
Dim s2$(10):s2$(0)="1"
 
 
Debug @s$(); тут они одинаковы по адресам
Debug @s$(0)
Debug ""
 
Debug @s2$(); а тут список адресов подряд на каждый элемент масива
Debug @s2$(0)

Мож и CopyMemoryString использует типа адрес переменной в которой стоит адрес места куда вставлять текст, ну да наверное так и есть, ему нужно не просто место куда кинуть но еще и изменить содежримое этой переменной(адреса) указать на новое место. На больше у меня мозгов нехватило :roll: .

*Pointer = @stroka2$(0)
CopyMemoryString("Hello", *Pointer);также видимо первоначально ставит адрес(2 аргумента)
есть переменная *Pointer, в нее записываем адрес ОЗУ куда бросать
далее CopyMemoryString использует адрес нашей переменной в которой она берет адрес куда писать текст и после копирования в эту переменную бросает новое значения адреса.
Вот результат для двух и одной буквы:
3473408 это адрес всегда один *Pointer,
268632134 а тут добавлял по две буквы и смешение по 4 байта
268632138
268632142

3473408 это адрес *Pointer тот самый
268632142 а тут добавлял по одной букве и смешение по 2 байта
268632144
268632146

Теперь панятно почему так :)

_________________
искатель истины


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Как ускорить конкатенацию?
СообщениеДобавлено: Вс окт 21, 2018 3:44 pm 
Не в сети
профессор

Зарегистрирован: Пн июл 22, 2013 11:00 pm
Сообщений: 656
Благодарил (а): 2 раз.
Поблагодарили: 34 раз.
Пункты репутации: 9
balex1978 писал(а):
Сергейчик
Цитата:
Так примерно накидал код конкатенации на подобии CopyMemoryString ,длинных строках примерно одинаково работает
Ну незнаю по поводу одинаково, как по мне так твой цикл с Concatenaciy2() дал 51 секунду, а CopyMemoryString() всего 0.656.

Я тож непойму зачем так CopyMemoryString("Hello", @*Pointer)
@*Pointer
Я думаю что это указатель на указатель

Вот в строковом масиве который ты используеш s${1}(10) он линеен и адреса масива и первого элемента совпадают, а не фиксированой длинны различаются
Код:
1
2
3
4
5
6
7
8
9
10
11
 
Dim s${1}(10):s$(0)="1"
Dim s2$(10):s2$(0)="1"
 
 
Debug @s$(); тут они одинаковы по адресам
Debug @s$(0)
Debug ""
 
Debug @s2$(); а тут список адресов подряд на каждый элемент масива
Debug @s2$(0)

Мож и CopyMemoryString использует типа адрес переменной в которой стоит адрес места куда вставлять текст, ну да наверное так и есть, ему нужно не просто место куда кинуть но еще и изменить содежримое этой переменной(адреса) указать на новое место. На больше у меня мозгов нехватило :roll: .

*Pointer = @stroka2$(0)
CopyMemoryString("Hello", *Pointer);также видимо первоначально ставит адрес(2 аргумента)
есть переменная *Pointer, в нее записываем адрес ОЗУ куда бросать
далее CopyMemoryString использует адрес нашей переменной в которой она берет адрес куда писать текст и после копирования в эту переменную бросает новое значения адреса.
Вот результат для двух и одной буквы:
3473408 это адрес всегда один *Pointer,
268632134 а тут добавлял по две буквы и смешение по 4 байта
268632138
268632142

3473408 это адрес *Pointer тот самый
268632142 а тут добавлял по одной букве и смешение по 2 байта
268632144
268632146

Теперь панятно почему так :)

Я тож непойму зачем так CopyMemoryString("Hello", @*Pointer)
;====================================
Просто пурик компилит две процедуры
В первой используя 2аргумента с адресом который также ставит во внутреннею переменную
дале использует уже другую процедуру для копирования с одним аргументом. :wink:
А вот то что он при этом не сохраняет данные пару регистров это не айс если в асме такую процедуру применить в коде,так как нужно будет самому перед каждой такой процедурой их сохранять(и скорее все,так как юзер по умолчанию не знает задействованных регистров)иначе всем данным будет кирдык.
Я же сохранил регистры кроме еах и на выходе остальные останутся неповреждёнными. :roll:
Код:
1
2
3
4
5
6
7
8
9
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
64
65
66
67
68
69
70
71
72
73
 
 
Global Buffer.s=#NULL$;буфер для строкового вывода
Buffer=LSet(Buffer,9999,"CRLF")
Global Pointer = @Buffer
CopyMemoryString("PUREBASIC"+#CRLF$, @Pointer)
!mov dword eax,[v_Pointer];после первой у него уже стоит адрес
!mov dword [ggg],eax
Procedure copy(*s);его вторая процедура
!MOV     ecx,[esp+4]
!TEST   ecx,ecx
!JZ sst
!MOVZX   eax, word ptr ecx
!TEST   ax,ax
!JZ ff
!MOV     edx, ggg
!MOV     edx, [edx]
!JMP     rr
!align 10h
!
!rr:                            
!                                      
!ADD     ecx, 2
!MOV     [edx], ax
!MOVZX   eax, word ptr ecx
!ADD     edx, 2
!TEST   ax, ax
!JNZ     short rr
!XOR     eax, eax
!MOV     [edx], ax
!MOV     ecx, ggg
!MOV     [ecx],edx
!MOV     edx, ggg
!MOV     eax, [edx]
!retn    4
;
!sst:                        
!MOV     eax, ggg
!MOV     eax, [eax]
!retn    4
 ;
!ff:                          
!MOV     ecx, ggg
!MOV     eax, [ecx]
!retn    4
!align 10h
 
DataSection
!ggg:
!dd 0
 EndDataSection
 
EndProcedure
             
             
             
For i=0 To 1000
Copy(@"555    ")
Next
;FreeMemory(Buffer)
 
 
 
If OpenWindow(0, 0, 0,600,600, "EditorGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    EditorGadget(0, 8, 8,560, 580)
 
 
SetGadgetText(0,buffer)
 
 
    Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
  EndIf
 



Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Как ускорить конкатенацию?
СообщениеДобавлено: Пн окт 22, 2018 11:44 am 
Не в сети
профессор

Зарегистрирован: Вс июл 05, 2009 5:55 pm
Сообщений: 313
Благодарил (а): 1 раз.
Поблагодарили: 10 раз.
Пункты репутации: 0
Сергейчик писал(а):
Я тож непойму зачем так CopyMemoryString("Hello", @*Pointer)
Так я вроде написал, что он использует адрес переменной в которой он будет хранить адрес куда копировать текст. Ну АПИ так иногда прикалываются, я долго немог понять чего от меня требуется, пока не увидил реальный код на пурике как это реализовать, пример не могу привести, в голову не приходит чего и где кодил.
Ему нужен адрес не места вставки а адрес переменной в которой хранится адрес места вставки.
Другими словами со стороны CopyMemoryString выглядит так, хоть и по детски напишу, но понятнее:
-мне(ну тобиш команде CopyMemoryString) нужен адрес переменной
-в ней я буду хранить адрес указателя на место вставки
-после того как я вставлю твой текст, эта переменная будет хранить новое место вставки
-и тебе не нужно беспокоится чтобы давать мне точное место вставки, но ты всегда можеш его проверить неиспользуя пеек()
-И для упрощения в код нужно добавить всего навсего один значек - @

это типа аналог в строковом масиве, по адресу содержится только список адресов на строки, видиш получается табличная адресация, как для таблици ИНТ в ПК которая находится в начале ОЗУ, да и есть возможность на АСМе так быстро например переходить на другие куски кода используя JMP[] в скобках у тебя содержится адрес или регистр или регистр со смещением на таблицу по 1, 2 , 4, 8 байт, указал адрес начала таблици перемножил на смещение и прочитав в таблице новый адрес переходим на новый кусок кода, вобщем как это делает INT 0 INT1, INT2... но только тут подпрограмки.
=======================
Сергейчик писал(а):
В первой используя 2аргумента с адресом который также ставит во внутреннею переменную
дале использует уже другую процедуру для копирования с одним аргументом

Я АСМ не смотрел, трудно чегото сказать, может он в первой передает указетель на адрес, который снял с плеч пользователя, чтобы каждый раз ему неставить так CopyMemoryString("Hello", @*Pointer), а упростить CopyMemoryString("Hello") , вот про этот @*Pointer я имею ввиду.

Сергейчик писал(а):
(и скорее все,так как юзер по умолчанию не знает задействованных регистров)иначе всем данным будет кирдык.
Ну так в инструкции написано что можно использовать, а чего обязательно сохранять, я точно помню что можно испоьльзовать ЕАХ, а с другими, надо справку, вот из справки:
"На x86 процессорах доступные энергозависимые регистры: eax, ecx и edx.
Все другие должны всегда сохраняться.
"

_________________
искатель истины


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Как ускорить конкатенацию?
СообщениеДобавлено: Вт окт 23, 2018 2:20 am 
Не в сети
профессор

Зарегистрирован: Пн июл 22, 2013 11:00 pm
Сообщений: 656
Благодарил (а): 2 раз.
Поблагодарили: 34 раз.
Пункты репутации: 9
Ну eax ладно ещё один как переменный а вот ecx счётчик и edx общего назначения можно задействовать до входа в какую не будь процедуру... :roll:
Думал почему у меня прога вылетает при выделении большого объёма памяти,и тут осинило что просто регистр работает как интегер и больше в него число не запихнёшь. :roll:
стал проверять и выяснил что строковый массив как в коде и вовсе с меньшим размером редимится. :evil:
В общем он зависим от загрузки памяти на компе есле её больше свободной то и редимится массив с большим числом элементов.... :roll:
PS:Теперь можно затестить нормально (не должна вылетать прога)
Код:
1
2
3
4
5
6
7
8
9
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
 
Global Dim stroka2${1}(0)
Global MemoryString_BazovyiAdres.i
Global MemoryString_AdresCursora.l
Global MemoryString_AdresLimita.l
Global MemoryString_realwcslen.l
Global MemoryString_smehenie.l
Procedure.i AllocateMemoryString(kolihestvosimvolov.l,Limit.i)
  ReDim stroka2${1}(kolihestvosimvolov)
      MemoryString_realwcslen=kolihestvosimvolov
      MemoryString_smehenie=kolihestvosimvolov
      MemoryString_BazovyiAdres=@stroka2$(0)
      MemoryString_AdresCursora=MemoryString_BazovyiAdres
      MemoryString_AdresLimita=MemoryString_BazovyiAdres+(Limit*2)-2
   ProcedureReturn MemoryString_BazovyiAdres
EndProcedure
Procedure Free_MemoryString()
 ReDim stroka2${1}(0)
EndProcedure
 
 
 !Macro rashireniypamyti;{
 !{
 
  ReDim stroka2${1}(MemoryString_realwcslen)
  MemoryString_BazovyiAdres=@stroka2$(0)
  !add dword [v_MemoryString_AdresCursora],eax
  !add dword [v_MemoryString_AdresLimita],eax
 
 If ArraySize(stroka2$())= -1;MemoryString_realwcslen>530001887
  MessageRequester("", "массив стал  недоступен = -1 на увеличении в "+Str(MemoryString_realwcslen)+"  символов")
 
  End
 EndIf
 !}
;}
Procedure CopyMemoryString_utf16(*s)
    !MOV dword ecx,[esp+4]
    !MOV dword edx,[v_MemoryString_AdresCursora]
    !ysseok6665:
   !CMP word ptr ecx,0h
    !JZ vyhod455
 
    !CMP word ptr ecx+2,0h
    !JZ vyhod445
    ;
    !MOV dword eax,[ecx]
    !MOV dword [edx],eax
    !ADD dword ecx,4
    !ADD dword edx,4
    !JNZ ysseok6665
    ;
    !vyhod445:
   !MOV word ax,[ecx]
    !MOV word [edx],ax
    !ADD dword edx,2  
    !vyhod455:
   !MOV word [edx],0h
    !MOV dword [v_MemoryString_AdresCursora],edx
    ;===========================================
    ;проверка за выход лимита выделенного массива
     !cmp dword [v_MemoryString_AdresLimita],edx
     !ja net;нет невышли за лимит и значит выходим
     ;===========================
 
     ;да мы привысили установленный лимит массива
  !mov dword eax,[v_MemoryString_smehenie]
  !add dword [v_MemoryString_realwcslen],eax
  !add dword eax,eax;
  !add dword [v_MemoryString_AdresLimita],eax
  !mov dword eax,[v_MemoryString_BazovyiAdres]
  !sub dword [v_MemoryString_AdresLimita],eax
  !sub dword [v_MemoryString_AdresCursora],eax
 
 
   !rashireniypamyti;макрос
     
      ;!add dword [v_MemoryString_AdresCursora],eax
      ;!add dword [v_MemoryString_AdresLimita],eax  
   
     !net:
   !retn 4  
EndProcedure
  AllocateMemoryString(100000000,99999000)
 
 
If OpenWindow(0, 0, 0,600,600, "EditorGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    EditorGadget(0, 8, 8,560, 580)
   
    MessageRequester("", "Начало теста")
   time = GetTickCount_()
   For q=1 To 100000000
 
CopyMemoryString_utf16(@"Hн66665555677777")
 
Next
 
   t.d = (GetTickCount_() - time)
  MessageRequester("", "Количество  циклов=" + q + #CR$ + "Время теста= " + t)
   ; SetGadgetText(0,PeekS(@stroka2$(0),-1,#PB_UTF16))
   
 Free_MemoryString()  
   
       Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
  EndIf  
 



Вернуться наверх
 Профиль  
 
Показать сообщения за:  Сортировать по:  
Начать новую тему Ответить на тему  [ Сообщений: 60 ]  На страницу Пред.  1, 2, 3, 4  След.

Часовой пояс: UTC + 3 часа


Кто сейчас на форуме

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 12


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
cron
Создано на основе phpBB® Forum Software © phpBB Group (блог о phpBB)
Сборка создана CMSart Studio
Русская поддержка phpBB