Server IP : 103.119.228.120 / Your IP : 18.191.189.124 Web Server : Apache System : Linux v8.techscape8.com 3.10.0-1160.119.1.el7.tuxcare.els2.x86_64 #1 SMP Mon Jul 15 12:09:18 UTC 2024 x86_64 User : nobody ( 99) PHP Version : 5.6.40 Disable Function : shell_exec,symlink,system,exec,proc_get_status,proc_nice,proc_terminate,define_syslog_variables,syslog,openlog,closelog,escapeshellcmd,passthru,ocinum cols,ini_alter,leak,listen,chgrp,apache_note,apache_setenv,debugger_on,debugger_off,ftp_exec,dl,dll,myshellexec,proc_open,socket_bind,proc_close,escapeshellarg,parse_ini_filepopen,fpassthru,exec,passthru,escapeshellarg,escapeshellcmd,proc_close,proc_open,ini_alter,popen,show_source,proc_nice,proc_terminate,proc_get_status,proc_close,pfsockopen,leak,apache_child_terminate,posix_kill,posix_mkfifo,posix_setpgid,posix_setsid,posix_setuid,dl,symlink,shell_exec,system,dl,passthru,escapeshellarg,escapeshellcmd,myshellexec,c99_buff_prepare,c99_sess_put,fpassthru,getdisfunc,fx29exec,fx29exec2,is_windows,disp_freespace,fx29sh_getupdate,fx29_buff_prepare,fx29_sess_put,fx29shexit,fx29fsearch,fx29ftpbrutecheck,fx29sh_tools,fx29sh_about,milw0rm,imagez,sh_name,myshellexec,checkproxyhost,dosyayicek,c99_buff_prepare,c99_sess_put,c99getsource,c99sh_getupdate,c99fsearch,c99shexit,view_perms,posix_getpwuid,posix_getgrgid,posix_kill,parse_perms,parsesort,view_perms_color,set_encoder_input,ls_setcheckboxall,ls_reverse_all,rsg_read,rsg_glob,selfURL,dispsecinfo,unix2DosTime,addFile,system,get_users,view_size,DirFiles,DirFilesWide,DirPrintHTMLHeaders,GetFilesTotal,GetTitles,GetTimeTotal,GetMatchesCount,GetFileMatchesCount,GetResultFiles,fs_copy_dir,fs_copy_obj,fs_move_dir,fs_move_obj,fs_rmdir,SearchText,getmicrotime MySQL : ON | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : ON Directory : /usr/share/doc/memcached-1.4.15/ |
Upload File : |
WARNING: This document is currently a stub. It is incomplete, but provided to give a vague overview of how threads are implemented. Multithreading in memcached *was* originally simple: - One listener thread - N "event worker" threads - Some misc background threads Each worker thread is assigned connections, and runs its own epoll loop. The central hash table, LRU lists, and some statistics counters are covered by global locks. Protocol parsing, data transfer happens in threads. Data lookups and modifications happen under central locks. THIS HAS CHANGED! I do need to flesh this out more, and it'll need a lot more tuning, but it has changed in the following ways: - A secondary small hash table of locks is used to lock an item by its hash value. This prevents multiple threads from acting on the same item at the same time. - This secondary hash table is mapped to the central hash tables buckets. This allows multiple threads to access the hash table in parallel. Only one thread may read or write against a particular hash table bucket. - atomic refcounts per item are used to manage garbage collection and mutability. - A central lock is still held around any "item modifications" - any change to any item flags on any item, the LRU state, or refcount incrementing are still centrally locked. - When pulling an item off of the LRU tail for eviction or re-allocation, the system must attempt to lock the item's bucket, which is done with a trylock to avoid deadlocks. If a bucket is in use (and not by that thread) it will walk up the LRU a little in an attempt to fetch a non-busy item. Since I'm sick of hearing it: - If you remove the per-thread stats lock, CPU usage goes down by less than a point of a percent, and it does not improve scalability. - In my testing, the remaining global STATS_LOCK calls never seem to collide. Yes, more stats can be moved to threads, and those locks can actually be removed entirely on x86-64 systems. However my tests haven't shown that as beneficial so far, so I've prioritized other work. Apologies for the rant but it's a common question.