Äú¿ÉÒÔ¾èÖú£¬Ö§³ÖÎÒÃǵĹ«ÒæÊÂÒµ¡£

1Ôª 10Ôª 50Ôª





ÈÏÖ¤Â룺  ÑéÖ¤Âë,¿´²»Çå³þ?Çëµã»÷Ë¢ÐÂÑéÖ¤Âë ±ØÌî



  ÇóÖª ÎÄÕ ÎÄ¿â Lib ÊÓÆµ iPerson ¿Î³Ì ÈÏÖ¤ ×Éѯ ¹¤¾ß ½²×ù Modeler   Code  
»áÔ±   
 
   
 
 
     
   
 ¶©ÔÄ
  ¾èÖú
JAVA IO ÒÔ¼° NIO Àí½â
 
×÷Õߣº hapjin À´Ô´£º ²©¿ÍÔ° ·¢²¼ÓÚ 2016-8-9
  2678  次浏览      27
 

ÓÉÓÚNetty£¬Á˽âÁËһЩÒì²½IOµÄ֪ʶ£¬JAVAÀïÃæNIO¾ÍÊÇÔ­À´µÄIOµÄÒ»¸ö²¹³ä£¬±¾ÎÄÖ÷Òª¼Ç¼ÏÂÔÚJAVAÖÐIOµÄµ×²ãʵÏÖÔ­Àí£¬ÒÔ¼°¶ÔZerocopy¼¼Êõ½éÉÜ¡£

IO£¬ÆäʵÒâζ×Å£ºÊý¾Ý²»Í£µØ°áÈë°á³ö»º³åÇø¶øÒÑ£¨Ê¹ÓÃÁË»º³åÇø£©¡£±ÈÈ磬Óû§³ÌÐò·¢Æð¶Á²Ù×÷£¬µ¼Ö¡° syscall read ¡±ÏµÍ³µ÷Ó㬾ͻá°ÑÊý¾Ý°áÈëµ½ Ò»¸öbufferÖУ»Óû§·¢Æðд²Ù×÷£¬µ¼Ö ¡°syscall write ¡±ÏµÍ³µ÷Ó㬽«»á°ÑÒ»¸ö buffer ÖеÄÊý¾Ý °á³öÈ¥(·¢Ë͵½ÍøÂçÖÐ or дÈëµ½´ÅÅÌÎļþ)

ÉÏÃæµÄ¹ý³Ì¿´ËƼòµ¥£¬µ«Êǵײã²Ù×÷ϵͳ¾ßÌåÈçºÎʵÏÖÒÔ¼°ÊµÏÖµÄϸ½Ú¾Í·Ç³£¸´ÔÓÁË¡£ÕýÊÇÒòΪʵÏÖ·½Ê½²»Í¬£¬ÓÐÕë¶ÔÆÕͨÇé¿öϵÄÎļþ´«Êä(ÔÝÇÒ³ÆÆÕͨIO°É)£¬Ò²ÓÐÕë¶Ô´óÎļþ´«Êä»òÕßÅúÁ¿´óÊý¾Ý´«ÊäµÄʵÏÖ·½Ê½£¬±ÈÈçzerocopy¼¼Êõ¡£

ÏÈÀ´¿´Ò»ÕÅÆÕͨµÄIO´¦ÀíµÄÁ÷³Ìͼ£º

Õû¸öIO¹ý³ÌµÄÁ÷³ÌÈçÏ£º

1£©³ÌÐòԱд´úÂë´´½¨Ò»¸ö»º³åÇø£¨Õâ¸ö»º³åÇøÊÇÓû§»º³åÇø£©£º¹þ¹þ¡£È»ºóÔÚÒ»¸öwhileÑ­»·ÀïÃæµ÷ÓÃread()·½·¨¶ÁÊý¾Ý(´¥·¢"syscall read"ϵͳµ÷ÓÃ)

 byte[] b = new byte[4096];

while((read = inputStream.read(b))>=0) {
        total = total + read;
            // other code....
        }

2)µ±Ö´Ðе½read()·½·¨Ê±£¬Æäʵµ×²ãÊÇ·¢ÉúÁ˺ܶà²Ù×÷µÄ£º

¢ÙÄں˸ø´ÅÅÌ¿ØÖÆÆ÷·¢ÃüÁî˵£ºÎÒÒª´Ó¶Á´ÅÅÌÉϵÄijij¿é´ÅÅÌ¿éÉϵÄÊý¾Ý¡£--kernel issuing a command to the disk controller hardware to fetch the data from disk.

¢ÚÔÚDMAµÄ¿ØÖÆÏ£¬°Ñ´ÅÅÌÉϵÄÊý¾Ý¶ÁÈëµ½Äں˻º³åÇø¡£--The disk controller writes the data directly into a kernel memory buffer by DMA

