alibek писал(а):Нужно модифицировать скрипт таким образом, чтобы он суммировал счетчики на нескольких (например двух) интерфейсах.
И тут возникают сложности с тем, как определять и обрабатывать переполнения.
Proxy писал(а):Ну а если просто сложить, а затем уже работать как с одним? Ну если допустим счётчика 2, то по любому снижению значения суммы можно судить о переполнении одного или сразу двух счётчиков. Но глупо как-то, некорректно будет себя вести, если один счётчик обнулится, а второй в это время сильно возрастёт (более, чем на предыдущее значение сбросившегося счётчика).
Хакер писал(а):Допустим, счётчик был бы не 32-, а 8-битным. Пусть предпоследнее измерение дало 250, а текущее 5. Если отнять от пятерчки число 250, то результат будет 11.
Proxy писал(а):Ну так вроде и загвоздка вся в том, что предыдущее значение счётчика узнать — большая проблема.
Хакер писал(а):Proxy писал(а):Ну так вроде и загвоздка вся в том, что предыдущее значение счётчика узнать — большая проблема.
Если бы это было большой проблемой, это было бы столь же актуально и для случая с одним счётчиком: вычислить dC/dt было бы невозможно.
Хакер писал(а):Если так, так для нескольких счётчиков скрипт должен отдавать несколько значений, программа должна вычислять дельту отдельно для каждого из счётчиков, а потом суммировать дельты.
alibek писал(а):Так не получится, программа не умеет суммировать дельты.
alibek писал(а):Поэтому нужно либо исключить переполнение (взяв заведомо большую разрядность)
alibek писал(а):Но в любом случае нужно определять факт того, что на каком-то из счетчиков произошло переполнение (и делать это без доступа к предыдущим значениям).
Хакер писал(а):Она чужая и с закрытым исходным кодом?
alibek писал(а):Поэтому правильнее, чтобы cgi-скрипт сам получал значения со всех интерфейсов, суммировал их и отдавал сумму в одном поле.
Хакер писал(а):вычисляет dC/dt для каждого счётчика по отдельности
alibek писал(а):Знать о предыдущих состояниях он не может.
Было: Прибавилось: Стало:
C1A C1D C1B
C2A C2D C2B
C3A C3D C3B
... ... ...
CnA CnD CnB
----------------------------
Сумма: Total_A Total_D Total_B
Арифметика с переполнениями (computer-like):
Было: Прибавилось: Стало:
255 000 255
255 001 000
255 002 001
255 003 002
010 004 014
----------------------------
Сумма: 006 010 016
Арифметика без переполнений (human-like):
Было: Прибавилось: Стало:
255 000 255
255 001 256
255 002 257
255 003 258
010 004 014
----------------------------
Сумма: 1030 010 1040
Хакер писал(а):Почему он не может сохранять где-то предыдущие значения и время предыдущего измерения?
alibek писал(а):т.е. нужно сохранять несколько сотен промежуточных значений.
Хакер писал(а):Зачем? Не нужно сохранять значения каждого счётчика. Нужно сохранять сумму с учётом переполнений.
Хакер писал(а):Пусть Cacti не вычисляет дельту. Разве принципиально, чтобы её вычисляла именно она?
alibek писал(а):Сумм тоже много (пара сотен).
Хакер писал(а):Я всё-таки не могу понять саму суть проблемы.
alibek писал(а):Суть проблемы была в том, что нужно было эмулировать переполнение для суммы значений.
alibek писал(а):Если его эмулировать, то проблемы больше нет.
Хакер писал(а):Речь идёт о специфике скриптового языка, в котором переполнение не происходит само собой естественным образом?
Хакер писал(а):То есть вот этот пост решил проблему?
alibek писал(а):А каков естественный образ?
old_time = GetTickCount(); // За 1 секунду до переполнения, вернёт 4294966296
... что-то делаем ...
new_time = GetTickCount(); // Через 2 секунду после переполнения, вернёт 2000
printf("%d\n", new_time - old_time); // Выведет 3000 без всяких контролей переполнения
alibek писал(а):Это скриптовый язык.
Который выдаст ошибку переполнения.
Поэтому нужно или использовать xor, или использовать модуль для многоразрядной математики (с последующим обрезанием значения).
Private Const BITMSK_NEGATIVE_BIT_DW As Long = &H80000000
Private Const BITMSK_NEGATIVE_BIT_W As Integer = &H8000
Private Const BITMSK_NEGATIVE_BIT_B As Byte = &H80
Private Const BITMSK_ALL_BITS_DW As Long = &HFFFFFFFF
Private Const BITMSk_ALL_BITS_W As Integer = &HFFFF
Private Const BITMSK_ALL_BITS_B As Byte = &HFF
...
...
...
Public Function EmAddUnsigned(ByVal ul1 As Long, ByVal ul2 As Long) As Long
If (BITMSK_NEGATIVE_BIT_DW And ul1) = _
(BITMSK_NEGATIVE_BIT_DW And ul2) Then
'
' Либо два неотрицательных числа, либо два отрицательных. Их
' сложение может дать переполнение, поэтому сделаем из них
' два разнознаковых числа (такие никогда не дадут переполнение):
' инвертируем одному из них MSB, складываем, а потом инвертируем
' MSB у результата. Биты инвертируются оператором Xor.
'
Const MSB As Long = BITMSK_NEGATIVE_BIT_DW ' Самый старший бит
EmAddUnsigned = ((ul1 Xor MSB) + ul2) Xor MSB
Else
'
' Знаки разные, и можно просто сложить числа: два числа, только
' одно из которых отрицательное, никогда не дадут переполнение
' в результате сложения или вычитания.
'
EmAddUnsigned = ul1 + ul2
End If
End Function
Public Function EmSubtractUnsigned(ByVal ul1 As Long, _
ByVal ul2 As Long) As Long
'
' Заранее предостерегаю от идеи сделать эту функцию как обёртку над
' EmAddUnsigned(ul1, -ul2). Выражение (-ul2) может дать overflow.
' Эта функция использует тот же принцип, что и EmAddUnsigned, но
' с обратной логикой выбора способа.
'
If (BITMSK_NEGATIVE_BIT_DW And ul1) = _
(BITMSK_NEGATIVE_BIT_DW And ul2) Then
EmSubtractUnsigned = ul1 - ul2
Else
Const MSB As Long = BITMSK_NEGATIVE_BIT_DW ' Самый старший бит
EmSubtractUnsigned = ((ul1 Xor MSB) - ul2) Xor MSB
End If
End Function
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 4