purebasic.info

PureBasic forum
Текущее время: Вт ноя 20, 2018 6:49 pm

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




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

Зарегистрирован: Пн июл 22, 2013 11:00 pm
Сообщений: 655
Благодарил (а): 2 раз.
Поблагодарили: 34 раз.
Пункты репутации: 9
Собственно нужно собрать в строку много подстрок!
можно ли как то по другому выделять буфер для строки кроме stroka=LSet(stroka,rashetindexa,"") :?:
Может через выделенную память собирать а после peeks() :?: :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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
 
Global stroka.s=#NULL$
Global rashetindexa.l=0
Global index.l=0
 
Procedure Sozdanie_bufera_Strooki(razmer.l)
  stroka=LSet(stroka,razmer+1,"")
  rashetindexa=razmer
EndProcedure
Procedure.s Set_bufer_Stroka(*strokka)
 
  ;!mov dword eax,[v_rashetindexa]
  ;!sub dword eax,1000
  ;!cmp dword eax,[v_index]
  ;!ja net
  If index>rashetindexa-100
  rashetindexa+10000
  ;!add dword [v_rashetindexa],10000
    stroka=LSet(stroka,rashetindexa,"")
  EndIf
 
  ;!net:
  !PUSH esi
  !PUSH edi
  !mov dword edi,[v_stroka]
  !mov dword esi,[p.p_strokka+8]
  !add dword edi,[v_index]
!ysseok66:
   !cmp word[esi],0h
   !jz skopirovali66
  !mov word ax,[esi]
  !mov word[edi],ax
  !add dword esi,2
  !add dword edi,2
  !add dword [v_index],2
  !jmp ysseok66
  !skopirovali66:
!mov word[edi],0h
  !pop edi
  !pop esi
  ProcedureReturn stroka
EndProcedure
Procedure.s Get_bufer_Stroka()
  ProcedureReturn stroka
EndProcedure
 
Sozdanie_bufera_Strooki(10000)
 
 
;Debug Set_bufer_Stroka(@"uhgttfghj*stroca")
;Debug index
;Set_bufer_Stroka(@"uhgttfghj*stroca")
 
;MessageRequester("",Get_bufer_Stroka(0))
;Debug stroka
;Debug index
 
 
 
Global mov_.s="m555"
Global mov1.s="m645543"
   Set_bufer_Stroka(@"m645543");
 
 
 
 
   MessageRequester("", "Начало теста"  )
   time = GetTickCount_()
   For q=0 To 10000