¢ÛÄں˰ÑÊý¾Ý´ÓÄں˻º³åÇø¸´ÖƵ½Óû§»º³åÇø¡£--kernel copies the data from the temporary buffer in kernel space

ÕâÀïµÄÓû§»º³åÇøÓ¦¸Ã¾ÍÊÇÎÒÃÇдµÄ´úÂëÖÐ new µÄ byte[] Êý×é¡£

´ÓÉÏÃæµÄ²½ÖèÖпÉÒÔ·ÖÎö³öʲô£¿

?¶ÔÓÚ²Ù×÷ϵͳ¶øÑÔ£¬JVMÖ»ÊÇÒ»¸öÓû§½ø³Ì£¬´¦ÓÚÓû§Ì¬¿Õ¼äÖС£¶ø´¦ÓÚÓû§Ì¬¿Õ¼äµÄ½ø³ÌÊDz»ÄÜÖ±½Ó²Ù×÷µ×²ãµÄÓ²¼þµÄ¡£¶øIO²Ù×÷¾ÍÐèÒª²Ù×÷µ×²ãµÄÓ²¼þ£¬±ÈÈç´ÅÅÌ¡£Òò´Ë£¬IO²Ù×÷±ØÐëµÃ½èÖúÄں˵İïÖú²ÅÄÜÍê³É(Öжϣ¬trap)£¬¼´£º»áÓÐÓû§Ì¬µ½ÄÚºË̬µÄÇл»¡£

?ÎÒÃÇд´úÂë new byte[] Êý×éʱ£¬Ò»°ãÊǶ¼ÊÇ¡°ËæÒ⡱ ´´½¨Ò»¸ö¡°ÈÎÒâ´óС¡±µÄÊý×é¡£±ÈÈ磬new byte[128]¡¢new byte[1024]¡¢new byte[4096]....

µ«ÊÇ£¬¶ÔÓÚ´ÅÅÌ¿éµÄ¶ÁÈ¡¶øÑÔ£¬Ã¿´Î·ÃÎÊ´ÅÅ̶ÁÊý¾Ýʱ£¬²¢²»ÊǶÁÈÎÒâ´óСµÄÊý¾ÝµÄ£¬¶øÊÇ£ºÃ¿´Î¶ÁÒ»¸ö´ÅÅÌ¿é»òÕßÈô¸É¸ö´ÅÅÌ¿é(ÕâÊÇÒòΪ·ÃÎÊ´ÅÅ̲Ù×÷´ú¼ÛÊǺܴóµÄ£¬¶øÇÒÎÒÃÇÒ²ÏàОֲ¿ÐÔÔ­Àí) Òò´Ë£¬¾ÍÐèÒªÓÐÒ»¸ö¡°Öм仺³åÇø¡±--¼´Äں˻º³åÇø¡£ÏȰÑÊý¾Ý´Ó´ÅÅ̶Áµ½Äں˻º³åÇøÖУ¬È»ºóÔÙ°ÑÊý¾Ý´ÓÄں˻º³åÇø°áµ½Óû§»º³åÇø¡£

ÕâÒ²ÊÇΪʲôÎÒÃÇ×ܸоõµ½µÚÒ»´Îread²Ù×÷ºÜÂý£¬¶øºóÐøµÄread²Ù×÷È´ºÜ¿ìµÄÔ­Òò°É¡£ÒòΪ£¬¶ÔÓÚºóÐøµÄread²Ù×÷¶øÑÔ£¬ËüËùÐèÒª¶ÁµÄÊý¾ÝºÜ¿ÉÄÜÒѾ­ÔÚÄں˻º³åÇøÁË£¬´ËʱֻÐ轫Äں˻º³åÇøÖеÄÊý¾Ý¿½±´µ½Óû§»º³åÇø¼´¿É£¬²¢Î´Éæ¼°µ½µ×²ãµÄ¶ÁÈ¡´ÅÅ̲Ù×÷£¬µ±È»¾Í¿ìÁË¡£

 The kernel tries to cache and/or prefetch data, so the data being requested by the process may already be available in kernel space.
If so, the data requested by the process is copied out. 
If the data isn't available, the process is suspended while the kernel goes about bringing the data into memory.  

Èç¹ûÊý¾Ý²»¿ÉÓã¬process½«»á±»¹ÒÆð£¬²¢ÐèÒªµÈ´ýÄں˴ӴÅÅÌÉϰÑÊý¾ÝÈ¡µ½Äں˻º³åÇøÖС£

