Какой код в играх "съедает" основное время процессора? Рендер? Нет, рендерит видеокарта. Это физика либо логика ИИ. При этом большей частью производятся простые действия (сложение, умножение, деление, сравнение) над игровыми данными. А сами данные - это, как правило Single и Long, в "чистом" виде, в виде структур и массивов. При большом количестве игровых объектов, с ними работают через Quad или OcTree, это позволяет быстро отсеивать те объекты, которые обрабатывать не нужно (например, они находятся заведомо далеко). Обход Quad и Oc деревьев осуществляют, как правило, с помощью рекурсии. Исходя из этого для измерения производительности для игр хорошо подходит тест - рисование простого фрактала, это те же самые действия, тоже рекурсия, такие же данные. Вот проект на Visual Basic 6: FrVB6 Его можно перевести полностью, а можно только это:
Code
Private Sub DrawFractal(vPos As Vector, vDir As Vector) Dim vP As Vector, vD As Vector
If vDir.x * vDir.x + vDir.y * vDir.y < 0.017 Then Exit Sub vP.x = vPos.x + vDir.x vP.y = vPos.y + vDir.y DrawLine vPos, vP
Private Sub DrawLine(vP1 As Vector, vP2 As Vector) Dim x As Single, y As Single, k As Single, dx As Single, dy As Single
dx = vP2.x - vP1.x dy = vP2.y - vP1.y If Abs(dx) < Abs(dy) Then k = dx / dy If vP2.y > vP1.y Then y = vP1.y x = vP1.x While y < vP2.y Map(x, y) = &H50BB50 x = x + k y = y + 1 Wend Else y = vP2.y x = vP1.x While y < vP1.y Map(x, y) = &H40FF30 x = x + k y = y + 1 Wend End If Else k = dy / dx If vP2.x > vP1.x Then x = vP1.x y = vP1.y While x < vP2.x Map(x, y) = &HA0AF20 y = y + k x = x + 1 Wend Else x = vP2.x y = vP1.y While x < vP1.x Map(x, y) = &H609F30 y = y + k x = x + 1 Wend End If End If End Sub
определяем (если нет) структуру:
Code
Private Type Vector x As Single y As Single End Type
Создаём массив и два вектора:
Code
Dim Map(1023, 767) As Long Dim vP As Vector, vD As Vector
Единственно изменил расположение процедур и сделал глобальным массив MAP
Вот с пуром пришлось каждую строчку колбасить . В общем:
PureBasic и FreeBasic одинаковы: 46-47
VisualBasic 6.0: 532-548
Моя машина: пень DUAL CORE E5200 2500
Все три компилятора проверял функцией GetTickCount
Код FB (компиль 0.22):
Code
#Include "windows.bi" Private Type Vector x As Single y As Single End Type Dim Shared Map(1023, 767) As Long Dim vP As Vector, vD As Vector Private Sub DrawLine(vP1 As Vector, vP2 As Vector) Dim x As Single, y As Single, k As Single, dx As Single, dy As Single dx = vP2.x - vP1.x dy = vP2.y - vP1.y If Abs(dx) < Abs(dy) Then k = dx / dy If vP2.y > vP1.y Then y = vP1.y x = vP1.x While y < vP2.y Map(x, y) = &H50BB50 x = x + k y = y + 1 Wend Else y = vP2.y x = vP1.x While y < vP1.y Map(x, y) = &H40FF30 x = x + k y = y + 1 Wend End If Else k = dy / dx If vP2.x > vP1.x Then x = vP1.x y = vP1.y While x < vP2.x Map(x, y) = &HA0AF20 y = y + k x = x + 1 Wend Else x = vP2.x y = vP1.y While x < vP1.x Map(x, y) = &H609F30 y = y + k x = x + 1 Wend End If End If End Sub
Sub DrawFractal(vPos As Vector, vDir As Vector) Dim vP As Vector, vD As Vector If vDir.x * vDir.x + vDir.y * vDir.y < 0.017 Then Exit Sub vP.x = vPos.x + vDir.x vP.y = vPos.y + vDir.y DrawLine vPos, vP
Structure Vector x.f y.f EndStructure Global Dim Map_.l(1023, 767) vP.Vector vD.Vector Procedure DrawLine(*vP1.Vector,*vP2.Vector) x.l y.l k.f dx.f dy.f
dx = *vP2\x - *vP1\x dy = *vP2\y - *vP1\y If Abs(dx) < Abs(dy) k = dx / dy If *vP2\y > *vP1\y y = *vP1\y x = *vP1\x While y < *vP2\y Map_(x, y) = $50BB50 x = x + k y = y + 1 Wend Else y = *vP2\y x = *vP1\x While y < *vP1\y Map_(x, y) = $40FF30 x = x + k y = y + 1 Wend EndIf Else k = dy / dx If *vP2\x > *vP1\x x = *vP1\x y = *vP1\y While x < *vP2\x Map_(x, y) = $A0AF20 y = y + k x = x + 1 Wend Else x = *vP2\x y = *vP1\y While x < *vP1\x Map_(x, y) = $609F30 y = y + k x = x + 1 Wend EndIf EndIf EndProcedure
Ты в VB6 из среды запускал? Запускай EXE, желательно мой (или сам включи все оптимизации). И от PB и FB хотелось бы EXE-шники, потестить на разных компах. И GetTickCount очень неточен, чем не устроил QPC? Ну и синтаксис у PB , впервые вижу. Я так понял "\", этот аналог сишного "->"? Но почему тогда
Code
vP\x = *vPos\x + *vDir\x
а не
Code
*vP\x = *vPos\x + *vDir\x
?
Сообщение отредактировал -Mikle- - Пятница, 13 Апреля 2012, 09:13
Да, но сейчас после твоего поста запустил твой EXE, результаты:
у VB6 ~0.5122 у FB ~ 0.047 у PB не проверял, но думаю что будет 0.047
Вот код с QPC
Code
#Include "windows.bi" Private Type Vector x As Single y As Single End Type Dim Shared Map(1023, 767) As Long
Dim Shared QSpeed As Double Private Function QTime() As Double Dim QD As LARGE_INTEGER, t As Double
QueryPerformanceCounter @QD If QD.LowPart < 0 Then t = QD.LowPart + 4294967296 Else t = QD.LowPart If QD.HighPart < 0 Then t = t + (QD.HighPart + 4294967296) * 4294967296 Else t = t + QD.HighPart * 4294967296 QTime = t * QSpeed End Function
Private Sub QTimeInit() Dim QD As LARGE_INTEGER
QueryPerformanceFrequency @QD If QD.LowPart < 0 Then QSpeed = QD.LowPart + 4294967296 Else QSpeed = QD.LowPart If QD.HighPart < 0 Then QSpeed = QSpeed + (QD.HighPart + 4294967296) * 4294967296 Else QSpeed = QSpeed + QD.HighPart * 4294967296 QSpeed = 1 / QSpeed End Sub
Dim vP As Vector, vD As Vector Private Sub DrawLine(vP1 As Vector, vP2 As Vector) Dim x As Single, y As Single, k As Single, dx As Single, dy As Single dx = vP2.x - vP1.x dy = vP2.y - vP1.y If Abs(dx) < Abs(dy) Then k = dx / dy If vP2.y > vP1.y Then y = vP1.y x = vP1.x While y < vP2.y Map(x, y) = &H50BB50 x = x + k y = y + 1 Wend Else y = vP2.y x = vP1.x While y < vP1.y Map(x, y) = &H40FF30 x = x + k y = y + 1 Wend End If Else k = dy / dx If vP2.x > vP1.x Then x = vP1.x y = vP1.y While x < vP2.x Map(x, y) = &HA0AF20 y = y + k x = x + 1 Wend Else x = vP2.x y = vP1.y While x < vP1.x Map(x, y) = &H609F30 y = y + k x = x + 1 Wend End If End If End Sub
Sub DrawFractal(vPos As Vector, vDir As Vector) Dim vP As Vector, vD As Vector If vDir.x * vDir.x + vDir.y * vDir.y < 0.017 Then Exit Sub vP.x = vPos.x + vDir.x vP.y = vPos.y + vDir.y DrawLine vPos, vP
Почему тогда твои результаты на VB6 в 10 раз хуже моих? На PB и FB примерно совпадают.
Наверное потому что:
PB (обертка FASM) FB (обертка GNU ASM)
Кто же с ассемблером меряется в скорости Хотя я в этом деле не спец. Может кто другой скажет почему так. А вообще возми скачай среду FbEdit уже настроенную вместе с компилем и проверь для FB можно ОТСЮДА (21.8 мб)
Да, я ставлю такие же оптимизации. Проверил на Athlon64 3800+, VB6 довольно сильно вырвался вперёд: vb6 - 0.0505 pb -0.0594 На интеле примерно такие результаты, как у тебя. Табличку сделаю, только мне нужен EXE с QPC на PB.
Сообщение отредактировал -Mikle- - Пятница, 13 Апреля 2012, 12:02
Да, я ставлю такие же оптимизации. Проверил на Athlon64 3800+, VB6 довольно сильно вырвался вперёд: vb6 - 0.0505 pb -0.0594 На интеле примерно такие результаты, как у тебя.
Ну вот , а то часто видел реплики в сети, что VB6 тормоз. Вот прямое доказательство обратного!
Quote
Табличку сделаю, только мне нужен EXE с QPC на PB.
Подождем PBPROG может он че еще подправит в коде, я уж давно по нормальному на PB не кодил, может что и не так сделал. Ну а если не захочет, тогда допишу сам.
PBPROG, похоже, что в PB массивах поменяны местами строки и столбцы, задай так:
Code
Map.l(767, 1023)
И во всех обращениях к массиву поменяй местами x и y. trew, хорошо бы тоже сделать визуализацию, чтобы убедиться, что код правильно работает.
Quote
Ну вот , а то часто видел реплики в сети, что VB6 тормоз. Вот прямое доказательство обратного!
Факт. Сколько видел таких тестов, доказывающих тормознутость VB6, везде либо полная безсмыслица, либо навязывание чуждого для VB6 стиля программирования.
Сообщение отредактировал -Mikle- - Пятница, 13 Апреля 2012, 13:38
PBPROG, похоже, что в PB массивах поменяны местами строки и столбцы, задай так:
В FB кстати тоже
Вот код:
Code
#Include "windows.bi"
Private Type Vector x As Single y As Single End Type
Dim Shared bi32BitInfo As BITMAPINFO Dim Shared Map(767, 1023) As Long Declare Sub DrawFractal(vPos As Vector, vDir As Vector) Declare Sub DrawLine(vP1 As Vector, vP2 As Vector) Declare Sub Main() Dim Shared QSpeed As Double
Main '<- вход
Private Function QTime() As Double Dim QD As LARGE_INTEGER, t As Double QueryPerformanceCounter @QD If QD.LowPart < 0 Then t = QD.LowPart + 4294967296 Else t = QD.LowPart If QD.HighPart < 0 Then t = t + (QD.HighPart + 4294967296) * 4294967296 Else t = t + QD.HighPart * 4294967296 QTime = t * QSpeed End Function
Private Sub QTimeInit() Dim QD As LARGE_INTEGER QueryPerformanceFrequency @QD If QD.LowPart < 0 Then QSpeed = QD.LowPart + 4294967296 Else QSpeed = QD.LowPart If QD.HighPart < 0 Then QSpeed = QSpeed + (QD.HighPart + 4294967296) * 4294967296 Else QSpeed = QSpeed + QD.HighPart * 4294967296 QSpeed = 1 / QSpeed End Sub
Private Sub Main() Dim vP As Vector, vD As Vector Dim t1 As Single, t2 As Single Dim msg As MSG
Private Sub DrawLine(vP1 As Vector, vP2 As Vector) Dim x As Single, y As Single, k As Single, dx As Single, dy As Single
dx = vP2.x - vP1.x dy = vP2.y - vP1.y If Abs(dx) < Abs(dy) Then k = dx / dy If vP2.y > vP1.y Then y = vP1.y x = vP1.x While y < vP2.y Map(y, x) = &H50BB50 x = x + k y = y + 1 Wend Else y = vP2.y x = vP1.x While y < vP1.y Map(y, x) = &H40FF30 x = x + k y = y + 1 Wend End If Else k = dy / dx If vP2.x > vP1.x Then x = vP1.x y = vP1.y While x < vP2.x Map(y, x) = &HA0AF20 y = y + k x = x + 1 Wend Else x = vP2.x y = vP1.y While x < vP1.x Map(y, x) = &H609F30 y = y + k x = x + 1 Wend End If End If End Sub
Факт. Сколько видел таких тестов, доказывающих тормознутость VB6, везде либо полная безсмыслица, либо навязывание чуждого для VB6 стиля программирования.
Здесь-то было все по честному. Чистая математика и рекурсия.
Похоже что с файлообменника уже удалили файлы, перезалью. http://depositfiles.com/files/vipw13pu3 Код немного оптимизировал чтобы добиться большего быстродействия.
If Abs(dx) < Abs(dy) k = dx / dy If *vP2\y > *vP1\y y = *vP1\y x = *vP1\x While y < *vP2\y xx=x : yy=y Map(yy, xx) = $50BB50 x + k y + 1 Wend Else y = *vP2\y x = *vP1\x While y < *vP1\y xx=x : yy=y Map(yy, xx) = $40FF30 x + k y + 1 Wend EndIf Else k = dy / dx If *vP2\x > *vP1\x x = *vP1\x y = *vP1\y While x < *vP2\x xx=x : yy=y Map(yy, xx) = $A0AF20 y + k x + 1 Wend Else x = *vP2\x y = *vP1\y While x < *vP1\x xx=x : yy=y Map(yy, xx) = $609F30 y + k x + 1 Wend EndIf EndIf
Select Msg Case #WM_CHAR DestroyWindow_(hWnd) PostQuitMessage_(0) : Result = 0 Case #WM_CLOSE DestroyWindow_(hWnd) Case #WM_DESTROY PostQuitMessage_(0) : Result = 0 Default Result = DefWindowProc_(hWnd, Msg, wParam, lParam) EndSelect
PBPROG, выложи на нормальный файлообменник. MTS вообще пишет, что хост блокирован по решению суда, ну, это обходится, попал на депозит, подождал минуту, ввёл капчу... ещё одна капча, и так шесть раз, надоело, закрыл. Капчи хорошо читаемы, я не мог ошибаться. Есть Narod.ru, 188.ru.
Quote (PBPROG)
Код немного оптимизировал чтобы добиться большего быстродействия.
Вот это зря, мы же сравниваем на алгоритмы, а компиляторы, теперь придётся для остальных языков переписывать.
Сообщение отредактировал -Mikle- - Четверг, 27 Сентября 2012, 13:31
Разница в том, что теперь процедура ничего не возвращает (т. е. работает как процедура, а не как функция) и не тратится время на копирование в регистры, возвращаемых данных. Хоть это требует не очень много времени, но учитывая что процедура DrawFractal() вызывается 1653637 раз (если отладчик не врет), это позволило сэкономить немного времени.
Добавлено (27.09.2012, 19:28) --------------------------------------------- Я немного проанализировал код и по моему он не оптимален с точки зрения тестирования. В процедуру по ссылке передаются параметры, но не возвращаются. Это дало возможность схитрить, например, использовав const в параметрах процедур кода на дельфи. Кстати, если убрать const, то дельфи оказывается в хвосте по скорости выполнения кода. А ведь часто некоторые данные нужно возвращать через аргументы процедур/функций. Поэтому предлагаю доработать тест, добавив в структуру Vector поле Color в котором будет хранится цвет точки, выводимой на экран. Заодно и массив точек передавать по ссылке процедурам.
If Abs(dx) < Abs(dy) k = dx / dy If *vP2\y > *vP1\y y = *vP1\y x = *vP1\x While y < *vP2\y xx=x : yy=y Map(yy, xx) = *vP1\Color x + k y + 1 Wend *vP2\Color - x Else y = *vP2\y x = *vP1\x While y < *vP1\y xx=x : yy=y Map(yy, xx) = *vP2\Color x + k y + 1 Wend *vP1\Color + x EndIf Else k = dy / dx If *vP2\x > *vP1\x x = *vP1\x y = *vP1\y While x < *vP2\x xx=x : yy=y Map(yy, xx) = *vP2\Color y + k x + 1 Wend *vP1\Color + y Else x = *vP2\x y = *vP1\y While x < *vP1\x xx=x : yy=y Map(yy, xx) = *vP1\Color y + k x + 1 Wend *vP2\Color - y EndIf EndIf
Select Msg Case #WM_CHAR DestroyWindow_(hWnd) PostQuitMessage_(0) : Result = 0 Case #WM_CLOSE DestroyWindow_(hWnd) Case #WM_DESTROY PostQuitMessage_(0) : Result = 0 Default Result = DefWindowProc_(hWnd, Msg, wParam, lParam) EndSelect