Страница: 1 | 2 | 3 |
Вопрос: Небольшой тест скорости PB7 vs VB6
Добавлено: 29.03.05 19:07
Автор вопроса: Macronix | Web-сайт:
В данном примере VB работает быстрее почти в два раза.
Тестировал на трех машинах. Почему так получилось? Может я чего не заметил. Выложите, плиз, свои результаты.
Код для VB
Option Explicit
Const THREAD_BASE_PRIORITY_IDLE = -15
Const THREAD_BASE_PRIORITY_LOWRT = 15
Const THREAD_BASE_PRIORITY_MIN = -2
Const THREAD_BASE_PRIORITY_MAX = 2
Const THREAD_PRIORITY_LOWEST = THREAD_BASE_PRIORITY_MIN
Const THREAD_PRIORITY_HIGHEST = THREAD_BASE_PRIORITY_MAX
Const THREAD_PRIORITY_BELOW_NORMAL = (THREAD_PRIORITY_LOWEST + 1)
Const THREAD_PRIORITY_ABOVE_NORMAL = (THREAD_PRIORITY_HIGHEST - 1)
Const THREAD_PRIORITY_IDLE = THREAD_BASE_PRIORITY_IDLE
Const THREAD_PRIORITY_NORMAL = 0
Const THREAD_PRIORITY_TIME_CRITICAL = THREAD_BASE_PRIORITY_LOWRT
Const HIGH_PRIORITY_CLASS = &H80
Const IDLE_PRIORITY_CLASS = &H40
Const NORMAL_PRIORITY_CLASS = &H20
Const REALTIME_PRIORITY_CLASS = &H100
Private Declare Function GetTickCount Lib "kernel32" () As Long
Private Declare Function SetThreadPriority Lib "kernel32" (ByVal hThread As Long, ByVal nPriority As Long) As Long
Private Declare Function SetPriorityClass Lib "kernel32" (ByVal hProcess As Long, ByVal dwPriorityClass As Long) As Long
Private Declare Function GetThreadPriority Lib "kernel32" (ByVal hThread As Long) As Long
Private Declare Function GetPriorityClass Lib "kernel32" (ByVal hProcess As Long) As Long
Private Declare Function GetCurrentThread Lib "kernel32" () As Long
Private Declare Function GetCurrentProcess Lib "kernel32" () As Long
Private Sub Form_Load()
Dim lTickCount As Long
Dim hThread As Long
Dim hProcess As Long
Dim lTest As Long
'Set High Priority
hThread = GetCurrentThread: hProcess = GetCurrentProcess
SetThreadPriority hThread, THREAD_PRIORITY_TIME_CRITICAL
SetPriorityClass hProcess, REALTIME_PRIORITY_CLASS
'Test
lTickCount = GetTickCount + 5000
While GetTickCount < lTickCount
lTest = lTest + 1: Wend
MsgBox Str$(lTest) & "+"
End Sub
Код для PB
#COMPILE EXE
#REGISTER NONE
#DIM ALL
#INCLUDE "Win32Api.Inc"
FUNCTION WINMAIN (BYVAL hInstance AS DWORD, _
BYVAL hPrevInstance AS DWORD, _
BYVAL lpCmdLine AS ASCIIZ PTR, _
BYVAL iCmdShow AS LONG) AS LONG
REGISTER lTest AS LONG
REGISTER lTickCount AS LONG
LOCAL hThread AS LONG
LOCAL hProcess AS LONG
'Set High Priority
hThread = GetCurrentThread : hProcess = GetCurrentProcess
CALL SetThreadPriority (hThread, %THREAD_BASE_PRIORITY_LOWRT)
CALL SetPriorityClass (hProcess, %REALTIME_PRIORITY_CLASS)
'Test
lTickCount = GetTickCount + 5000
WHILE GetTickCount < lTickCount
INCR lTest: WEND
MSGBOX STR$(lTest) & "+"
END FUNCTION
Ответы
Всего ответов: 44
Номер ответа: 1
Автор ответа:
cresta
Вопросов: 117
Ответов: 1538
Профиль | | #1
Добавлено: 29.03.05 20:47
В этом примере тестируется не скорость выполнения цикла, а время, необходимое ф-ции GetTickCount чтобы получить количество тиков. А GetTickCount ни к VB, ни к PB отношения не имеет.
Номер ответа: 2
Автор ответа:
Macronix
ICQ: 170650558
Вопросов: 12
Ответов: 46
Web-сайт:
Профиль | | #2
Добавлено: 29.03.05 20:57
Получается, в VB вызов функции GetTickCount проходит быстрее, чем в PB (у меня на PIII 1GHz получалось VB:134896602+, PB:75328922, то-есть, почти в два раза)
Номер ответа: 3
Автор ответа:
sne
Разработчик Offline Client
ICQ: 233286456
Вопросов: 34
Ответов: 5445
Web-сайт:
Профиль | | #3
Добавлено: 29.03.05 22:27
Незнаю как в PB но в VB вызов API происходит из рук вон медленно
Номер ответа: 4
Автор ответа:
cresta
Вопросов: 117
Ответов: 1538
Профиль | | #4
Добавлено: 29.03.05 22:49
А ты уверен, что VB-виртуальная машина в точности повторила твой код? Я не уверен. Зачастую бывает, что она переиначивает то, что ты написал, видя, что цикл пустой (бесполезный), т.к. результат вычисления нигде не используется.
Кроме того в PB коде столько хлама, что тормоза ещё те
Вот во что превратился твой цикл (РВ):
0040188A |. DB45 A8 |FILD DWORD PTR SS:[EBP-58]
0040188D |. BB 01000000 |MOV EBX,1
00401892 |. E8 790B0000 |CALL Test.00402410
00401897 |. FF15 E8414000 |CALL DWORD PTR DS:[<&KERNEL32.GetTickCo>; [GetTickCount
0040189D |. BB 01000000 |MOV EBX,1
004018A2 |. E8 4E0B0000 |CALL Test.004023F5
004018A7 |. E8 7D070000 |CALL Test.00402029
004018AC |. DED9 |FCOMPP
004018AE |. DFE0 |FSTSW AX
004018B0 |. 9E |SAHF
004018B1 |. 0F83 05000000 |JNB Test.004018BC
004018B7 |. FF45 80 |INC DWORD PTR SS:[EBP-80]
004018BA |.^EB CB \JMP SHORT Test.00401887
Кроме GetTickCount ещё вызывается три каких-то левых ф-ции CALL Test.00402029, CALL Test.004023F5, CALL Test.00402410. И ещё какого-то хрена операции с плавающей запятой... На хрена всё это тут? Для занятия места и пожирания времени, не иначе
Потому и проигрывает.
Даже сделал цикл ассемблерной вставкой - и то попытался запихать свои левые ф-ции. Вставил таки Хорошо хоть не в тело цикла.
00401801 |. 50 PUSH EAX
00401802 |. 8BDC MOV EBX,ESP
00401804 |. 8B43 04 MOV EAX,DWORD PTR DS:[EBX+4]
00401807 |. E8 41090000 CALL Test.0040214D
0040180C |. 58 POP EAX
0040180D |. 83C4 04 ADD ESP,4
00401810 |. E8 070C0000 CALL Test.0040241C
00401815 |. 8985 74FFFFFF MOV DWORD PTR SS:[EBP-8C],EAX
0040181B |. C745 80 000000>MOV DWORD PTR SS:[EBP-80],0
00401822 |. 56 PUSH ESI
00401823 |. 8BB5 74FFFFFF MOV ESI,DWORD PTR SS:[EBP-8C]
00401829 |. 57 PUSH EDI
0040182A |. FFD6 CALL ESI
0040182C |. 05 88130000 ADD EAX,1388
00401831 |. 8BD8 MOV EBX,EAX
00401833 |> 47 /INC EDI
00401834 |. FFD6 |CALL ESI
00401836 |. 3BC3 |CMP EAX,EBX
00401838 |.^0F8E F5FFFFFF \JLE Test.00401833
Сам цикл - последние 4 строки. ))
А результаты если интересно, такие:
VB-цикл: 245 556 998
asm-цикл: 701 543 869
Вот тебе и PB
Номер ответа: 5
Автор ответа:
alex
Вопросов: 84
Ответов: 453
Профиль | | #5
Добавлено: 29.03.05 22:58
Согласен с cresta, никакого отношения к скорости работы эти исходники не имеют.
x-bond странно, но в VB исходнике GetTickCount
описана у тебя как:
Private Declare Function GetTickCount Lib "kernel32" () As Long
А в "Win32Api.Inc" GetTickCount описан как:
Declare Function GetTickCount Lib "KERNEL32.DLL" Alias "GetTickCount" () As Dword
Видишь, типы то разные возвращаются! Поэтому и кажется, что VB быстрее работает. Перепиши в PB декаларацию как:
Private Declare Function GetTickCount Lib "kernel32" () As Long
И увидишь, что время работы примеров почти одиноково.
На моем P2-400:
VB пример: 52855533+
PB пример: 55965070+
PowerBASIC работает немного быстрее.
Номер ответа: 6
Автор ответа:
alex
Вопросов: 84
Ответов: 453
Профиль | | #6
Добавлено: 29.03.05 23:11
И вообще, на powerbasic.com тема скорости работы “VB app vs PB app” поднималась неоднократно, и в основном из-за ошибок перевода Long а Dword, очередной юзер заявлял что VB быстрее PB. Когда начинали проверять дотошнее, выяснялось, что VB в среднем работает от 100% до 300% медленнее, чем PB.
Номер ответа: 7
Автор ответа:
cresta
Вопросов: 117
Ответов: 1538
Профиль | | #7
Добавлено: 29.03.05 23:56
Действительно, с Long PB немножко обогнал VB, и до кучи ещё два примера:
306 131 481 - PB
247 752 992 - VB
717 515 664 - vc++
720 704 084 - asm
На Atlon XP 2200.
Номер ответа: 8
Автор ответа:
alex
Вопросов: 84
Ответов: 453
Профиль | | #8
Добавлено: 30.03.05 00:44
И вообще, писать на PB в стиле Visual Basic это неправильно. PowerBASIC позволяет грамотно оптимизировать работу программы, если использовать его "родные" конструкции. А бездумное копирование кода из VB, сводит эту оптимизацию к нулю.
Например, если взять типичную конструкцию SELECT CASE. Можно написать ее как в стиле VB:
Или в стиле PB:
Рвзницу в призводительности посмотрите на этом исходнике для PowerBASIC Console Compiler:
#Register All
Declare Function GetTickCount Lib "KERNEL32.DLL" Alias "GetTickCount" () As Long
Macro maxtest = 3000000
Function PBMain
Local t As Long
Local i As Long
Local x As Long
Local u As Long
Local TestString As String
t = gettickcount - t
u = gettickcount
Cursor Off
Print "--------------------------------"
Print "Start Select Case speed"
Print "--------------------------------"
Print "Please wait... "
Print " "
Print "Visual Basic style, speed: ";
For i = 1 To maxtest
TestString="Test Speed"
Select Case TestString
Case "String1"
x=1
Case "String2"
x=2
Case "String3"
x=3
Case "String4"
x=4
Case "String5"
x=5
Case "String6"
x=6
Case "Test Speed"
x=7
End Select
Next i
u = gettickcount - u
Print Format$(u)
'------------------------------------------
Print " "
Print "Power Basic style, speed: ";
t = gettickcount - t
u = gettickcount
For i = 1 To maxtest
TestString="Test Speed"
Select Case As Const$ TestString
Case "String1"
x=1
Case "String2"
x=2
Case "String3"
x=3
Case "String4"
x=4
Case "String5"
x=5
Case "String6"
x=6
Case "Test Speed"
x=7
End Select
Next i
u = gettickcount - u
Print Format$(u)
Print "--------------------------------"
WaitKey$
End Function
На моем P2-400 разница просто чудовищная:
--------------------------------
Start Select Case speed
--------------------------------
Please wait...
Visual Basic style, speed: 21050
Power Basic style, speed: 3104
--------------------------------
Кострукция Select Case As Const$ работает на 678%
быстрее, чем обычный Select Case...
Есть над чем подумать
Номер ответа: 9
Автор ответа:
CyRax
Разработчик Offline Client
ICQ: 204447456
Вопросов: 180
Ответов: 4229
Web-сайт:
Профиль | | #9
Добавлено: 30.03.05 11:04
Select Case As Const$
А у меня все Case без Const$. Если я переделаю проблем не будет?
Номер ответа: 10
Автор ответа:
Macronix
ICQ: 170650558
Вопросов: 12
Ответов: 46
Web-сайт:
Профиль | | #10
Добавлено: 30.03.05 13:13
Знал же, что LONG быстрее чем DWORD, а проверить декларацию в Win32Api.Inc не соизволил.
Вот мои результаты с LONG: (округленные до милионов)
PIII 1Ghz
VB - 136
PB - 124
PIV 1.8Ghz
VB - 126
PB - 153
Athlon 2000+
VB - 224
PB - 345
Интересно, Атлон явно лидирует, а 3 пенек все еще отстает. и еще VB на 4 пеньке показал худший результат, чем на P1GHz, странно...
Номер ответа: 11
Автор ответа:
CyRax
Разработчик Offline Client
ICQ: 204447456
Вопросов: 180
Ответов: 4229
Web-сайт:
Профиль | | #11
Добавлено: 30.03.05 13:22
x-bond,
цикл While...Wend лучше не использовать если тебе нужна скорость. Для этого есть цикл For...Next.
Номер ответа: 12
Автор ответа:
CyRax
Разработчик Offline Client
ICQ: 204447456
Вопросов: 180
Ответов: 4229
Web-сайт:
Профиль | | #12
Добавлено: 30.03.05 13:31
И вообще, подготовительная оптимизация в любом языке никогда не мешает. Чем меньше неизвестных в цикле, тем лучше.
И неизвестные - это необязательно числа. Например UCase$ или LCase$ лучше вынести за цикл.
Собственно для этого и нужен ассемблер (а не как пиасал Морфеус - для написания скриптов ), чтобы понимать суть происходящего.
PowerBasic позволяет производить оптимизацию вплоть до инструкций процессора. Уровень VB - самый низкий, расчитанный для новичков.
Полнота использования этого инструмена (PB) зависит только от твоих знаний.
К примеру какие ты строки используешь в критических участках? Нужно ASCIIZ - они намного быстрее. И т.д. Вобщем хочешь писать на уровне VB - получишь и скорость уровня VB. Чудес не бывает.
Номер ответа: 13
Автор ответа:
Macronix
ICQ: 170650558
Вопросов: 12
Ответов: 46
Web-сайт:
Профиль | | #13
Добавлено: 30.03.05 14:15
CyRax, вот ты говоришь об оптимизации, а на твоем сайте в примерах сравнения VB vs PB в коде VB даже не объявленны переменные, и работают как Variant, естественно Васик будет сильно тормозить.
Советую обновить тесты.
Номер ответа: 14
Автор ответа:
CyRax
Разработчик Offline Client
ICQ: 204447456
Вопросов: 180
Ответов: 4229
Web-сайт:
Профиль | | #14
Добавлено: 30.03.05 15:15
VB vs PB в коде VB даже не объявленны переменные, и работают как Variant
А в PB-шный ты заглядывал? Там тоже самый медленный целочисленный тип используется - Dword.
Всё бралось по минимуму. Хочешь - сделай по максимуму и отошли мне. Я проверю правильность алгоритмов и выложу на сайте.
Номер ответа: 15
Автор ответа:
CyRax
Разработчик Offline Client
ICQ: 204447456
Вопросов: 180
Ответов: 4229
Web-сайт:
Профиль | | #15
Добавлено: 30.03.05 15:18
Да, только не забудь ассемблерный тест вставить. Надеюсь ассемблер знаешь?