ÄÇÎÒÃÇ¿ÉÄÜ»á˵£ºDMAΪʲô²»Ö±½Ó½«´ÅÅÌÉϵÄÊý¾Ý¶ÁÈëµ½Óû§»º³åÇøÄØ£¿Ò»·½ÃæÊÇ ?ÖÐÌáµ½µÄÄں˻º³åÇø×÷Ϊһ¸öÖм仺³åÇø¡£ÓÃÀ´¡°ÊÊÅ䡱Óû§»º³åÇøµÄ¡°ÈÎÒâ´óС¡±ºÍÿ´Î¶Á´ÅÅÌ¿éµÄ¹Ì¶¨´óС¡£ÁíÒ»·½ÃæÔòÊÇ£¬Óû§»º³åÇøÎ»ÓÚÓû§Ì¬¿Õ¼ä£¬¶øDMA¶ÁÈ¡Êý¾ÝÕâÖÖ²Ù×÷Éæ¼°µ½µ×²ãµÄÓ²¼þ£¬Ó²¼þÒ»°ãÊDz»ÄÜÖ±½Ó·ÃÎÊÓû§Ì¬¿Õ¼äµÄ£¨OSµÄÔ­Òò°É£©

×ÛÉÏ£¬ÓÉÓÚDMA²»ÄÜÖ±½Ó·ÃÎÊÓû§¿Õ¼ä(Óû§»º³åÇø)£¬ÆÕͨIO²Ù×÷ÐèÒª½«Êý¾ÝÀ´»ØµØÔÚ Óû§»º³åÇø ºÍ Äں˻º³åÇøÒÆ¶¯£¬ÕâÔÚÒ»¶¨³ÌÐòÉÏÓ°ÏìÁËIOµÄËÙ¶È¡£ÄÇÓÐûÓÐÏàÓ¦µÄ½â¾ö·½°¸ÄØ£¿

ÄǾÍÊÇÖ±½ÓÄÚ´æÓ³ÉäIO£¬Ò²¼´JAVA IOÖÐÌáµ½µÄÄÚ´æÓ³ÉäÎļþ£¬»òÕß˵ Ö±½ÓÄÚ´æ....×ÜÖ®£¬ËüÃDZí´ïµÄÒâ˼¶¼²î²»¶à¡£Ê¾ÀýͼÈçÏ£º

´ÓÉÏͼ¿ÉÒÔ¿´³ö£ºÄں˿ռäµÄ buffer Óë Óû§¿Õ¼äµÄ buffer ¶¼Ó³É䵽ͬһ¿é ÎïÀíÄÚ´æÇøÓò¡£

ËüµÄÖ÷ÒªÌØµãÈçÏ£º

¢Ù¶ÔÎļþµÄ²Ù×÷²»ÐèÒªÔÙ·¢read »òÕß write ϵͳµ÷ÓÃÁË---The user process sees the file data asmemory, so there is no need to issue read() or write() system calls.

¢Úµ±Óû§½ø³Ì·ÃÎÊ¡°ÄÚ´æÓ³ÉäÎļþ¡±µØÖ·Ê±£¬×Ô¶¯²úÉúȱҳ´íÎó£¬È»ºóÓɵײãµÄOS¸ºÔ𽫴ÅÅÌÉϵÄÊý¾ÝË͵½ÄÚ´æ¡£¹ØÓÚҳʽ´æ´¢¹ÜÀí£¬¿É²Î¿¼£ºÄÚ´æ·ÖÅäÓëÄÚ´æ¹ÜÀíµÄһЩÀí½â

 As the user process touches the mapped memory space, page faults will be generated automatically to bring in the file data from disk. 
If the user modifies the mapped memory space, the affected page is automatically marked as dirty and will be subsequently 
flushed to disk to update the file. 

Õâ¾ÍÊÇÊÇJAVA NIOÖÐÌáµ½µÄÄÚ´æÓ³É仺³åÇø£¨Memory-Mapped-Buffer£©ËüÀàËÆÓÚJAVA NIOÖеÄÖ±½Ó»º³åÇø(Directed Buffer)¡£MemoryMappedBuffer¿ÉÒÔͨ¹ýjava.nio.channels.FileChannel.java(ͨµÀ)µÄ map·½·¨´´½¨¡£

ʹÓÃÄÚ´æÓ³É仺³åÇøÀ´²Ù×÷Îļþ£¬Ëü±ÈÆÕͨµÄIO²Ù×÷¶ÁÎļþÒª¿ìµÃ¶à¡£ÉõÖÁ±ÈʹÓÃÎļþͨµÀ(FileChannel)²Ù×÷Îļþ »¹Òª¿ì¡£ÒòΪ£¬Ê¹ÓÃÄÚ´æÓ³É仺³åÇø²Ù×÷Îļþʱ£¬Ã»ÓÐÏÔʾµÄϵͳµ÷ÓÃ(read,write)£¬¶øÇÒOS»¹»á×Ô¶¯»º´æÒ»Ð©ÎļþÒ³(memory page)

zerocopy¼¼Êõ½éÉÜ

