Dim MyAbakus As New XAbakus
MyAbakus.Init "D:\Base\BASE.GDB", "admin", "q"
MyAbakus.itGetInternetTraffic "tex", "30.01.2002", "01.02.2003", 50
MyAbakus.itReady
Иногда (не всегда) при вызове метода Init происходит ошибка "не найен метод"
Если сделать так
Dim MyAbakus As New XAbakus
MyAbakus.itReady
MyAbakus.Init "D:\Base\BASE.GDB", "admin", "q"
MyAbakus.itGetInternetTraffic "tex", "30.01.2002", "01.02.2003", 50
CTPEKOA>Здравствуйте al, Вы писали:
al>>P.S. Использование оператора New в операторе Dim снижает призводительность программы
CTPEKOA>Это почему?
Общеизвестный факт. Бейсик в случае New в Dim работает примерно так:
Dim a as New MyClass
....
a.Caption="Test"
' реально бейсик интерпретирует это как If a Is Nothing Then Set a = New MyClass : a.Caption = "Test"
a.MyMethod
' и опять VB делает - If a Is Nothing Then Set a = New MyClass : a.MyMethod
Другими словами, использование New в операторе Dim не приводит к немедленному созданию объекта, а откладывает его
создание до первого к нему обращения. Т.к. понять, в каком месте это первое обращение призойдет VB не может, то он
генерирует код проверки перед каждым обращением к объекту. Это и является причиной замедления работы.
Убедиться в таком поведении VB поможет такой пример:
' в классе Class1
Option Explicit
Public Sub Test()
MsgBox "Test"
End Sub
Private Sub Class_Initialize()
MsgBox "Class_Initialize"
End Sub
' в форме
Option Explicit
Private Sub Form_Load()
Dim a As New Class1
MsgBox "Dim a As New Class1"
a.Test
End Sub
У меня (VB6,SP5) последовательность сообщений — "Dim a As New Class1" — "Class_Initialize" — "Test"
Если бы VB создавал обект в операторе Dim .. As New, то последовательность была-бы другой: "Class_Initialize" — "Dim a As New Class1" — "Test"
Здравствуйте al, Вы писали:
al>Здравствуйте CTPEKO3A, Вы писали:
CTPEKOA>>Здравствуйте al, Вы писали:
al>>>P.S. Использование оператора New в операторе Dim снижает призводительность программы
CTPEKOA>>Это почему?
al>Общеизвестный факт. Бейсик в случае New в Dim работает примерно так:
Хорошо, но как это влияет на производительность программы?
Какая мне разница, когда объект будет создан — тогда, когда я впервые обращусь к его методу или когда-то заранее? Ведь совершенно одинаковое время потребуется для создания объекта в любом случае.
И, с другой стороны, вы себе представляете в какой машинный код преобразуется проверка If a Is Nothing Then? Мне почему-то кажется что это что-то вполне атомарное, чем можно пренебречь. Вот если вы создаёте сотни объектов или что-то подобное, то да, тогда будет заметно. А если нет — то зачем?
It's nice to be important, but it's more important to be nice.
CTPEKOA>Здравствуйте al, Вы писали:
al>>Здравствуйте CTPEKO3A, Вы писали:
CTPEKOA>>>Здравствуйте al, Вы писали:
al>>>>P.S. Использование оператора New в операторе Dim снижает призводительность программы
CTPEKOA>>>Это почему?
al>>Общеизвестный факт. Бейсик в случае New в Dim работает примерно так:
CTPEKOA>Хорошо, но как это влияет на производительность программы?
Выполнение лишнего If занимает некторое время. В некоторых случаях это может быть критично.
Если есть возможность писать более быстрый код без особых извращений, то наверное это стоит делать всегда. Например, не так сложно писать:
Dim A As MyObject : Set A = New MyObject, вместо Dim A As New MyObject.
Танньше я иногда использовал Dim ... As New .. для создания временных обектов в коде. Но теперь мне больше нравиться использовать With New. Так, пример из корневого вопроса можно представить так:
with New XAbakus ' вместо Dim MyAbakus As New XAbakus
.Init "D:\Base\BASE.GDB", "admin", "q"
.itGetInternetTraffic "tex", "30.01.2002", "01.02.2003", 50
.itReady
end with
Кроме ускорения (в этом случае, конечно, принебрежимо малого) я избавляюсь от временной
переменной и необходимости писать Set ... = Nothing, когда эта переменная будет не нужна,
"стремление к совершенству" не посзволит мне больше занимать память ненужным объектом.
CTPEKOA>И, с другой стороны, вы себе представляете в какой машинный код преобразуется проверка If a Is Nothing Then? Мне почему-то кажется что это что-то вполне атомарное, чем можно пренебречь. Вот если вы создаёте сотни объектов или что-то подобное, то да, тогда будет заметно. А если нет — то зачем?
Как говориться, лишь бы поспорить. Я так поянл (из предыдущего вопроса), что вы не знали
об этом свойстве VB. Так какя у вас есть гарантия, что вы не будете создавать сотни объектов или что-то подобное при помощи Dim .. As New ..? Вот теперь наверное не будете.
Здравствуйте al и CTPEKO3A, Вы писали:
CTP>Хорошо, но как это влияет на производительность программы?
al>Выполнение лишнего If занимает некторое время. В некоторых случаях это может быть критично.
CTP>И, с другой стороны, вы себе представляете в какой машинный код преобразуется проверка If a Is Nothing Then? Мне почему-то кажется что это что-то вполне атомарное, чем можно пренебречь. Вот если вы создаёте сотни объектов или что-то подобное, то да, тогда будет заметно. А если нет — то зачем?
al>Так какя у вас есть гарантия, что вы не будете создавать сотни объектов или что-то подобное при помощи Dim .. As New ..? Вот теперь наверное не будете.
Да причем здесь "сотни объектов"? Достаточно значительной (много обращений за свойствами) работы с ОДНИМ объектом, как получится эффект, о котором говорил уважаемый al.
Главное, что эта дельта времени есть, а уж как она скажется (или нет) — зависит от программера.
Здравствуйте Vi2, Вы писали:
Vi2>Здравствуйте al и CTPEKO3A, Вы писали:
CTP>>Хорошо, но как это влияет на производительность программы?
al>>Выполнение лишнего If занимает некторое время. В некоторых случаях это может быть критично.
Vi2>Главное, что эта дельта времени есть, а уж как она скажется (или нет) — зависит от программера.
А как велика эта дельта времени и откуда она берется?
Перед вызовом любого указателя байсиком проверяется неравенство этого указателя нулю (или это делает инфроструктура COM?). В любом случае сравнение в исходном коде присутствует, но даже пренебригая числом выполнных операций сравнения, время вызова любого
метода класса больше времени затраченного на указанные сравнения.
пример кода:
Module1:
Public Declare Function GetTickCount Lib"kernel32" () As Long
Sub Main()
Dim t1 As Long, t2 As Long, t3 As Long
Dim I As Long
Dim c1 As Class1, c2 As New Class1
Set c1 = New Class1
Dim res As String
res = "Results: "
c1.I = 0
c2.I = 0
c1.D = 0
c2.D = 0
c1.S = "A"
c2.S = "A"
t1 = GetTickCount
For I = 0 To 100000000
c1.I = c1.I
Next
t2 = GetTickCount
For I = 0 To 100000000
c2.I = c2.I
Next
t3 = GetTickCount
res = res + vbCrLf + "declare 'As Class1', Integer=" + CStr(t2 - t1)
res = res + vbCrLf + "declare 'As New Class1', Integer=" + CStr(t3 - t2)
t1 = GetTickCount
For I = 0 To 100000000
c1.D = c1.D
Next
t2 = GetTickCount
For I = 0 To 100000000
c2.D = c2.D
Next
t3 = GetTickCount
res = res + vbCrLf + "declare 'As Class1', double =" + CStr(t2 - t1)
res = res + vbCrLf + "declare 'As New Class1', double =" + CStr(t3 - t2)
t1 = GetTickCount
For I = 0 To 100000000
c1.S = c1.S
Next
t2 = GetTickCount
For I = 0 To 100000000
c2.S = c2.S
Next
t3 = GetTickCount
res = res + vbCrLf + "declare 'As Class1', string =" + CStr(t2 - t1)
res = res + vbCrLf + "declare 'As New Class1', string =" + CStr(t3 - t2)
MsgBox res
Clipboard.SetText res
End Sub
Class1 :
Public I As Integer
Public D As Double
Public S As String
Итого раздница на более 8%, а для случая обычно сипользуемых свойств, не более 3%. Вы работаете на задачей где подобное время является критическим? тогда почему ВЫ пишете на VB?
Здравствуйте Chorkov, Вы писали:
C>получается 17% и 10%, что немного больше .
Не забудьте еще, что у объектов, созданных как As New, невозможно ловить события.
Здравствуйте retalik, Вы писали:
R>Не забудьте еще, что у объектов, созданных как As New, невозможно ловить события.
Поправка: почти невозможно (есть какой-то изврат с объектными ссылками)
Кроме того, в VB.NET есть динамическая привязка к событиям (AddHandler).
Здравствуйте Chorkov, Вы писали:
C>Здравствуйте Vi2, Вы писали:
Vi2>>Здравствуйте al и CTPEKO3A, Вы писали:
CTP>>>Хорошо, но как это влияет на производительность программы?
C>Перед вызовом любого указателя байсиком проверяется неравенство этого указателя нулю. (или это делает инфроструктура COM?). В любом случае сравнение в исходном коде присутствует,
Это не так. Во пример дезасемблированного кода, порожденного VB:
Видите, в случае As New — cmp dword ptr [f1],0 и т.д? Это и есть то самое сравнение, которое отсутствует в случае Set ... = New .... Кроме замедления это еще приводит к увеличению размера конечного файла. Проверка-же любого указателя на Nothing проиходит через систему обработки исключений Windows (SEH). Если опустить Set f2 = New Form1, то на операторе mov eax,dword ptr [eax] возникнет исключение "Access Violation" (c0000005). Которое обрабатывается VB Run-time.
Здравствуйте al, Вы писали:
al>Здравствуйте retalik, Вы писали:
R>>... у объектов, созданных как As New, невозможно ловить события.
al>Кроме того, в общем случае, непонятно, в какй момент будет вызван конструктор (Class_Initialize).
Видимо, имеет место непонимание, для чего нужна конструкция As New.
Я использую ее в следующих ситуациях:
1) Сокрытие инициализации переменных (вынесение инициализации за пределы Sub Main).
Например, когда проет разрабатывается большим числом программистов и только оди имеет в данные момент доступ к Main.
2) Создание обьектов "По свитку" (откладывание процедуры инициализации обьектов до момента их фактического использования).
Например в случае когда инициализация переменных требует затрат времени или дополнительного диалога с пользовательм, показ которого нежелателен, если в этих данных так и не возникнет необходимость.
Признаю, что в большенстве из перечисленных ситуаций допустимо использование классов с атрибутом GlobalMultiuse, однако использование New, мне кажется, более оправданным, поскольку позволяет является "более явным". Кроме того, "Глобализация" не позволяет своевременно закрывать обьекты. Например:
в классе:
public rSet as Recordset
private db as Database
Private Sub Class_Initialize()
set db=OpenDatabase(...)
...
End Sub
Private Sub Class_Terminate()
rSet.Close
db.Close
End Sub
На форме:
dim RecSource as New MyClass
База данных будет открываться/закрываться только один раз и только если в ней возникнит необходимость.
Здравствуйте al, Вы писали:
al>Здравствуйте Chorkov, Вы писали:
C>>Здравствуйте Vi2, Вы писали:
Vi2>>>Здравствуйте al и CTPEKO3A, Вы писали:
CTP>>>>Хорошо, но как это влияет на производительность программы?
C>>Перед вызовом любого указателя байсиком проверяется неравенство этого указателя нулю. (или это делает инфроструктура COM?). В любом случае сравнение в исходном коде присутствует,
al>Это не так. Во пример дезасемблированного кода, порожденного VB:
al>
al>Исходинк:
al>Option Explicit
al>Private Sub Form_Click()
al>
al> Dim f1 As New Form1
al> f1.Show
al>
al> Dim f2 As Form1
al> Set f2 = New Form1
al> f2.Show
al>
al>End Sub
al>
al>Видите, в случае As New — cmp dword ptr [f1],0 и т.д? Это и есть то самое сравнение, которое отсутствует в случае Set ... = New .... Кроме замедления это еще приводит к увеличению размера конечного файла. Проверка-же любого указателя на Nothing проиходит через систему обработки исключений Windows (SEH). Если опустить Set f2 = New Form1, то на операторе mov eax,dword ptr [eax] возникнет исключение "Access Violation" (c0000005). Которое обрабатывается VB Run-time.
al>Такие вот дела...
Код дейвствительно длиннее ... но на счет скорости вы не вполне правы.
Сравним исполняемую часть кода в случае создания нового обьекта:
С учетом времени затраченного внутри
al> 00401A1C call __vbaObjSet (0040115c)
исполняемая часть кода, в слкчае dim as New оказывается короче.
Устверждение об отсутствии предварительной проверки не неравенство нулю, также неверное. Просто вместо прямой проверки (jne) используется косвенная (через проверку доступности указанной памяти на чтение), что требует техже 4 байт интсрукций. Достоинство только в том, что отсутствие явного условного перехода позволяет процессору лучьше предсказывать переходы.
Обращаю, также внимание на то, что наличее обьекта в переменной f2 проверяется только после того как в стек будут загружены все неявные аргументы для вызова метода Show. Что привет к значительным потерям времени в случае использования конструкции:
dim F as form1
on error goto err_form1
F.Show
....
err_form1:
set F=new form1
resume
P.S.
В любом случае, раздница в обьеме и скорости кода пренебрежимо мала по сравнению с затратами на процедура Show.
Здравствуйте Chorkov, Вы писали:
C>Устверждение об отсутствии предварительной проверки не неравенство нулю, также неверное. Просто вместо прямой проверки (jne) используется косвенная (через проверку доступности указанной памяти на чтение), что требует техже 4 байт интсрукций.
Чего-то я этих 4-х байт как ни искал, так и не нашел. Эту проверку выполняет сам процессор совместно с ОС, и выполняется она в любом случае. Почитайте Рихтера.