объединение строк - как улучшить производительность

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
marvan
Бывалый
Бывалый
 
Сообщения: 269
Зарегистрирован: 22.06.2004 (Вт) 13:26
Откуда: Москва

объединение строк - как улучшить производительность

Сообщение marvan » 06.09.2004 (Пн) 16:31

В программе тормоза. При объединении строк переменной длины. Где то встречал то ли модуль то ли класс для работы со строками, как с массивом. Да вот не найду теперь.:(
Private Sub Command1_Click()
    Dim s As String
    For i = 0 To 1000
    ' если поставить 10000
    ' время ожидания существенно увечивается
        s = s & GetStr
    Next
    MsgBox "OK"
End Sub

'это генератор строк произвольной длины
'добавлен для примера
Private Function GetStr() As String
    Dim n As Byte
    Dim MaxLen As Byte
    Dim mASCII As Byte
    Dim strTmp As String
    MaxLen = CByte(254 * Rnd)
    For n = 1 To MaxLen
        Do
            mASCII = CByte(122 * Rnd)
            If mASCII < 65 Then
                mASCII = mASCII + 50
            End If
            Select Case mASCII
                Case 65 To 90, 97 To 122
                     Exit Do
                Case Else
                     mASCII = 0
            End Select
        Loop
        strTmp = strTmp & Chr(mASCII)
    Next
    GetStr = strTmp
End Function

BP
Бывалый
Бывалый
 
Сообщения: 234
Зарегистрирован: 17.02.2004 (Вт) 5:34
Откуда: Украина

Сообщение BP » 06.09.2004 (Пн) 19:01

На VB врядли можно работать со строками как с массивом. На PB это можно сделать через указатели, а на VB разве что через API.

hCORe
VB - Экстремал
VB - Экстремал
Аватара пользователя
 
Сообщения: 2332
Зарегистрирован: 22.02.2003 (Сб) 15:21
Откуда: parent directory

Сообщение hCORe » 06.09.2004 (Пн) 19:22

Не вот это?
Вложения
cAppendString.zip
cAppendString
(1.01 Кб) Скачиваний: 219
Моду создают модоки, а распространяют модозвоны.

Andrey Fedorov
Член-корреспондент академии VBStreets
Член-корреспондент академии VBStreets
 
Сообщения: 3287
Зарегистрирован: 21.05.2004 (Пт) 9:28
Откуда: Москва

Сообщение Andrey Fedorov » 07.09.2004 (Вт) 7:31

На VB можно прекрасно работать со строками. Если только подумать как с ним сам VB работает (да и любой другой язык, кстати). Ну если не охота думать - сходите, к примеру, сюда:

http://vbaccelerator.com/home/VB/Code/Techniques/StringBuilder/article.asp

И возьмите готовый класс.
Фиг Вам! - Сказал Чебурашка, обгладывая Крокодила Гену...

Andrey Fedorov
Член-корреспондент академии VBStreets
Член-корреспондент академии VBStreets
 
Сообщения: 3287
Зарегистрирован: 21.05.2004 (Пт) 9:28
Откуда: Москва

Сообщение Andrey Fedorov » 07.09.2004 (Вт) 7:37

На VB врядли можно работать со строками как с массивом.


Неужто?

А попробуй так:

Dim m() as byte, s as string
s="Абракадабра"
m=s

И твоя строка уже в массиве.
Только учти что один символ занимает два байта (ибо уенкод).
Фиг Вам! - Сказал Чебурашка, обгладывая Крокодила Гену...

marvan
Бывалый
Бывалый
 
Сообщения: 269
Зарегистрирован: 22.06.2004 (Вт) 13:26
Откуда: Москва

Сообщение marvan » 07.09.2004 (Вт) 10:56

2 hCORe
Большое спасибо за пример.
Я тут не удержался, накопал в инете в след за ссылкой от Andrey Fedorov ещё четыре аналогичных класса.
Протестил с разным объёмом итераций - ваш cAppendString.cls - самый быстрый.
Только я не понял смысл комментариев:
Код: Выделить всё
      '***  вызов copymemory быстрее, чем это:
      Mid$(strTemp, 1&) = pstrBuffer

Так если copymemory быстрее - почему не используется?

Andrey Fedorov
Член-корреспондент академии VBStreets
Член-корреспондент академии VBStreets
 
Сообщения: 3287
Зарегистрирован: 21.05.2004 (Пт) 9:28
Откуда: Москва

Сообщение Andrey Fedorov » 07.09.2004 (Вт) 11:03

Так если copymemory быстрее - почему не используется?


Да я даже не смотрел тот пример... ;)
Просто глянул в описании что он использует правильную методику и дал на него ссылку. По мне и Mid$ вполне нормально работает.
Или ты за микросекунды борешься???
Фиг Вам! - Сказал Чебурашка, обгладывая Крокодила Гену...