¿´ÍêÁËÉÏÃæµÄIO²Ù×÷µÄµ×²ãʵÏÖ¹ý³Ì£¬ÔÙÀ´Á˽âzerocopy¼¼Êõ¾ÍºÜeasyÁË¡£IBMÓÐһƪÃûΪ¡¶Efficient data transfer through zero copy¡·µÄÂÛÎĶÔzerocopy×öÁËÍêÕûµÄ½éÉÜ¡£¸Ð¾õ·Ç³£ºÃ£¬ÏÂÃæ¾Í»ùÓÚÕâÆªÎÄÀ´¼Ç¼ÏÂ×Ô¼ºµÄһЩÀí½â¡£

zerocopy¼¼ÊõµÄÄ¿±ê¾ÍÊÇÌá¸ßIOÃܼ¯ÅªJAVAÓ¦ÓóÌÐòµÄÐÔÄÜ¡£ÔÚ±¾ÎĵÄÇ°Ãæ²¿·Ö½éÉÜÁË£ºIO²Ù×÷ÐèÒªÊý¾ÝƵ·±µØÔÚÄں˻º³åÇøºÍÓû§»º³åÇøÖ®¼ä¿½±´£¬¶øzerocopy¼¼Êõ¿ÉÒÔ¼õÉÙÕâÖÖ¿½±´´ÎÊý£¬Í¬Ê±Ò²½µµÍÁËÉÏÏÂÎÄÇл»(Óû§Ì¬ÓëÄÚºË̬֮¼äµÄÇл»)µÄ´ÎÊý¡£

±ÈÈ磬´ó¶àÊýWEBÓ¦ÓóÌÐòÖ´ÐеÄÒ»Ïî²Ù×÷¾ÍÊÇ£º½ÓÊÜÓû§ÇëÇó--->´Ó±¾µØ´ÅÅ̶ÁÊý¾Ý--->Êý¾Ý½øÈëÄں˻º³åÇø--->Óû§»º³åÇø--->Äں˻º³åÇø--->Óû§»º³åÇø--->socket·¢ËÍ

Êý¾Ýÿ´ÎÔÚÄں˻º³åÇøÓëÓû§»º³åÇøÖ®¼äµÄ¿½±´»áÏûºÄCPUÒÔ¼°ÄÚ´æµÄ´ø¿í¡£¶øzerocopyÓÐЧ¼õÉÙÁËÕâÖÖ¿½±´´ÎÊý¡£

 Each time data traverses the user-kernel boundary, it must be copied, which consumes CPU cycles and memory bandwidth.
Fortunately, you can eliminate these copies through a technique called¡ªappropriately enough ¡ªzero copy

ÄÇËüÊÇÔõô×öµ½µÄÄØ£¿

ÎÒÃÇÖªµÀ£¬JVM(JAVAÐéÄâ»ú)ΪJAVAÓïÑÔÌṩÁË¿çÆ½Ì¨µÄÒ»ÖÂÐÔ£¬ÆÁ±ÎÁ˵ײã²Ù×÷ϵͳµÄ¾ßÌåʵÏÖϸ½Ú£¬Òò´Ë£¬JAVAÓïÑÔÒ²ºÜÄÑÖ±½ÓʹÓõײã²Ù×÷ϵͳÌṩµÄһЩ¡°Ææ¼¼ÒùÇÉ¡±¡£

¶øÒªÊµÏÖzerocopy£¬Ê×ÏȵÃÓвÙ×÷ϵͳµÄÖ§³Ö¡£Æä´Î£¬JDKÀà¿âÒ²ÒªÌṩÏàÓ¦µÄ½Ó¿ÚÖ§³Ö¡£ÐÒÔ˵ÄÊÇ£¬×ÔJDK1.4ÒÔÀ´£¬JDKÌṩÁ˶ÔNIOµÄÖ§³Ö£¬Í¨¹ýjava.nio.channels.FileChannelÀàµÄtransferTo()·½·¨¿ÉÒÔÖ±½Ó½«×Ö½Ú´«Ë͵½¿ÉдµÄͨµÀÖÐ(Writable Channel)£¬²¢²»ÐèÒª½«×Ö½ÚËÍÈëÓû§³ÌÐò¿Õ¼ä(Óû§»º³åÇø)

 You can use the transferTo()method to transfer bytes directly from the channel on which it is invoked to 
another writable byte channel, without requiring data to flow through the application

ÏÂÃæ¾ÍÀ´Ïêϸ·ÖÎöһϾ­µäµÄweb·þÎñÆ÷(±ÈÈçÎļþ·þÎñÆ÷)¸ÉµÄ»î£º´Ó´ÅÅÌÖÐÖжÁÎļþ£¬²¢°ÑÎļþͨ¹ýÍøÂç(socket)·¢Ë͸øClient¡£

 File.read(fileDesc, buf, len);
Socket.send(socket, buf, len);

