The GVar plugin is a wrapper around several hash tables as of the latest version. Hash tables have an amortized constant time complexity. I haven't done a detailed analysis on properties, so I can't say exactly what the complexity is for them, but their runtime does seem to increase almost linearly as more elements are added. Hash tables can also be described as having an O(1) complexity on average, which basically just means that the number of elements in a hash table has no bearing on its runtime under normal conditions. This is definitely not the case for properties. Below are some tests to prove it.
This code allocates 100,000 unique strings to be used as keys:
pawn Код:
new names[100000][16];
for (new i = 0; i < 100000; i++)
{
format(names[i], sizeof(names[]), "name_%d", i);
}
GetTickCount will be used to calculate the time that has elapsed. It should be noted that because this native does not provide access to a high resolution timer, the results listed here could possibly be off by several milliseconds. However, the data should at least be accurate enough make a few simple comparisons.
Tests for SetGVarInt and GetGVarInt:
pawn Код:
new time = GetTickCount();
for (new i = 0; i < 100000; i++)
{
SetGVarInt(names[i], i);
}
printf("Time #1: %d", GetTickCount() - time);
time = GetTickCount();
for (new i = 0; i < 100000; i++)
{
GetGVarInt(names[i]);
}
printf("Time #2: %d", GetTickCount() - time);
The results:
Код:
[19:07:15] Time #1: 166
[19:07:15] Time #2: 52
The script took 166 milliseconds to allocate 100,000 elements and only 52 milliseconds to retrieve them.
Tests for setproperty and getproperty:
pawn Код:
new time = GetTickCount();
for (new i = 0; i < 100000; i++)
{
setproperty(0, names[i], i);
}
printf("Time #1: %d", GetTickCount() - time);
time = GetTickCount();
for (new i = 0; i < 100000; i++)
{
getproperty(0, names[i]);
}
printf("Time #2: %d", GetTickCount() - time);
The results:
Код:
[19:29:28] Time #1: 200739
[19:32:43] Time #2: 195040
Allocation of 100,000 elements with properties, on the other hand, took
200,739 milliseconds, and retrieval took
195,040 milliseconds—both well over 3 minutes. That's several orders of magnitude slower than GVars!
PVars aren't quite as bad, but they are limited to 800 elements per player. In order to make a proper comparison, the loops must be much smaller.
Tests for SetGVarInt and GetGVarInt (800 elements):
pawn Код:
new time = GetTickCount();
for (new i = 0; i < 800; i++)
{
SetGVarInt(names[i], i);
}
printf("Time #1: %d", GetTickCount() - time);
time = GetTickCount();
for (new i = 0; i < 800; i++)
{
GetGVarInt(names[i]);
}
printf("Time #2: %d", GetTickCount() - time);
The results:
Код:
[19:14:15] Time #1: 1
[19:14:15] Time #2: 1
Tests for SetPVarInt and GetPVarInt (800 elements):
pawn Код:
new time = GetTickCount();
for (new i = 0; i < 800; i++)
{
SetPVarInt(playerid, names[i], i);
}
printf("Time #1: %d", GetTickCount() - time);
time = GetTickCount();
for (new i = 0; i < 800; i++)
{
GetPVarInt(playerid, names[i]);
}
printf("Time #2: %d", GetTickCount() - time);
The results:
Код:
[19:14:30] Time #1: 4
[19:14:30] Time #2: 3
GVars are still slightly faster, but not by much. Properties and PVars might appear to be faster in a few specific cases, but PVars are limited in size and properties quickly become unmanageable as they increase in size. GVars have no imposed limits on storage capacity, and they also have an amortized constant time complexity. There are a few things to consider, however:
- Long GVar names can increase runtime, so keep them short.
- GetGVarsUpperIndex and GetGVarNameAtIndex both actually have a linear time complexity due to their different methods of implementation, so use them sparingly.
Edit: I have modified this post for clarity.