marvan
Бывалый
Бывалый
 
Сообщения: 269
Зарегистрирован: 22.06.2004 (Вт) 13:26
Откуда: Москва

Сообщение marvan » 07.09.2004 (Вт) 13:45

проверил - замена
Mid$(strTemp, 1&) = pstrBuffer
на
RtlMoveMemory ByVal StrPtr(strTemp), ByVal StrPtr(pstrBuffer), LenB(pstrBuffer)
на производительности не сказывается
Спасибо всем отозвавшимся.

BP
Бывалый
Бывалый
 
Сообщения: 234
Зарегистрирован: 17.02.2004 (Вт) 5:34
Откуда: Украина

Сообщение BP » 07.09.2004 (Вт) 14:09

Это не работа со строками как с массивом.
Вот работа со строками как с массивом

PB:
Код: Выделить всё
Dim a As String, B As Byte Ptr
a="Hello World!"
b=StrPtr(a)
MsgBox @b[0] 'Покажет "H"
MsgBox @b[1] 'Покажет "e"


А то что ты показал - это просто копирование. В результате таких непрофессиональных действий размер занимаемой памяти удвоится. Поэтому и приходится прибегать к АПИ

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 07.09.2004 (Вт) 14:50

BP, а зачем же наезжать?
ИМХО, человек писал не о том, что работать со строкой, как с массивом, а о том, что строку можно преобразовать в массив. А s=vbNullString освободит память.
Lasciate ogni speranza, voi ch'entrate.

Andrey Fedorov
Член-корреспондент академии VBStreets
Член-корреспондент академии VBStreets
 
Сообщения: 3287
Зарегистрирован: 21.05.2004 (Пт) 9:28
Откуда: Москва

Сообщение Andrey Fedorov » 07.09.2004 (Вт) 14:54

А то что ты показал - это просто копирование.


Ну не хочешь так (строку, кстати, после присвоения массива можно очистить - к слову о двойном размере в памяти (строки у тебя видно дюже большие и в глобальных переменных :lol: )), то считай что функция Mid$(s, i, 1) дает тебе доступ к нужному элементу массива строки. После чего можешь работать со строкой "как с массивом".

А ведь по сути оно так и есть, согласись ;)
Фиг Вам! - Сказал Чебурашка, обгладывая Крокодила Гену...

Andrey Fedorov
Член-корреспондент академии VBStreets
Член-корреспондент академии VBStreets
 
Сообщения: 3287
Зарегистрирован: 21.05.2004 (Пт) 9:28
Откуда: Москва

Сообщение Andrey Fedorov » 07.09.2004 (Вт) 14:56

на производительности не сказывается


Да и не должна была вообще-то сказаться.
В VB довольно-таки неплохой компилятор...
Фиг Вам! - Сказал Чебурашка, обгладывая Крокодила Гену...

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 07.09.2004 (Вт) 15:01

Насчет Mid$() не соглашусь. Все-таки массив это одно, а Mid$(s,i,1) это функция, которая каждый раз вычисляется.
(ностальгируя) Вот в бейсике ZX Spectrum было классно, можно было запросто написать s(1 To 3) или s(2 To 2), очень изящно и красиво. А уж про Beta-Basic и Mega-Basic я вообще молчу.
Lasciate ogni speranza, voi ch'entrate.

Andrey Fedorov
Член-корреспондент академии VBStreets
Член-корреспондент академии VBStreets
 
Сообщения: 3287
Зарегистрирован: 21.05.2004 (Пт) 9:28
Откуда: Москва

Сообщение Andrey Fedorov » 07.09.2004 (Вт) 15:10

Насчет Mid$() не соглашусь. Все-таки массив это одно, а Mid$(s,i,1) это функция, которая каждый раз вычисляется.


Ну тут надо смотеть дизассемблированный код.
Но что-то мне кажется что Mid$ так и работает.
На ее входе строка, смещение и длина отрезка.
Так что и код должен получиться такой-же как при работе с массивом.
Но чтобы быть на 100% уверенным - смотреть надо...

(ностальгируя)

А в первом бэсике с которым я работал функция вывода форматировала строку почти как ptintf...
Фиг Вам! - Сказал Чебурашка, обгладывая Крокодила Гену...

marvan
Бывалый
Бывалый
 
Сообщения: 269
Зарегистрирован: 22.06.2004 (Вт) 13:26
Откуда: Москва

Сообщение marvan » 07.09.2004 (Вт) 15:49

Это не работа со строками как с массивом