´Ó´úÂëÉÏ¿´£¬¾ÍÊÇÁ½²½²Ù×÷¡£µÚÒ»²½£º½«Îļþ¶ÁÈëbuf£»µÚ¶þ²½£º½« buf ÖеÄÊý¾Ýͨ¹ýsocket·¢ËͳöÈ¥¡£µ«ÊÇ£¬ÕâÁ½²½²Ù×÷ÐèÒªËÄ´ÎÉÏÏÂÎÄÇл»(Óû§Ì¬ÓëÄÚºË̬֮¼äµÄÇл») ºÍ ËĴο½±´²Ù×÷²ÅÄÜÍê³É¡£

¢ÙµÚÒ»´ÎÉÏÏÂÎÄÇл»·¢ÉúÔÚ read()·½·¨Ö´ÐУ¬±íʾ·þÎñÆ÷Ҫȥ´ÅÅÌÉ϶ÁÎļþÁË£¬Õâ»áµ¼ÖÂÒ»¸ö sys_read()µÄϵͳµ÷ÓᣴËʱÓÉÓû§Ì¬Çл»µ½ÄÚºË̬£¬Íê³ÉµÄ¶¯×÷ÊÇ£ºDMA°Ñ´ÅÅÌÉϵÄÊý¾Ý¶ÁÈëµ½Äں˻º³åÇøÖУ¨ÕâÒ²ÊǵÚÒ»´Î¿½±´£©¡£

¢ÚµÚ¶þ´ÎÉÏÏÂÎÄÇл»·¢ÉúÔÚread()·½·¨µÄ·µ»Ø(ÕâҲ˵Ã÷read()ÊÇÒ»¸ö×èÈûµ÷ÓÃ)£¬±íʾÊý¾ÝÒѾ­³É¹¦´Ó´ÅÅÌÉ϶Áµ½Äں˻º³åÇøÁË¡£´Ëʱ£¬ÓÉÄÚºË̬·µ»Øµ½Óû§Ì¬£¬Íê³ÉµÄ¶¯×÷ÊÇ£º½«Äں˻º³åÇøÖеÄÊý¾Ý¿½±´µ½Óû§»º³åÇø£¨ÕâÊǵڶþ´Î¿½±´£©¡£

¢ÛµÚÈý´ÎÉÏÏÂÎÄÇл»·¢ÉúÔÚ send()·½·¨Ö´ÐУ¬±íʾ·þÎñÆ÷×¼±¸°ÑÊý¾Ý·¢ËͳöÈ¥ÁË¡£´Ëʱ£¬ÓÉÓû§Ì¬Çл»µ½ÄÚºË̬£¬Íê³ÉµÄ¶¯×÷ÊÇ£º½«Óû§»º³åÇøÖеÄÊý¾Ý¿½±´µ½Äں˻º³åÇø(ÕâÊǵÚÈý´Î¿½±´)

¢ÜµÚËÄ´ÎÉÏÏÂÎÄÇл»·¢ÉúÔÚ send()·½·¨µÄ·µ»Ø¡¾ÕâÀïµÄsend()·½·¨¿ÉÒÔÒì²½·µ»Ø£¬ËùνÒì²½·µ»Ø¾ÍÊÇ£ºÏß³ÌÖ´ÐÐÁËsend()Ö®ºóÁ¢¼´´Ósend()·µ»Ø£¬Ê£ÏµÄÊý¾Ý¿½±´¼°·¢Ë;ͽ»¸øµ×²ã²Ù×÷ϵͳʵÏÖÁË¡¿¡£´Ëʱ£¬ÓÉÄÚºË̬·µ»Øµ½Óû§Ì¬£¬Íê³ÉµÄ¶¯×÷ÊÇ£º½«Äں˻º³åÇøÖеÄÊý¾ÝË͵½ protocol engine.£¨ÕâÊǵÚËĴο½±´£©

ÕâÀï¶Ô protocol engine²»ÊÇÌ«Á˽⣬µ«ÊÇ´ÓÉÏÃæµÄʾÀýͼÀ´¿´£ºËüÊÇNIC(NetWork Interface Card) buffer¡£Íø¿¨µÄbuffer???

ÏÂÃæÕâ¶Î»°£¬·Ç³£ÖµµÃÒ»¶Á£ºÕâÀïÔÙÒ»´ÎÌáµ½ÁËΪʲôÐèÒªÄں˻º³åÇø¡£

 Use of the intermediate kernel buffer (rather than a direct transfer of the data
into the user buffer)might seem inefficient. But intermediate kernel buffers were 
introduced into the process to improve performance. Using the intermediate 
buffer on the read side allows the kernel buffer to act as a "readahead cache" 
when the application hasn't asked for as much data as the kernel buffer holds.
This significantly improves performance when the requested data amount is less
than the kernel buffer size. The intermediate buffer on the write side allows the write to complete asynchronously.

