Point analysis of MyicQ-1.0A1 server code (2) - Online personnel management and memory allocation
Solarsoft
Http://solarsoft.126.com
Online personnel management
In the UPD server, the management of online personnel is essential. In fact, this method can also be used in the game server. Let's take a look, how myicq is managed.
Myicq is a hash table to manage, the search efficiency of the hash table is very high, and it is currently the most efficient lookup method I have seen. Please see the implementation of myicq in my mych tablet:
#define hash_size (1 << 16)
#define hash_mask (hash_size - 1)
Struct hash {
Listhead ipport; // ip and port
Listhead uin; // Unique ID number
}
Static hash bucket [hash_size]; // Set "bucket"
INLINE INT Hashfn // Hash Function
{
UIN ^ = (uin >> 16);
UIN ^ = (uin >> 8);
Return (uin & hash_mask);
}
INLINE INT Hashfn (uint32 ip, uint16 port)
{
INT H = (IP ^ port);
H ^ = (H >> 16);
h ^ = (h >> 8);
Return (h & hash_mask);
}
And use class sessionhash to manage the definition:
Class sessionhash {
PUBLIC:
Static udpsession * get (uint32 uin);
Static udpsession * get (uint32 ip, uint16 port);
Static void Put (udpsession * p, uint32 ip, uint16 port);
Static void Put (udpsession * p, uint32 uin);
Static void Random (ICQoutPacket & Out, INT N);
}
UDPSession * sessionhash :: get (uint32 uin)
{
Listhead * POS;
Listhead * head = & bucket [hashfn]. Uin;
List_for_each (pos, head) {
UDPSession * p = list_entry (POS, UDPSESSION, UINITEM);
IF (p-> uin == uin)
Return P;
}
Return NULL;
}
UDPSession * sessions :: get (uint32 ip, uint16 port)
{
Listhead * POS;
Listhead * head = & bucket [hashfn (ip, port)]. Ipport;
List_for_each (pos, head) {
UDPSession * p = list_entry (POS, UDPSession, IpportItem);
IF (p-> ip == ip && p-> port == port)
Return P;
}
Return NULL;
}
Void sessionhash :: Put (udpsession * p, uint32 ip, uint16 port)
{
INT i = Hashfn (IP, Port);
BUCKET [I] .ipport.addhead (& P-> ipportItem);
}
Void sessionhash :: Put (udpsession * p, uint32 uin) {
INT i = hashfn (uin);
Bucket [i] .uin.addhead (& P-> Uinitem);
}
Void Sessionhash :: Random (icqoutPacket & Out, INT N)
{
UINT16 NUM = 0;
Uint8 * Old = out.skip (sizeof (num));
INT START = RAND32 () & hash_mask;
INT i = start;
Do {
i = ((i 1) & hash_mask;
Listhead * pos, * head = & bucket [i] .ipport;
List_for_each (pos, head) {
UDPSession * s = list_entry (POS, UDPSession, IpportItem);
IF (S-> Status! = status_invis&& s-> status! = status_offline) {
OUT << S-> uin;
OUT << (uint8) 1; // online
OUT << S-> Face;
OUT << S-> nickname;
OUT << S-> province;
IF ( NUM> = n)
Break;
}
}
WHILE (NUM Old = out.setcursor (OLD); OUT << Num; Out.setcursor (OLD); } For such management, I also recognize that this seems to be the best way. Memory assignment: Here, the author is hereby incorporated SLAB, and SLAB is developed in 94 years, with Sun Microsystem Solaris 2.4 operating system, general memory allocation, such as initial testing, no need When SLAB introduces an object's concept, this object is actually a memory area that stores a set of data structures, which is constructor and parsed, for initialization, the latter for recycling. To avoid repeat initialization Objects, SLAB allocation mode does not discard allocated objects, but release but they still reserve in memory. Requests are not re-initialized. Please see the code in MyicQ Struct SLAB; Struct obj { Obj * next; SLAB * SLAB; } Struct SLAB { Listhead item; / * - All SLABs of a cache are a two-way linked list, this is a list pointer * / INT inuse; / * - The number of objects used in this SLAB * / Obj * free; / * - Point to an empty object's pointer, used to assign empty objects * / } Class Cache {// Object Management PUBLIC: Cache (int size, int N); ~ Cache (); void * allocobj (); Void FreeObj (void * p); Static int cable (); Private: SLAB * newsLAB (); INT Reclaim (int N = 0xfffff); Cache * nextcache; Listhead slablish; Listhead * firstNotful1; Int objsize; // Object size INT Numobjs; // Object INT Numfreeslabs; // empty SLABS record Int slabsize; // slab size static cache * cachelist; } In the code, I found that almost all memory allocations use this method. It exists in the definition in each class. Here I think this memory allocation is worth it, can you guarantee the efficient allocation of the server memory! I didn't test it, so I didn't dare to conclude. I suddenly thought of a new memory management method, and I was got to pay attention to and analyze the ISEE project. Can we use the memory management method in ISEE? Is it possible? Improve efficiency, after all, the server can't stop in a few days. About memory management in ISEE can be downloaded in http://isee.126.com, by the way, it is a very good example of learning and development.