нашёл я тот самый модуль, о поисках которого говорил в первом посте:
Add or Remove String Array items by manipulating memory на этой странице
к стати оказалось, что это совсем не то о чём я думал.
а вот то, что я искал (пришлось самому писать) -
Public Sub Add(ByRef nStr As String)
    Dim LenStr As Long 'размер строки
    LenStr = LenB(nStr)
    If LenStr > 0 Then
        Do While (LenStr + LenTxt) > LenBuf
        'увеличить размер буфера
            LenBuf = 1.5 * LenBuf
            ReDim Preserve ArrBuf(0 To LenBuf) As Byte
        Loop
        CopyMemory ArrBuf(LenTxt), ByVal StrPtr(nStr), LenStr
        LenTxt = LenStr + LenTxt
    End If
End Sub

это я и имел в виду, говоря о работе со строками, как с массивом

Andrey Fedorov
Член-корреспондент академии VBStreets
Член-корреспондент академии VBStreets
 
Сообщения: 3287
Зарегистрирован: 21.05.2004 (Пт) 9:28
Откуда: Москва

Сообщение Andrey Fedorov » 07.09.2004 (Вт) 16:00

нашёл я тот самый модуль


Ну по большому-то счету оно все одно и то-же

Под строку резервируется некоторое место, после его исчерпания создается новая строка большего размера. Но весь фокус в том что какие-либо CopyMemory тут даром не нужны! Все отлично проделывается средствами самого VB:

Надо зарезервировать (увеличить) место под строку - достаточно выполнить:

s=s & Space(8000)

и потом запольнять его с помощью Mid$, запоминая количество добавленных символов.

Весь смысл в том чтобы избавить VB от необходимости постоянно выделять память под строку, что происходит при выполнении операций типа

s = s & "Что-то"

А всяческие API-функции и массивы тут даром не нужны...
Фиг Вам! - Сказал Чебурашка, обгладывая Крокодила Гену...

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 07.09.2004 (Вт) 16:12

Andrey Fedorov, есть оператор Mid$() и функция Mid$(). Первый скорее всего так и работает, если ты говоришь, что разницы в производительности нет. А вот функция навряд-ли.
Lasciate ogni speranza, voi ch'entrate.

Andrey Fedorov
Член-корреспондент академии VBStreets
Член-корреспондент академии VBStreets
 
Сообщения: 3287
Зарегистрирован: 21.05.2004 (Пт) 9:28
Откуда: Москва

Сообщение Andrey Fedorov » 07.09.2004 (Вт) 16:29

alibek.

А вот функция навряд-ли


А какая им по большому счету разница???

Ну сам прикинь как бы ты по хорошему сделал реализацию Mid$, неважно оператора или функции (у которой на входе адрес строки, смещение и длина подстроки). Получится быстро и просто - MS так и сделали. Там трудно что-то накрутить... :lol:

Впрочем, мне достаточно того что работает быстро - на все случаи жизни хватало с огромадным запасом, посему потроха не столь интересуют...
Фиг Вам! - Сказал Чебурашка, обгладывая Крокодила Гену...

marvan
Бывалый
Бывалый
 
Сообщения: 269
Зарегистрирован: 22.06.2004 (Вт) 13:26
Откуда: Москва

Сообщение marvan » 07.09.2004 (Вт) 16:34

А всяческие API-функции и массивы тут даром не нужны

проверил - действительно разница в скорости отсутствует:
Public Sub Append(Text As String)
    Dim lngText As Long
    lngText = Len(Text)
    If lngText = 0 Then Exit Sub
    If (plngStringLen + lngText) > plngBufferLen Then
        plngBufferLen = (plngStringLen + lngText) * 2&
        pstrBuffer = pstrBuffer & Space(plngBufferLen)
    End If
    Mid$(pstrBuffer, plngStringLen + 1&) = Text
    plngStringLen = plngStringLen + lngText
End Sub

TEH3OP
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 143
Зарегистрирован: 12.12.2003 (Пт) 20:19
Откуда: Москва

к слову о работе со строкой, как с массивом

Сообщение TEH3OP » 08.09.2004 (Ср) 1:12

marvan писал(а):Где то встречал то ли модуль то ли класс для работы со строками, как с массивом. Да вот не найду теперь.:(

Если я чего не понял сорры...

Но (САБЖ) ваащета в VB мона сделать так:
Код: Выделить всё
Dim bstTest as String
Dim abytTest() as String

bstTest = "Мама мыла раму!"
abytTest = bstTest

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Re: к слову о работе со строкой, как с массивом

Сообщение tyomitch » 08.09.2004 (Ср) 11:49

TEH3OP писал(а):Но (САБЖ) ваащета в VB мона сделать так:
Код: Выделить всё
Dim bstTest as String
Dim abytTest() as String

bstTest = "Мама мыла раму!"
abytTest = bstTest


Нигде не опечатался? ;-)
Изображение


Вернуться в Visual Basic 1–6

Кто сейчас на конференции

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

    TopList  
cron