Ò»¸öºËÐĹ۵ã¾ÍÊÇ£ºÄں˻º³åÇøÌá¸ßÁËÐÔÄÜ¡£ß×£¿ÊDz»ÊÇºÜÆæ¹Ö£¿ÒòÎªÇ°ÃæÒ»Ö±ËµÕýÊÇÒòΪÒýÈëÁËÄں˻º³åÇø(Öм仺³åÇø)£¬Ê¹µÃÊý¾ÝÀ´»ØµØ¿½±´£¬½µµÍÁËЧÂÊ¡£

ÄÇÏÈÀ´¿´¿´£¬ËüΪʲô˵Äں˻º³åÇøÌá¸ßÁËÐÔÄÜ¡£

¶ÔÓÚ¶Á²Ù×÷¶øÑÔ£¬Äں˻º³åÇø¾ÍÏ൱ÓÚÒ»¸ö¡°readahead cache¡±£¬µ±Óû§³ÌÐòÒ»´ÎÖ»ÐèÒª¶ÁһС²¿·ÖÊý¾Ýʱ£¬Ê×ÏȲÙ×÷ϵͳ´Ó´ÅÅÌÉ϶ÁÒ»´ó¿éÊý¾Ýµ½Äں˻º³åÇø£¬Óû§³ÌÐòֻȡ×ßÁËһС²¿·Ö( ÎÒ¿ÉÒÔÖ» new ÁËÒ»¸ö 128BµÄbyteÊý×é°¡! new byte[128])¡£µ±Óû§³ÌÐòÏÂÒ»´ÎÔÙ¶ÁÊý¾Ý£¬¾Í¿ÉÒÔÖ±½Ó´ÓÄں˻º³åÇøÖÐÈ¡ÁË£¬²Ù×÷ϵͳ¾Í²»ÐèÒªÔٴηÃÎÊ´ÅÅÌÀ²£¡ÒòΪÓû§Òª¶ÁµÄÊý¾ÝÒѾ­ÔÚÄں˻º³åÇøÀ²£¡ÕâÒ²ÊÇÇ°ÃæÌáµ½µÄ£ºÎªÊ²Ã´ºóÐøµÄ¶Á²Ù×÷(read()·½·¨µ÷ÓÃ)ÒªÃ÷ÏԵرȵÚÒ»´Î¿ìµÄÔ­Òò¡£´ÓÕâ¸ö½Ç¶È¶øÑÔ£¬Äں˻º³åÇøÈ·ÊµÌá¸ßÁ˶Á²Ù×÷µÄÐÔÄÜ¡£

ÔÙÀ´¿´Ð´²Ù×÷£º¿ÉÒÔ×öµ½ ¡°Ò첽д¡±£¨write asynchronously£©¡£Ò²¼´£ºwirte(dest[]) ʱ£¬Óû§³ÌÐò¸æËß²Ù×÷ϵͳ£¬°Ñdest[]Êý×éÖеÄÄÚÈÝдµ½XXÎļþÖÐÈ¥£¬ÓÚÊÇwrite·½·¨¾Í·µ»ØÁË¡£²Ù×÷ϵͳÔòÔÚºǫ́ĬĬµØ°ÑÓû§»º³åÇøÖеÄÄÚÈÝ(dest[])¿½±´µ½Äں˻º³åÇø£¬ÔÙ°ÑÄں˻º³åÇøÖеÄÊý¾ÝдÈë´ÅÅÌ¡£ÄÇô£¬Ö»ÒªÄں˻º³åÇøÎ´Âú£¬Óû§µÄwrite²Ù×÷¾Í¿ÉÒÔºÜ¿ìµØ·µ»Ø¡£ÕâÓ¦¸Ã¾ÍÊÇÒ첽ˢÅ̲ßÂÔ°É¡£

(Æäʵ£¬µ½ÕâÀï¡£ÒÔǰһ¸ö¾À½áµÄÎÊÌâ¾ÍÊÇͬ²½IO£¬Òì²½IO£¬×èÈûIO£¬·Ç×èÈûIOÖ®¼äµÄÇø±ðÒѾ­Ã»ÓÐÌ«´óµÄÒâÒåÁË¡£ÕâЩ¸ÅÄֻÊÇÕë¶ÔµÄ¿´ÎÊÌâµÄ½Ç¶È²»Ò»Ñù¶øÒÑ¡£×èÈû¡¢·Ç×èÈûÊÇÕë¶ÔÏß³Ì×ÔÉí¶øÑÔ£»Í¬²½¡¢Òì²½ÊÇÕë¶ÔÏß³ÌÒÔ¼°Ó°ÏìËüµÄÍⲿʼþ¶øÑÔ....)

 Unfortunately, this approach itself can become a performance bottleneck if the size of the data requested 
is considerably larger than the kernel buffer size. The data gets copied multiple times among the disk, kernel buffer, 
and user buffer before it is finally delivered to the application.
Zero copy improves performance by eliminating these redundant data copies.