mov1+mov_
   Next
   t.d = (GetTickCount_() - time)/1000
   MessageRequester("", "Количество  циклов=" + q + #CR$ + "Время теста= " + t)
 
MessageRequester("", "Начало теста"  )
time = GetTickCount_()
   For q=0 To 10000
Set_bufer_Stroka(@mov_)
   Next
   t.d = (GetTickCount_() - time)/1000
   MessageRequester("", "Количество  циклов=" + q + #CR$ + "Время теста= " + t)
;Debug Get_bufer_Stroka(0)
Debug stroka
Debug index
 
;MessageRequester("",Get_bufer_Stroka())
 



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

Зарегистрирован: Вт апр 14, 2009 7:22 pm
Сообщений: 362
Благодарил (а): 1 раз.
Поблагодарили: 13 раз.
Пункты репутации: 0
Просьба к моему вопросу отнестись серьёзно.
Собственно вопрос:
Зачем, для чего, какая инфа на входе и что с ней предполагается делать дальше?

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


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

Зарегистрирован: Пн апр 09, 2007 4:53 pm
Сообщений: 11325
Благодарил (а): 4 раз.
Поблагодарили: 441 раз.
Сергейчик писал(а):
Собственно нужно собрать в строку много подстрок!
Из справки.
Код:
1
2
3
4
5
6
7
8
*Buffer = AllocateMemory(1000)
*Pointer = *Buffer
CopyMemoryString("Hello", @*Pointer)
CopyMemoryString(" World")  ; This one will be put just after "Hello"
*Pointer-4                  ; Come back from 2 characters unicode (on the 'l' of 'World')
CopyMemoryString("LD")      ; Finally the last two letters will be uppercase
Debug PeekS(*Buffer)
 

Выход за пределы буфера не проверяется, и нужно самому за этим следить. Purifier в этом поможет.

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


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

Зарегистрирован: Пн июл 22, 2013 11:00 pm
Сообщений: 655
Благодарил (а): 2 раз.
Поблагодарили: 34 раз.
Пункты репутации: 9
Пётр писал(а):
Сергейчик писал(а):
Собственно нужно собрать в строку много подстрок!
Из справки.
Код:
1
2
3
4
5
6
7
8
*Buffer = AllocateMemory(1000)
*Pointer = *Buffer
CopyMemoryString("Hello", @*Pointer)
CopyMemoryString(" World")  ; This one will be put just after "Hello"
*Pointer-4                  ; Come back from 2 characters unicode (on the 'l' of 'World')
CopyMemoryString("LD")      ; Finally the last two letters will be uppercase
Debug PeekS(*Buffer)
 

Выход за пределы буфера не проверяется, и нужно самому за этим следить. Purifier в этом поможет.

Что то ReAllocateMemory() робит и новые адреса назначает(а старые что так и остаются или это они тупо в памяти просто не чищены и помечены как негодные?)
Может как через api(там всякие глобальные кучи и....?) или либы сишной?
PS:А то строкам в отладчике не комфортно....... :wink:
Код:
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
 
Global razmerbufera.l=10000
 
*Buffer = AllocateMemory(razmerbufera)
Debug *Buffer
Pointer=*Buffer
 
Global *r
For i=0 To 2000
  ;Debug Pointer
 
  If Pointer >(*Buffer+razmerbufera)-1000
        Pointer =Pointer-*Buffer
        razmerbufera+10000
        *r=*Buffer
        *Buffer= ReAllocateMemory(*Buffer,razmerbufera)
        ;FreeMemory(*r)
       Pointer =Pointer+*Buffer
     Debug "Смена адреса"  
     Debug *Buffer
     Debug Pointer
     Debug "========"  
 
  EndIf
CopyMemoryString("Hello>>>>>", @Pointer)
Next
 Debug PeekS(*r)
Debug "новай адрес"
Debug PeekS(*Buffer)
 
FreeMemory(*Buffer)
 



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

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

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



Тут такое дело что мы смотрим всякие данные в виде теста,например окно skintilly,GetGadgetText()
они принимают данные в виде текста и отдают их в буфер в виде строки,вот и нужно для отображения в них
собрать определённую строку .
допустим взять текст "ABVGDEIKA_ABVGDEIKA" и из него допустим нужно получить другой текст по номеру байта "10,12,13,84 и т.д" вобщем интерпретировать всякие строки.в разные свои значения.
А так как информация выводится в виде строки то сначала её быстро собрать..... :roll:
PS:Последовательно собирается в строку многие кусочки подстрок вот и нужно что бы они быстро собирались через указатель памяти (видно же что быстрей идёт конкатенация).


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

Зарегистрирован: Вт дек 05, 2006 8:46 am
Сообщений: 6399
Благодарил (а): 21 раз.
Поблагодарили: 200 раз.
Пункты репутации: 52
С буржуйского форума разные операции со строками, (там эта тема не раз поднималась), говорят, что быстро

Код:
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
DisableDebugger
 
Structure StringBuilderItem
  item.s
  size.i
EndStructure
 
Structure StringBuilder
  size.i
  count.i
  List item.StringBuilderItem()
EndStructure
 
Procedure StringBuilder_Add(*sb.StringBuilder,itm$)
  nSize = StringByteLength(itm$)
  *sb\size = *sb\size + nSize
  *sb\count = *sb\count + 1
  AddElement(*sb\item())
  *sb\item()\item = itm$
  *sb\item()\size = nSize
EndProcedure
 
Procedure StringBuilder_Clear(*sb.StringBuilder)
  ClearList(*sb\item())
  *sb\count = 0
  *sb\size = 0
EndProcedure
 
Procedure StringBuilder_Free(*sb.StringBuilder)
  ClearList(*sb\item())
  FreeStructure(*sb)
EndProcedure
 
Procedure.s StringBuilder_Get(*sb.StringBuilder,idx.i)
  If idx > *sb\count - 1
    ProcedureReturn ""
  EndIf
  SelectElement(*sb\item(),idx)
  ProcedureReturn *sb\item()\item
EndProcedure
 
Procedure.s StringBuilder_GetChunk(*source,nSize)
  *bfr = AllocateMemory(nSize + 4)
  CopyMemory(*source,*bfr,nSize)
  out$ = PeekS(*bfr)
  FreeMemory(*bfr)
  ProcedureReturn out$
EndProcedure
 
Procedure.i StringBuilder_GetLongest(*sb.StringBuilder)
  nLongest = 0
  ResetList(*sb\item())
  While NextElement(*sb\item())
    If *sb\item()\size > nLongest
      nLongest = *sb\item()\size
    EndIf
  Wend
  ProcedureReturn nLongest
EndProcedure
 
Procedure StringBuilder_Insert(*sb.StringBuilder,idx,val$)
  If idx > *sb\count - 1 : ProcedureReturn : EndIf
  SelectElement(*sb\item(),idx)
  InsertElement(*sb\item())
  nSize = StringByteLength(val$)
  *sb\count = *sb\count + 1
  *sb\size = *sb\size + nSize
  *sb\item()\item = val$
  *sb\item()\size = nSize
EndProcedure
 
Procedure.s StringBuilder_Join(*sb.StringBuilder,delim$="")
  nSizeDelim = StringByteLength(delim$)
  nAdder = ListSize(*sb\item()) * nSizeDelim
  *bfr = AllocateMemory(*sb\size + nAdder + 4)
  nLoops = 0
  ResetList(*sb\item())
  While NextElement(*sb\item())
    PokeS(*bfr+nPos,*sb\item()\item,*sb\item()\size)
    nPos = nPos + *sb\item()\size
    nLoops = nLoops + 1
    If nSizeDelim > 0 And nLoops < *sb\count
      PokeS(*bfr+nPos,delim$,nSizeDelim)
      nPos = nPos + nSizeDelim
    EndIf
  Wend
  out$ = PeekS(*bfr,*sb\size)
  FreeMemory(*bfr)
  ProcedureReturn out$
EndProcedure
 
Procedure.i StringBuilder_New()
  *s.StringBuilder = AllocateStructure(StringBuilder)
  *s\count = 0
  *s\size = 0
  ProcedureReturn *s
EndProcedure
 
Procedure StringBuilder_Remove(*sb.StringBuilder,idx.i)
  If idx > *sb\count - 1 : ProcedureReturn : EndIf
  SelectElement(*sb\item(),idx)
  *sb\count = *sb\count - 1
  *sb\size = *sb\size - *sb\item()\size
  DeleteElement(*sb\item())
EndProcedure
 
Procedure StringBuilder_Replace(*sb.StringBuilder,idx.i,val$)
  If idx > *sb\count - 1 : ProcedureReturn : EndIf
  SelectElement(*sb\item(),idx)
  *sb\size = *sb\size - *sb\item()\size
  nSize = StringByteLength(val$)
  *sb\size = *sb\size + nSize
  *sb\item()\item = val$
  *sb\item()\size = nSize
EndProcedure
 
Procedure.i StringBuilder_Split(val$,delim$)
  *sb = StringBuilder_New()
  nSizeDel = StringByteLength(delim$)
  nSizeVal = StringByteLength(val$)
  If nSizeDel = 0 Or nSizeVal = 0
    ProcedureReturn *sb
  EndIf
  nEnd = 0 : nLen = 0 : nStart = 0
  While nEnd <= nSizeVal
    If CompareMemory(@val$+nEnd,@delim$,nSizeDel)
      StringBuilder_Add(*sb,StringBuilder_GetChunk(@val$+nStart,nLen))
      nEnd = nEnd + nSizeDel
      nStart = nEnd
      nLen = 0
    Else
      nEnd = nEnd + 1
      nLen = nLen + 1
    EndIf
  Wend
  If nLen > 0
    StringBuilder_Add(*sb,StringBuilder_GetChunk(@val$+nStart,nLen))
  EndIf
  ProcedureReturn *sb
EndProcedure
 
items=5000
joinstart.q=ElapsedMilliseconds()
*s.StringBuilder = StringBuilder_New()
For a=1 To items
  StringBuilder_Add(*s,Str(a)+Space(100))
Next
s$=StringBuilder_Join(*s,"|")
joinend.q=ElapsedMilliseconds()-joinstart
 
splitstart.q=ElapsedMilliseconds()
*s1.StringBuilder = StringBuilder_Split(s$,"|")
splitend.q=ElapsedMilliseconds()-splitstart
 
EnableDebugger
 
Debug "Join: Len(s$)= "+Str(Len(s$))+" and took "+Str(joinend)+" ms"
Debug "Split: Elements(s$)= "+Str(*s1\count)+" and took "+Str(splitend)+" ms"
 
StringBuilder_Free(*s)
StringBuilder_Free(*s1)
 
s$ = "Probably the best sparkling wine in the world"
*s.StringBuilder = StringBuilder_Split(s$," ")
StringBuilder_Replace(*s,3,"malt")
StringBuilder_Remove(*s,4)
StringBuilder_Insert(*s,4,"vinegar")
Debug StringBuilder_Join(*s," ")


_________________
read-only ¯\_(ツ)_/¯


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

Зарегистрирован: Вт апр 14, 2009 7:22 pm
Сообщений: 362
Благодарил (а): 1 раз.
Поблагодарили: 13 раз.
Пункты репутации: 0
Но содержимое гаджетов, это же "копеешные" размеры, что тут ускорять?
Я думал что то в потоке и большие объёмы.
Т.е. можно представить приблизительно порядок размеров результата и количество фрагментов для сборки?
Самое узкое место в данном случае это не экономить память не наращивать буфер по каждому чиху а найти компромиссный размер для первоначального захвата и последующих.
И писать соответственно с вычислением и запоминанием следующего свободного байта и если зачем то нужна будет обратная процедура, то хранить таблицу указателей и длинны фрагментов, при нынешних размерах памяти это даже не копейки а доли копеек, как мне кажется.

А так то можно ещё конкретней задачу?

p.s. Сишная(онаже пуриковская) строка как область памяти заканчивающаяся нулём как признаком конца, проста в реализации и вполне устраивает мир когда иногда чуть чуть нужно их по бросать туда сюда, но если упёрлись в скорость, то вперёд и с песней все вспоминают функции работы с памятью и изобретают велосипед под свою дорогу со своими ямами и бордюрами.


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

Зарегистрирован: Вс июл 05, 2009 5:55 pm
Сообщений: 313
Благодарил (а): 1 раз.
Поблагодарили: 10 раз.
Пункты репутации: 0
Сергейчик писал(а):
можно ли как то по другому выделять буфер для строки кроме stroka=LSet(stroka,rashetindexa,"")
ого :shock: сколько живу такого изврата еще нивидел.
можно так A$="и тут держать клавишу столько сколько нужно символов, или из файлика скопировать .... .... .... потом в конце незабыть кавычки" :lol: так пойдет? Не? ну ладно есть более гуманный способ и по проше a$=Space(10000) на 10 килобукв.
Либо как у Петра *Buffer = AllocateMemory(1000), но работать тоже как у Петра(справке).
Да мс, с асемблером можно было бы и побыстрее чем за полторы секунды.


У пурика есть тормоз при соединении множества строк.
В конце результаты теста, савсем невдохновляет
вот для 20 000 строк жду пока в кучу слепит
34843 почти 35 сек, это же издевательство и это памяти занимает всегото 348908 байтиков,
помниш какие скоростя Сергейчик показывал в своих прогах 100 млрд циклов за 3.4 сек
что это 100 000 000 000 сотню Гиг, пурик что там как в картишки тасует эти строки или чё?

Самое печальное, что выключеный дебугер неускоряет ничуть, даже на 10 % нехочет :(
Код:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
a$="A123456789"
q=1000 ; столько строк будем клеить , во втором цикле в 10 раз больше.
 
b$=""
t= ElapsedMilliseconds()
For i=0 To q
    b$=b$+Chr(10)+Str(i)+"  "+a$
Next
t1=ElapsedMilliseconds()-t
Debug t1
 
b$=""
t= ElapsedMilliseconds()
For i=0 To q*10
    b$=b$+Chr(10)+Str(i)+"  "+a$
Next
t2=ElapsedMilliseconds()-t
 
Debug t2
Debug t2/t1
Debug MemoryStringLength(@b$  )
 
MessageRequester("",Str(t2 ) )
 


результаты теста, невпечатляют
; знаеш почему тупой виндофский нотепад тупо висит и даже проц негрузит
; когда большой файлик открывает, а вот почему
; q=500
; 31
; 2031 прикинь какихто 5000 строчек по десятку символов в кучу ждать 2 секунды
; 65 разница в скорости по количеству строк в 65 раз

; 16
; 2047
; 127

; 16
; 2109
; 131

; q=1000
; 63
; 8422 тута 8 сек, это гдето розтыкать нужно всего навсего файлик на 300-500 кило,
; а что делать будем когда файлик за метров 10 завалит полчаса ждать
; 133

; 78
; 8640
; 110


;вот и спешит нам на помощь умный код

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


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

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

a1=AllocateMemory выделяет размер памяти и дает тебе адрес(физической ОЗУ) первого байта(часто используется в Peek и других) его именуют указателем на память.

a2=ReAllocateMemory(a1, 1000) изменяет размер выделеной памяти ОЗУ, иногда перемещая в другие адреса, адрес(указатель) также меняется иногда остается тотже, но именно a2 нужно использавать иначе будет конфуз с вылетом проги.
Предыдущий указатель a1 больше несуществует, они нехранятся, некопятся и места незанимают.
После ReAllocateMemory память освобождается(но нестирается) и переназначается новый участок памяти ОЗУ.

Если память ненужна то освобождаем FreeMemory(a2), если прога завершается то можно неосвобождать, пурик сделает это сам.

Указатели на память пурик хранит у себя и размеры тоже можно узнать размер MemorySize(a2)

мож убедиться, что прога некопит память, она экономит ее как и винда, нужно открыть процес експлоер или чегото за прогу которая показывает все проги запущены и их размеры памяти.
Сама прога может занимать 18 метров в ОЗУ или другое число зависит от версии пурика.
сначала 100 метровпотом 200(ты неувидиш общего 300) и потом мизер но у меня не меньше 18 метров
Код:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
a=AllocateMemory(100000000)
PokeB(a,12)
Debug a
Debug PeekB(a)
 
Delay(5000)
a=ReAllocateMemory(a, 200000000)
Debug a
Debug PeekB(a)
Delay(5000)
 
a=ReAllocateMemory(a, 10000)
Debug a
Debug PeekB(a)
Delay(5000)




В справке неписано, но если сделать релок то каюк твоим даным, ты конечно мож попытаться их прочитать по старым адесам(если прога невыдетет, когда выходит за пределы дозволеного пространства например так Debug PeekB(0) выдает ошибку, думаю на асемблере и даст считать но записать в таблицу прерываний наврядли даст), но смотря куда релок переместит указатель, если увеличить размер памяти то память стирается. Проще заранее позаботится о размере и перемещении даных.

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


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

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

Код:
1
2
3
4
5
6
7
a$=Space(100)
a$="1345555"
Debug a$
a$=Space(10000)
Debug a$
 
 



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

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

Ты прикалываешся или как(я не про буржуйский форум), такой кусок кода в 150 строчек, может чегото по проще.
На старых версиях пурика неработает, но скорость впечатляет.
Join: Len(s$)= 523892 and took 34 ms
Split: Elements(s$)= 5000 and took 29 ms

Цитата:
Нужна динамическая строка

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

Ну суть приблизительно такая, думаю ты сможеш понять и написть подходящий код и выложить.
нужно учитывать три кодировки анси, УТФ8, уникод, помоему возвращает MemoryStringLength только без параметров нужно тогда все даные будут в том виде в котором компилирована прога.
Имея предыдущий размер строки в памяти и адрес можно вычислить неперевалили ли мы за пределы выделеной памяти.
тут бредо-теория, советую лучше пропустить, результать готовый внизу, тесты на скорость ВПЕЧАТЛЯЮТ второй код: 2 272 726 строк за (сек):0.64
Для строковых операций несколько метров обычно достаточно, ну наверно не в этом случае.

имеем строку String1
выделяем память м1=AllocateMemory под строку размером вычисленой этим MemoryStringLength(String1).
запихиваем туда по адресу м1 нашу строку String обычно это PokeS(м1, String1)

потом в цикле кажется.
имеем строку String2.
выделяем новый кусок памяти м2=AllocateMemory под строку размером вычисленой этим MemoryStringLength(String2), но размер должен быть больше потому что нам нужно запхать туда даные из первой строки поэтому :
м2=AllocateMemory(MemoryStringLength(String1)+MemoryStringLength(String2)).
короче думать уже устал, скажу проще там розберемся по ходу.

выделяеш память суеш туда строку.
в цикле розтягиваеш память :lol: , самому смешно стало, делаеш релокейтMemory(что негодится).

Все Заново.
Выделяеш память под первую строку и вторую тоже сумарно размер вычисляем этим - MemoryStringLength.
Сунеш последовательно туда эти строки этим PokeS.

Потом в цикле опять выделяеш память размером что уже занял и плюс для новой строки, копируеш с предыдущей памяти текст этим CopyMemory или MoveMemory.
добавляеш после этой строки новую строку этим PokeS, получается три строки.
удаляеш предыдущую память этим FreeMemory, а возможно ReAllocateMemory.
и так по циклу пока строчки все незапишеш.
на выходе чегото должно получится.
Если нужно в гаджет пихнуть то надо перевести в переменную этим PeekS(), после чего освободить память этим FreeMemory.

В общем нужно два блока ОЗУ, в одном хранятся уже соединенные строки, а во второй который длиннее с учетом добавляемой строки создаем, копируем в нее и добавляем новую строку и так по кругу копируя добавляя строку и удаляя предыдущий указатель...


Но может невозиться, обычно можно заранее выделить большой кусок памяти в 10 метров.
и только используя PokeS и зная адрес(адрес указателя и длинну строки предыдущей) где надо вставлять следущуюю строку, главное контролировать на преполнение буфера иначе кудате на пуриковские даные наедем, получим по носу и прога слитит, даных жалко :cry:

короче гдето так дополнил пример Петра
Код:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
*Buffer = AllocateMemory(1000)
*Pointer = *Buffer
CopyMemoryString("Hello", @*Pointer)
CopyMemoryString(" World")  ; This one will be put just after "Hello"
*Pointer-4                  ; Come back from 2 characters (on the 'l' of 'World')
CopyMemoryString("LD")      ; Finally the last letter will be uppercase
s$=PeekS(*Buffer)
Debug s$
Debug MemoryStringLength(@s$,#PB_Unicode)
ln=StringByteLength(s$,#PB_Unicode)
Debug ln
;ShowMemoryViewer(@s$, 500):CallDebugger
 
*Buff=*Buffer+ln;22
 
ln=PokeS(*Buff,"123")
Debug ln
Debug PeekS(*Buffer)
*Buff=*Buff+ln
 
ln=PokeS(*Buff,"5678")
Debug ln
Debug PeekS(*Buffer)



(ЭТОТ КОД НЕКОРЕКТЕН ПОСЛЕ ТЕСТОВ ТУТ ln=PokeS(*Buff,"5678") ВЫЛЕТАЕТ ПРОГА, ЕСЛИ ВКИНУТЬ МНОГО ТЕКСТА НАПРИМЕР ln=PokeS(*Buff,Space(100000)+"5678" ) ), ПОДХОДЯЩИЙ ПРИМЕР ДАЛЬШЕ ПРИВОДИТСЯ

у меня компилятор настроен на юникод поэтому смещение по 2 байта на символ.
Результат Hello WorLD имеет 11 символов но в юни получаем 22, поэтому *Buff=*Buffer+22.
А дальше все повторяется.

тут нашел еще какойто изврат почти в самом низу viewtopic.php?f=1&t=1910&p=31115&hilit=MemoryStringLength#p31115 правда тоже впечатляет скорость "на итерации в 200000 получается 203188мс против 297 мс - 683 раз" правда в конце форума говорит что работает неверно, знач правильно определил изврат.

диржи кайфуй, размер текста 1 метр, 22 738 коротких строчек влезло.
Код:
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
bb=1000500
 
*Buffer = AllocateMemory(bb+600); берем буфер с запасом
 
s$=PeekS(*Buffer)
Debug s$
 
Debug Len(s$)
Debug MemoryStringLength(@s$,#PB_Unicode)
ln=StringByteLength(s$,#PB_Unicode)
Debug ln
 
ss$="123456789"
 
*Buff=*Buffer+ln
 
ln=PokeS(*Buff,"123")
Debug ln
Debug PeekS(*Buffer)
*Buff=*Buff+ln
 
ln=PokeS(*Buff,"5678")
Debug ln
Debug PeekS(*Buffer)
*Buff=*Buff+ln
; а теперь в цикле и по времени
t= ElapsedMilliseconds()
For i=0 To 40000
ln=PokeS(*Buff,"WW э, ростут травы 678")
; Debug ln
; Debug PeekS(*Buffer)
*Buff=*Buff+ln
If *Buff-*Buffer>bb:Break:EndIf; тут смотрим на перепеолнение буфера, немножко доделаеш
Next
Debug PeekS(*Buffer) ;выводим строчку
Debug ""
Debug "количество байт "+Str(*Buff-*Buffer)
Debug "количество строчек "+Str(i)
Debug "потраченое время(сек):"+StrF((ElapsedMilliseconds()-t)/1000)
;ShowMemoryViewer(@s$, 500):CallDebugger
 


результат теста
количество байт 1 000 530
количество строчек 22 738
потраченое время(сек):0.0160000008
ляпота :D :) :o :shock: 8) :lol: :P :roll: :idea: :mrgreen:
вот еще результат, вот уже и заметил как глазом моргнуло :lol: , пурик лучший
количество байт 100 000 002
количество строчек 2 272 726
потраченое время(сек):0.6710000038

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


Последний раз редактировалось balex1978 Чт окт 04, 2018 9:43 pm, всего редактировалось 1 раз.

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

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

Ты неверь всему что говорят, всегда проверяй.
Со старым работать нельзя, только с новым, поэтому перед релокейтом сохраняй даные в новую облать памяти, а старую удаляй.
Думаю что релокейт нужен когда ты используеш как временное хранилище для обработки даных, а потом их кудато розтыкиваеш. После увеличиваеш размер ОЗУ и продолжаеш сней работать.(это дописал после того как уже одправил сообщение)

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

Просто если нужно релочить в большую сторону то сохраняй эти даные в временную выделеную
ОЗУ командой AllocateMemory() и релочь потом копируй назад и освобождай временную память.
И получиш... :?: штаны медленно превращаются... превращаются... , ага зачем козе баян.

Еще раз но по проще, заказываеш кусок ОЗУ -AllocateMemory() побольше и туда копируеш,
старый указатель(а соответственно и память ОЗУ) освобождаем, (ну конечно если у тебя там
метр с копейками мож оставить на розплод :) , погоды в твоем ПК он несделает, но если 100
метров то заметно сожрёт оперативки,) а указатель используеш новый в который скопировал.

вот код как понять как работает и как тебе приблизительно реализовать то что хочется
Код:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
M = AllocateMemory(10)
Debug MemorySize(M); размер
 
ln=PokeS(M,"123")
Debug ln
Debug PeekS(M)
 
M2 = AllocateMemory(20)
;CopyMemoryString("Hello", @*Pointer)
 
MoveMemory(M, M2, 10); или ln , тут копируем.
 
FreeMemory(M); освобождаем старуу память и указатель тоже, дважды неосвобождается и больше нерабочий
 
;FreeMemory(M);розкоментируй чтоб убедится, что больше выделеного куска ОЗУ тебе непринадлежит и может пуриком использоваться на свое усмотрение
;Debug MemorySize(M); можно розкоментировать чтоб убедиться что больше память незанята для тебя, выдаст ошибку
 
Debug PeekS(M); читаем с старой, если нестерто пуриком то увидим свой текст иначе бред, так непрограммируют, это я для примера.
 
Debug PeekS(M2); читаем с копии
 
ln=PokeS(M2+ln," Hello друзъя");тут чегото я недопонял, ну да ладно, работает, но только может в уникоеде
Debug PeekS(M2); читаем с копии что дописали в конец
 


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


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

Зарегистрирован: Пн июл 22, 2013 11:00 pm
Сообщений: 655
Благодарил (а): 2 раз.
Поблагодарили: 34 раз.
Пункты репутации: 9
Я так понял что нужно либо оставить работу с строкой и динамически увеличивать её размер(первый пример в топике)
Или через память используя как то функции API http://www.frolov-lib.ru/books/bsp/v13/ch2_3.htm


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

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

я какбы невникал глубоко, да и нужно тестить эти функции.
Но с прервой страници понял что тоже самое делает и встроеные пуриковские.
К примеру(я непроверял)
hmemGlobal = GlobalAlloc(GHND, 200000l);
это помоему аналог M2 = AllocateMemory(200000l), где M2 и hmemGlobal указатель на блок памяти или другими словами адрес начала того участка озу который ты запросил, похоже в обоих случаях динамически можно изменить.
где: GHND="Логический адрес перемещаемого блока памяти может изменяться."+очистак памяти

понимаеш если ты делаеш лрелок озу то за ним идет другие блоки которые пренадлежат комуто, и если ты хоч увеличить(релокмем.) то если за первым блоком есть свободное пространство, то используется оно, а если нет то чегото кудато нужно перенести, и это явно не списки переменных, ведь ты уже мож использовать их адреса, а тут босле релока(увеличения) все адреса переместились. Вот и может быть выделен кусок памяти в другом месте и те даные которые у тебя в этой части ОЗУ непереносятся. Ты их просто сам кудато переносиш например в во временную память потом обратно копируем, разве это проблема?
может нехоч сам переносить пускай оно само, но ведь на АСМе тебе этим приходится постоянно пользоваться. Или как ты думаеш организовано добавление строки на СИ или других языках и почему такие тормоза с этим? Ну если уж совсем лень то попробуй масив бинарный который тоже можно релочить и в него пхать текст и вычитывать как прямо так и через покеС и пеекС().
И он неочищается.

Там коду всего 10 строчек, несчитая разделителей(пустых строк) и просмотрщика памяти.
Код:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Dim a.b(20)
 
M = @a.b(0);AllocateMemory(10)
ln=PokeS(M,"Sos")
Debug PeekS(M)
 
ReDim a.b(10):     M = @a.b(0);ВАЖНО: ПОСЛЕ РЕСАЙЗА, АДРЕСА ИЗМЕНЯЮТСЯ ИНОГДА ПОЭТОМУ ПЕРЕЗАПИСЫВАЕМ
; выделяем 1 метр
ReDim a.b(1000000):M = @a.b(0); перезаписываем указатель, или везеде адрес берем не с переменной M, а так @a.b(0)
 
ln=StringByteLength(PeekS(M)); получаю длинну слова сос в уникоде чтобы после него добавить другую строку
M2= @a.b(ln) ;6 ;AllocateMemory(20)
ln=PokeS(M2,"- Hello друзъя"); тут добавляем вторую строку в указаное место с учетом длинны предыдущей строки; ln=PokeS(M2+ln," Hello друзъя");тут чегото я недопонял, ну да ладно, работает, но только может в уникоеде
Debug PeekS(M); тут смотрим как легли в память наши строки ; Debug PeekS(M2); читаем с копии что дописали в конец
 
ShowMemoryViewer(@a.b(0),200)



более детально с паралельным аналогом масива и AllocateMemory() тута
Код:
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
; я недумаю что так важно при работе с текстом беспокоится по каждом мегабайте 
;лишнего выделеного пространства у тебя же не калькулятор а солидный ПК.
 
Dim a.b(20)
 
M = @a.b(0);AllocateMemory(10)
 
Debug ArraySize(a.b());MemorySize(M); размер
 
ln=PokeS(M,"Sos")
Debug ln
Debug PeekS(M); читаем текст, ниже изврат прямо читаем с масива(я иногда иапользую память так иногда проще смотреть и преобразовывать блоки памяти в отличии от просмотрщика пуриковского)
Debug Chr(a.b(0)); тут в уникоде поэтому читаю через байт и только английский,
Debug Chr(a.b(2)); если нужно полноценно то следует два читать
Debug Chr(a.b(4)); если масив небинарный а ворд то нет проблем(просто тут пример бинарного чтоб небыло садо мазо)
 
;нужно увеличить или обрезать масив(наш выдленый кусак памяти, который содержит строку или какая разница чего еще)
ReDim a.b(10)
M = @a.b(0);ВАЖНО: ПОСЛЕ РЕСАЙЗА АДРЕСА ИЗМЕНЯЮТСЯ ИНОГДА ПОЭТОМУ ПЕРЕЗАПИСЫВАЕМ
Debug ArraySize(a.b());MemorySize(M); размер
Debug PeekS(M); читаем текст
 
Debug "две строки ниже это адреса старого и нового адресов выделеного нам пространства или ОЗУ или указатель на память"
Debug "если разные то масив кудаето переехал, но нас это небеспокоит"
Debug M; давай посмотрим дареса наших указателе на память, у меня всегда разные
ReDim a.b(1000000); выделяем 1 метр
M = @a.b(0); перезаписываем указатель, или везеде адрес берем не с переменной M, а так @a.b(0)
Debug M
 
 
Debug ArraySize(a.b());MemorySize(M); размер
Debug PeekS(M); читаем текст
; и тут тебя неинтересует чего пурик будет делать с этим блоком памяти,
; ОН ПРОСТО ОБЪЯЗАН СОХРАНИТЬ ЕГО ЦЕЛОСТНОСТЬ,
;вопрос в скорости таких ReDim, непроверял, но тебе зачем диначмически так часто менять размер
;для твоей задачи-содединить строки в кучу да побыстрей и побольше - я привел полностю быстрый и рабочий пример
 
ln=StringByteLength(PeekS(M),#PB_Unicode); получаю длинну слова сос в уникоде чтобы после него добавить другую строку
Debug ln
 
Debug PeekS(M)
 
M2= @a.b(ln) ;6 ;AllocateMemory(20)
 
 ; MoveMemory(M, M2, 10); или ln , тут копируем.
; FreeMemory(M); освобождаем старуу память и указатель тоже, дважды неосвобождается и больше нерабочий
; ;FreeMemory(M);розкоментируй чтоб убедится, что больше выделеного куска ОЗУ тебе непринадлежит и может пуриком использоваться на свое усмотрение
; ;Debug MemorySize(M); можно розкоментировать чтоб убедиться что больше память незанята для тебя, выдаст ошибку
; Debug PeekS(M); читаем с старой, если нестерто пуриком то увидим свой текст иначе бред, так непрограммируют, это я для примера.
; Debug PeekS(M2); читаем с копии
 
ln=PokeS(M2,"- Hello друзъя"); тут добавляем вторую строку в указаное место с учетом длинны предыдущей строки; ln=PokeS(M2+ln," Hello друзъя");тут чегото я недопонял, ну да ладно, работает, но только может в уникоеде
Debug PeekS(M); тут смотрим как легли в память наши строки ; Debug PeekS(M2); читаем с копии что дописали в конец
ShowMemoryViewer(@a.b(0),200); тут смотрим как в памяти- масиве наше слово лежит
; для справки слева внизу можно выбирать в каком виде отображать, выбери HEX или уникод.
 



Я вроде старался детально описать или я непонял чего тебе нужно. :?:

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


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

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

К слову, я так и непонял как это оно выделяет память под строку.
У пурика это кажется кратно 16 байтам включая ноль в конце и если длинна превышается то наверное все перетасовуется в памяти чтоб освободить для нужного размера.
Но тут строка дает ноль и где ты с ней работаеш, откуда знаеш что выделена, мож не выделена.
Код:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
stroka$="5"
rashetindexa=10
stroka$=LSet(stroka$,rashetindexa,""); просто пустые кавычки это ноль байт
Debug Len (stroka$)
; так например выделяется
 
stroka$="5"
rashetindexa=10
stroka$=LSet(stroka$,rashetindexa," ")
Debug Len (stroka$)
;но это равносильно этому: правда я увеличил с 10 до 200
stroka$=Space(200)
Debug Len (stroka$)
;а дальше это просто изврат какойто который неимеет смысла
; и уже исходя из надобности в эту строку соваеш свою или склеиваеш две
;в результате получается длинна(и буфера тож) которая заканчивается нулем.
 
;буфер размером в stroka$=Space(200) будет существовать пока ты в него невпишеш
; таким пособом stroka$="123" после этого он обрежется до 6 байт в уникоде +1 для ноля с ограничением кратности до 16 байт
; я незнаю как раобтает при этом pokeS() сокращает ли буфер или нет
; но проще для этого использовать алокейтмемори()



К слову так работает медленно всегда: c$=a$+b$

Поэтому я давал код с самоперемещаемым(масив через реДим) и "неперемещаемым" в кавычках буфером аллокатеМемори().

пример строкового буфера под АПИ функцию
Код:
1
2
Path.s=Space(501)
  GetWindowsDirectory_(@Path,500)


после заполнения мне неизвестно буфер остается в 501 или меньше.

адрес строки может менятся, причем пурик сам понимает чего вы хотите сделать и заранее выделяет побольше буфер, жесть.
Код:
1
2
3
4
5
6
a$="1234567890123456789"
Debug @a$
For i=0 To 10
a$=a$+"1234567890123456789"
Debug @a$
Next

Вот результат
3940008
3956504
...
3956504
вот на тыщу строк
3940008
3956504 0-ноль это номер строки в цикле
...
3956504 542 вот бац сменил его адрес
32932000 543
...
32932000 855 вот опять
3940064 856
...
3940064 1000
так что и в пурике без перемещений даже одной переменной необходится.

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


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

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


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

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


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

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