ÖÕÓÚÂÖµ½zerocopy·ÛÄ«µÇ³¡ÁË¡£µ±ÐèÒª´«ÊäµÄÊý¾ÝÔ¶Ô¶´óÓÚÄں˻º³åÇøµÄ´óСʱ£¬Äں˻º³åÇø¾Í»á³ÉΪƿ¾±¡£ÕâÒ²ÊÇΪʲôzerocopy¼¼ÊõºÏÊÊ´óÎļþ´«ÊäµÄÔ­Òò¡£Äں˻º³åÇøÎªÉ¶³ÉΪÁËÆ¿¾±£¿---ÎÒÏ룬ºÜ´óµÄÒ»¸öÔ­ÒòÊÇËüÒѾ­Æð²»µ½¡°»º³å¡±µÄ¹¦ÄÜÁË£¬±Ï¾¹´«ÊäµÄÊý¾ÝÁ¿Ì«´óÁË¡£

ÏÂÃæÀ´¿´¿´zerocopy¼¼ÊõÊÇÈçºÎÀ´´¦ÀíÎļþ´«ÊäµÄ¡£

µ± transferTo()·½·¨ ±»µ÷ÓÃʱ£¬ÓÉÓû§Ì¬Çл»µ½ÄÚºË̬¡£Íê³ÉµÄ¶¯×÷ÊÇ£ºDMA½«Êý¾Ý´Ó´ÅÅ̶ÁÈë Read bufferÖÐ(µÚÒ»´ÎÊý¾Ý¿½±´)¡£È»ºó£¬»¹ÊÇÔÚÄں˿ռäÖУ¬½«Êý¾Ý´ÓRead buffer ¿½±´µ½ Socket buffer(µÚ¶þ´ÎÊý¾Ý¿½±´)£¬×îÖÕÔÙ½«Êý¾Ý´Ó Socket buffer ¿½±´µ½ NIC buffer(µÚÈý´ÎÊý¾Ý¿½±´)¡£È»ºó£¬ÔÙ´ÓÄÚºË̬·µ»Øµ½Óû§Ì¬¡£

ÉÏÃæÕû¸ö¹ý³Ì¾Íֻɿ¼°µ½ÁË£ºÈý´ÎÊý¾Ý¿½±´ºÍ¶þ´ÎÉÏÏÂÎÄÇл»¡£¸Ð¾õÒ²²Å¼õÉÙÁËÒ»´ÎÊý¾Ý¿½±´Âï¡£µ«ÕâÀïÒѾ­²»Éæ¼°Óû§¿Õ¼äµÄ»º³åÇøÁË¡£

Èç¹û˵zerocopy¼¼ÊõÖ»ÄÜÍê³Éµ½Õâ²½£¬ÄÇÒ²¾Í just so so ÁË¡£

 This is an improvement: we've reduced the number of context switches from four to two and reduced the number of data copies
from four to three (only one of which involves the CPU)

Èý´ÎÊý¾Ý¿½±´ÖУ¬Ò²Ö»ÓÐÒ»´Î¿½±´ÐèÒªµ½CPUµÄ¸ÉÔ¤¡££¨µÚ2´Î¿½±´£©£¬¶øÇ°ÃæµÄ´«Í³Êý¾Ý¿½±´ÐèÒªËÄ´ÎÇÒÓÐÈý´Î¿½±´ÐèÒªCPUµÄ¸ÉÔ¤¡£

 We can further reduce the data duplication done by the kernel if the underlying network interface card supports 
gather operations. In Linux kernels 2.4 and later, the socket buffer descriptor was modified to accommodate this requirement. 
This approach not only reduces multiple context switches but also eliminates the duplicated data copies that 
require CPU involvement.

Ò²¾ÍÊÇ˵£¬Èç¹ûµ×²ãµÄÍøÂçÓ²¼þÒÔ¼°²Ù×÷ϵͳ֧³Ö£¬»¹¿ÉÒÔ½øÒ»²½¼õÉÙÊý¾Ý¿½±´´ÎÊý ÒÔ¼° CPU¸ÉÔ¤´ÎÊý¡£

´ÓÉÏͼ¿´³ö£ºÕâÀïÒ»¹²Ö»ÓÐÁ½´Î¿½±´ ºÍ Á½´ÎÉÏÏÂÎÄÇл»¡£¶øÇÒÕâÁ½´Î¿½±´¶¼ÊÇDMA copy£¬²¢²»ÐèÒªCPU¸ÉÔ¤(ÑϽ÷Ò»µãµÄ»°¾ÍÊDz»ÍêÈ«ÐèÒª°É.)¡£

Õû¸ö¹ý³ÌÈçÏ£º

Óû§³ÌÐòÖ´ÐÐ transferTo()·½·¨£¬µ¼ÖÂÒ»´Îϵͳµ÷Ó㬴ÓÓû§Ì¬Çл»µ½ÄÚºË̬¡£Íê³ÉµÄ¶¯×÷ÊÇ£ºDMA½«Êý¾Ý´Ó´ÅÅÌÖп½±´µ½Read buffer

ÓÃÒ»¸öÃèÊö·û±ê¼Ç´Ë´Î´ý´«ÊäÊý¾ÝµÄµØÖ·ÒÔ¼°³¤¶È£¬DMAÖ±½Ó°ÑÊý¾Ý´ÓRead buffer ´«Êäµ½ NIC buffer¡£Êý¾Ý¿½±´¹ý³Ì¶¼²»ÓÃCPU¸ÉÔ¤ÁË¡£

×ܽ᣺

ÕâÆªÎÄÕ´ÓIOµ×²ãʵÏÖÔ­Àí¿ªÊ¼½²½â£¬·ÖÎöÁËIOµ×²ãʵÏÖϸ½ÚµÄһЩÓÅȱµã£¬ÒÔ¼°ÎªÊ²Ã´ÒýÈëzerocopy¼¼ÊõºÍzerocopy¼¼ÊõµÄʵÏÖÔ­Àí¡£¸öÈ˵Äѧϰ¼Ç¼£¬×ªÔØÇë×¢Ã÷³ö´¦¡£

 

   
2678 ´Îä¯ÀÀ       27
Ïà¹ØÎÄÕÂ

Java΢·þÎñÐÂÉú´úÖ®Nacos
ÉîÈëÀí½âJavaÖеÄÈÝÆ÷
JavaÈÝÆ÷Ïê½â
Java´úÂëÖÊÁ¿¼ì²é¹¤¾ß¼°Ê¹Óð¸Àý
Ïà¹ØÎĵµ

JavaÐÔÄÜÓÅ»¯
Spring¿ò¼Ü
SSM¿ò¼Ü¼òµ¥¼òÉÜ
´ÓÁ㿪ʼѧjava±à³Ì¾­µä
Ïà¹Ø¿Î³Ì

¸ßÐÔÄÜJava±à³ÌÓëϵͳÐÔÄÜÓÅ»¯
JavaEE¼Ü¹¹¡¢ Éè¼ÆÄ£Ê½¼°ÐÔÄܵ÷ÓÅ
Java±à³Ì»ù´¡µ½Ó¦Óÿª·¢
JAVAÐéÄâ»úÔ­ÀíÆÊÎö
×îл¼Æ»®
DeepSeekÔÚÈí¼þ²âÊÔÓ¦ÓÃʵ¼ù 4-12[ÔÚÏß]
DeepSeek´óÄ£ÐÍÓ¦Óÿª·¢Êµ¼ù 4-19[ÔÚÏß]
UAF¼Ü¹¹ÌåϵÓëʵ¼ù 4-11[±±¾©]
AIÖÇÄÜ»¯Èí¼þ²âÊÔ·½·¨Óëʵ¼ù 5-23[ÉϺ£]
»ùÓÚ UML ºÍEA½øÐзÖÎöÉè¼Æ 4-26[±±¾©]
ÒµÎñ¼Ü¹¹Éè¼ÆÓ뽨ģ 4-18[±±¾©]

Java ÖеÄÖÐÎıàÂëÎÊÌâ
Java»ù´¡ÖªÊ¶µÄÈýÊ®¸ö¾­µäÎÊ´ð
Íæ×ª Java Web Ó¦Óÿª·¢
ʹÓÃSpring¸üºÃµØ´¦ÀíStruts
ÓÃEclipse¿ª·¢iPhone WebÓ¦ÓÃ
²å¼þϵͳ¿ò¼Ü·ÖÎö

Struts+Spring+Hibernate
»ùÓÚJ2EEµÄWeb 2.0Ó¦Óÿª·¢
J2EEÉè¼ÆÄ£Ê½ºÍÐÔÄܵ÷ÓÅ
Java EE 5ÆóÒµ¼¶¼Ü¹¹Éè¼Æ
Javaµ¥Ôª²âÊÔ·½·¨Óë¼¼Êõ
Java±à³Ì·½·¨Óë¼¼Êõ

Struts+Spring+Hibernate/EJB+ÐÔÄÜÓÅ»¯
»ªÏÄ»ù½ð ActiveMQ Ô­ÀíÓë¹ÜÀí
ijÃñº½¹«Ë¾ Java»ù´¡±à³Ìµ½Ó¦Óÿª·¢
ij·çµç¹«Ë¾ Java Ó¦Óÿª·¢Æ½Ì¨ÓëÇ¨ÒÆ
ÈÕÕÕ¸Û J2EEÓ¦Óÿª·¢¼¼Êõ¿ò¼ÜÓëʵ¼ù
ij¿ç¹ú¹«Ë¾ ¹¤×÷Á÷¹ÜÀíJBPM
¶«·½º½¿Õ¹«Ë¾ ¸ß¼¶J2EE¼°ÆäÇ°ÑØ¼¼Êõ