精华内容
下载资源
问答
  • Redis一开始是单线程模型,在一个线程中要同时处理两种事件:文件事件和时间事件文件事件主要是网络I/O的读写,请求的接收和回复时间事件就是单次/次执行的定时器,如主从复制、定时删除过期数据、字典rehash等...

    0:redis单线程的实现流程是怎样的?

    Redis一开始是单线程模型,在一个线程中要同时处理两种事件:文件事件和时间事件

    文件事件主要是网络I/O的读写,请求的接收和回复

    时间事件就是单次/多次执行的定时器,如主从复制、定时删除过期数据、字典rehash等

    redis所有核心功能都是跑在主线程中的,像aof文件落盘操作是在子线程中执行的,那么在高并发情况下它是怎么做到高性能的呢?

    由于这两种事件在同一个线程中执行,就会出现互相影响的问题,如时间事件到了还在等待/执行文件事件,或者文件事件已经就绪却在执行时间事件,这就是单线程的缺点,所以在实现上要将这些影响降到最低。那么redis是怎么实现的呢?

    定时执行的时间事件保存在一个链表中,由于链表中任务没有按照执行时间排序,所以每次需要扫描单链表,找到最近需要执行的任务,时间复杂度是O(N),redis敢这么实现就是因为这个链表很短,大部分定时任务都是在serverCron方法中被调用。从现在开始到最近需要执行的任务的开始时间,时长定位T,这段时间就是属于文件事件的处理时间,以epoll为例,执行epoll_wait最多等待的时长为T,如果有就绪任务epoll会返回所有就绪的网络任务,存在一个数组中,这时我们知道了所有就绪的socket和对应的事件(读、写、错误、挂断),然后就可以接收数据,解析,执行对应的命令函数。

    如果最近要执行的定时任务时间已经过了,那么epoll就不会阻塞,直接返回已经就绪的网络事件,即不等待。

    总之单线程,定时事件和网络事件还是会互相影响的,正在处理定时事件网络任务来了,正在处理网络事件定时任务的时间到了。所以redis必须保证每个任务的处理时间不能太长。

    redis处理流程如下:

    1:服务启动,开始网络端口监听,等待客户端请求

    2:客户端想服务端发起连接请求,创建客户端连接对象,完成连接

    3:将socket信息注册到epoll,设置超时时间为时间事件的周期时长,等待客户端发起请求

    4:客户端发起操作数据库请求(如GET)

    5:epoll收到客户端的请求,可能多个,按照顺序处理请求

    6:接收请求参数,接收完成后解析请求协议,得到请求命令

    7:执行请求命令,即操作redis数据库

    8:将结果返回给客户端

    1:redis哪些地方用到了多线程,哪些地方是单线程?

    Redis多线程和单线程模型对比如下图:

    d8fb71476106e9df7198307dc6187b32.png

    从上图中可以看出只有以下3个地方用的是多线程,其他地方都是单线程:

    1:接收请求参数

    2:解析请求参数

    3:请求响应,即将结果返回给client

    很明显以上3点各个请求都是互相独立互不影响的,很适合用多线程,特别是请求体/响应体很大的时候,更能体现多线程的威力。而操作数据库是请求之间共享的,如果使用多线程的话适合读写锁。而操作数据库本身是很快的(就是对map的增删改查),单线程不一定就比多线程慢,当然也有可能是作者偷懒,懒得实现罢了,但这次的多线程模型还是值得我们学习一下的。

    2:redis多线程是怎么实现的?

    先大致说一下多线程的流程:

    1:服务器启动时启动一定数量线程,服务启动的时候可以指定线程数,每个线程对应一个队列(list *io_threads_list[128]),最多128个线程。

    2:服务器收到的每个请求都会放入全局读队列clients_pending_read,同时将队列中的元素分发到每个线程对应的队列io_threads_list中,这些工作都是在主线程中执行的。

    3:每个线程(包括主线程和子线程)接收请求参数并做解析,完事后在client中设置一个标记CLIENT_PENDING_READ,标识参数解析完成,可以操作数据库了。(主线程和子线程都会执行这个步骤)

    4:主线程遍历队列clients_pending_read,发现设有CLIENT_PENDING_READ标记的,就操作数据库

    5:操作完数据库就是响应client了,响应是一组函数addReplyXXX,在client中设置标记CLIENT_PENDING_WRITE,同时将client加入全局写队列clients_pending_write

    6:主线程将全局队列clients_pending_write以轮训的方式将任务分发到每个线程对应的队列io_threads_list

    7:所有线程将遍历自己的队列io_threads_list,将结果发送给client

    3:redis多线程是怎么做到无锁的?

    上面说了多线程的地方都是互相独立互不影响的。但是每个线程的队列就存在两个两个线程访问的情况:主线程向队列中写数据,子线程消费,redis的实现有点反直觉。按正常思路来说,主线程在往队列中写数据的时候加锁;子线程复制队列&并将队列清空,这个两个动作是加锁的,子线程消费复制后的队列,这个过程是不需要加锁的,按理来说主线程和子线程的加锁动作都是非常快的。但是redis并没有这么实现,那么他是怎么实现的呢?

    redis多线程的模型是主线程负责搜集任务,放入全局读队列clients_pending_read和全局写队列clients_pending_write,主线程在将队列中的任务以轮训的方式分发到每个线程对应的队列(list *io_threads_list[128])

    1:一开始子线程的队列都是空,主线程将全对队列中的任务分发到每个线程的队列,并设置一个队列有数据的标记(_Atomic unsigned long io_threads_pending[128]),io_threads_pending[1]=5表示第一个线程的队列中有5个元素

    2:子线程死循环轮训检查io_threads_pending[index] > 0,有数据就开始处理,处理完成之后将io_threads_pending[index] = 0,没数据继续检查

    3:主线程将任务分发到子线程的队列中,自己处理自己队列中的任务,处理完成后,等待所有子线程处理完所有任务,继续收集任务到全局队列,在将任务分发给子线程,这样就避免了主线程和子线程同时访问队列的情况,主线程向队列写的时候子线程还没开始消费,子线程在消费的时候主线程在等待子线程消费完,子线程消费完后主线程才会往队列中继续写,就必须加锁了。因为任务是平均分配到每个队列的,所以每个队列的处理时间是接近的,等待的时间会很短。

    4:源码执行流程

    为了方便你看源码,这里加上一些代码的执行流程

    启动socket监听,注册连接处理函数,连接成功后创建连接对象connection,创建client对象,通过aeCreateFileEvent注册client的读事件

    main -> initServer -> acceptTcpHandler -> anetTcpAccept -> anetGenericAccept -> accept(获取到socket连接句柄)connCreateAcceptedSocket -> connCreateSocket -> 创建一个connection对象acceptCommonHandler -> createClient创建client连接对象 -> connSetReadHandler -> aeCreateFileEvent -> readQueryFromClientmain -> aeMain -> aeProcessEvents -> aeApiPoll(获取可读写的socket) -> readQueryFromClient(如果可读) -> processInputBuffer -> processCommandAndResetClient(多线程下这个方法在当前流程下不会执行,而由主线程执行) 

    在多线程模式下,readQueryFromClient会将client信息加入server.clients_pending_read队列,listAddNodeHead(server.clients_pending_read,c);

    主线程会将server.clients_pending_read中的数据分发到子线程的队列(io_threads_list)中,子线程会调用readQueryFromClient就行参数解析,主线程分发完任务后,会执行具体的操作数据库的命令,这块是单线程

    如果参数解析完成会在client->flags中加一个标记CLIENT_PENDING_COMMAND,在主线程中先判断client->flags & CLIENT_PENDING_COMMAND > 0,说明参数解析完成,才会调用processCommandAndResetClient,之前还担心如果子线程还在做参数解析,主线程就开始执行命令难道不会有问题吗?现在一切都清楚了

    main -> aeMain -> aeProcessEvents -> beforeSleep -> handleClientsWithPendingReadsUsingThreads -> processCommandAndResetClient -> processCommand -> call

    读是多次读:socket读缓冲区有数据,epoll就会一直触发读事件,所以读可能是多次的

    写是一次写:往socket写数据是在子线程中执行的,直接循环直到数据写完位置,就算某个线程阻塞了,也不会像单线程那样导致所有任务都阻塞

    执行完相关命令后,就是将结果返回给client,回复client是一组函数,我们以addReply为例,说一下执行流程,执行addReply还是单线程的,将client信息插入全局队列server.clients_pending_write。addReply -> prepareClientToWrite -> clientInstallWriteHandler -> listAddNodeHead(server.clients_pending_write,c)在主线程中将server.clients_pending_write中的数据以轮训的方式分发到多个子线程中beforeSleep -> handleClientsWithPendingWritesUsingThreads -> 将server.clients_pending_write中的数据以轮训的方式分发到多个线程的队列中io_threads_listlist *io_threads_list[IO_THREADS_MAX_NUM];是数组双向链表,一个线程对应其中一个队列子线程将client中的数据发给客户端,所以是多线程server.c -> main -> initThreadedIO(启动一定数量的线程) -> IOThreadMain(线程执行的方法) -> writeToClient -> connWrite -> connSocketWrite

    网络操作对应的一些方法,所有connection对象的type字段都是指向CT_Socket

    ConnectionType CT_Socket = {    .ae_handler = connSocketEventHandler,    .close = connSocketClose,    .write = connSocketWrite,    .read = connSocketRead,    .accept = connSocketAccept,    .connect = connSocketConnect,    .set_write_handler = connSocketSetWriteHandler,    .set_read_handler = connSocketSetReadHandler,    .get_last_error = connSocketGetLastError,    .blocking_connect = connSocketBlockingConnect,    .sync_write = connSocketSyncWrite,    .sync_read = connSocketSyncRead,    .sync_readline = connSocketSyncReadLine};

    作者:陈太汉
    出处:http://hlxs.cnblogs.com/

    展开全文
  • Redis一开始是单线程模型,在一个线程中要同时处理两种事件:文件事件和时间事件文件事件主要是网络I/O的读写,请求的接收和回复时间事件就是单次/次执行的定时器,如主从复制、定时删除过期数据、字典rehash等...

    0:redis单线程的实现流程是怎样的?

    Redis一开始是单线程模型,在一个线程中要同时处理两种事件:文件事件和时间事件

    文件事件主要是网络I/O的读写,请求的接收和回复

    时间事件就是单次/多次执行的定时器,如主从复制、定时删除过期数据、字典rehash等

    redis所有核心功能都是跑在主线程中的,像aof文件落盘操作是在子线程中执行的,那么在高并发情况下它是怎么做到高性能的呢?

    由于这两种事件在同一个线程中执行,就会出现互相影响的问题,如时间事件到了还在等待/执行文件事件,或者文件事件已经就绪却在执行时间事件,这就是单线程的缺点,所以在实现上要将这些影响降到最低。那么redis是怎么实现的呢?

    定时执行的时间事件保存在一个链表中,由于链表中任务没有按照执行时间排序,所以每次需要扫描单链表,找到最近需要执行的任务,时间复杂度是O(N),redis敢这么实现就是因为这个链表很短,大部分定时任务都是在serverCron方法中被调用。从现在开始到最近需要执行的任务的开始时间,时长定位T,这段时间就是属于文件事件的处理时间,以epoll为例,执行epoll_wait最多等待的时长为T,如果有就绪任务epoll会返回所有就绪的网络任务,存在一个数组中,这时我们知道了所有就绪的socket和对应的事件(读、写、错误、挂断),然后就可以接收数据,解析,执行对应的命令函数。

    如果最近要执行的定时任务时间已经过了,那么epoll就不会阻塞,直接返回已经就绪的网络事件,即不等待。

    总之单线程,定时事件和网络事件还是会互相影响的,正在处理定时事件网络任务来了,正在处理网络事件定时任务的时间到了。所以redis必须保证每个任务的处理时间不能太长。

    redis处理流程如下:

    1:服务启动,开始网络端口监听,等待客户端请求

    2:客户端想服务端发起连接请求,创建客户端连接对象,完成连接

    3:将socket信息注册到epoll,设置超时时间为时间事件的周期时长,等待客户端发起请求

    4:客户端发起操作数据库请求(如GET)

    5:epoll收到客户端的请求,可能多个,按照顺序处理请求

    6:接收请求参数,接收完成后解析请求协议,得到请求命令

    7:执行请求命令,即操作redis数据库

    8:将结果返回给客户端

    1:redis哪些地方用到了多线程,哪些地方是单线程?

    Redis多线程和单线程模型对比如下图:

    e5792166e8aca7b10f4b1815049fa2d6.png

    从上图中可以看出只有以下3个地方用的是多线程,其他地方都是单线程:

    1:接收请求参数

    2:解析请求参数

    3:请求响应,即将结果返回给client

    很明显以上3点各个请求都是互相独立互不影响的,很适合用多线程,特别是请求体/响应体很大的时候,更能体现多线程的威力。而操作数据库是请求之间共享的,如果使用多线程的话适合读写锁。而操作数据库本身是很快的(就是对map的增删改查),单线程不一定就比多线程慢,当然也有可能是作者偷懒,懒得实现罢了,但这次的多线程模型还是值得我们学习一下的。

    2:redis多线程是怎么实现的?

    先大致说一下多线程的流程:

    1:服务器启动时启动一定数量线程,服务启动的时候可以指定线程数,每个线程对应一个队列(list *io_threads_list[128]),最多128个线程。

    2:服务器收到的每个请求都会放入全局读队列clients_pending_read,同时将队列中的元素分发到每个线程对应的队列io_threads_list中,这些工作都是在主线程中执行的。

    3:每个线程(包括主线程和子线程)接收请求参数并做解析,完事后在client中设置一个标记CLIENT_PENDING_READ,标识参数解析完成,可以操作数据库了。(主线程和子线程都会执行这个步骤)

    4:主线程遍历队列clients_pending_read,发现设有CLIENT_PENDING_READ标记的,就操作数据库

    5:操作完数据库就是响应client了,响应是一组函数addReplyXXX,在client中设置标记CLIENT_PENDING_WRITE,同时将client加入全局写队列clients_pending_write

    6:主线程将全局队列clients_pending_write以轮训的方式将任务分发到每个线程对应的队列io_threads_list

    7:所有线程将遍历自己的队列io_threads_list,将结果发送给client

    3:redis多线程是怎么做到无锁的?

    上面说了多线程的地方都是互相独立互不影响的。但是每个线程的队列就存在两个两个线程访问的情况:主线程向队列中写数据,子线程消费,redis的实现有点反直觉。按正常思路来说,主线程在往队列中写数据的时候加锁;子线程复制队列&并将队列清空,这个两个动作是加锁的,子线程消费复制后的队列,这个过程是不需要加锁的,按理来说主线程和子线程的加锁动作都是非常快的。但是redis并没有这么实现,那么他是怎么实现的呢?

    redis多线程的模型是主线程负责搜集任务,放入全局读队列clients_pending_read和全局写队列clients_pending_write,主线程在将队列中的任务以轮训的方式分发到每个线程对应的队列(list *io_threads_list[128])

    1:一开始子线程的队列都是空,主线程将全对队列中的任务分发到每个线程的队列,并设置一个队列有数据的标记(_Atomic unsigned long io_threads_pending[128]),io_threads_pending[1]=5表示第一个线程的队列中有5个元素

    2:子线程死循环轮训检查io_threads_pending[index] > 0,有数据就开始处理,处理完成之后将io_threads_pending[index] = 0,没数据继续检查

    3:主线程将任务分发到子线程的队列中,自己处理自己队列中的任务,处理完成后,等待所有子线程处理完所有任务,继续收集任务到全局队列,在将任务分发给子线程,这样就避免了主线程和子线程同时访问队列的情况,主线程向队列写的时候子线程还没开始消费,子线程在消费的时候主线程在等待子线程消费完,子线程消费完后主线程才会往队列中继续写,就必须加锁了。因为任务是平均分配到每个队列的,所以每个队列的处理时间是接近的,等待的时间会很短。

    4:源码执行流程

    为了方便你看源码,这里加上一些代码的执行流程

    启动socket监听,注册连接处理函数,连接成功后创建连接对象connection,创建client对象,通过aeCreateFileEvent注册client的读事件

    main -> initServer -> acceptTcpHandler -> anetTcpAccept -> anetGenericAccept -> accept(获取到socket连接句柄)connCreateAcceptedSocket -> connCreateSocket -> 创建一个connection对象acceptCommonHandler -> createClient创建client连接对象 -> connSetReadHandler -> aeCreateFileEvent -> readQueryFromClientmain -> aeMain -> aeProcessEvents -> aeApiPoll(获取可读写的socket) -> readQueryFromClient(如果可读) -> processInputBuffer -> processCommandAndResetClient(多线程下这个方法在当前流程下不会执行,而由主线程执行) 

    在多线程模式下,readQueryFromClient会将client信息加入server.clients_pending_read队列,listAddNodeHead(server.clients_pending_read,c);

    主线程会将server.clients_pending_read中的数据分发到子线程的队列(io_threads_list)中,子线程会调用readQueryFromClient就行参数解析,主线程分发完任务后,会执行具体的操作数据库的命令,这块是单线程

    如果参数解析完成会在client->flags中加一个标记CLIENT_PENDING_COMMAND,在主线程中先判断client->flags & CLIENT_PENDING_COMMAND > 0,说明参数解析完成,才会调用processCommandAndResetClient,之前还担心如果子线程还在做参数解析,主线程就开始执行命令难道不会有问题吗?现在一切都清楚了

    main -> aeMain -> aeProcessEvents -> beforeSleep -> handleClientsWithPendingReadsUsingThreads -> processCommandAndResetClient -> processCommand -> call

    读是多次读:socket读缓冲区有数据,epoll就会一直触发读事件,所以读可能是多次的

    写是一次写:往socket写数据是在子线程中执行的,直接循环直到数据写完位置,就算某个线程阻塞了,也不会像单线程那样导致所有任务都阻塞

    执行完相关命令后,就是将结果返回给client,回复client是一组函数,我们以addReply为例,说一下执行流程,执行addReply还是单线程的,将client信息插入全局队列server.clients_pending_write。addReply -> prepareClientToWrite -> clientInstallWriteHandler -> listAddNodeHead(server.clients_pending_write,c)在主线程中将server.clients_pending_write中的数据以轮训的方式分发到多个子线程中beforeSleep -> handleClientsWithPendingWritesUsingThreads -> 将server.clients_pending_write中的数据以轮训的方式分发到多个线程的队列中io_threads_listlist *io_threads_list[IO_THREADS_MAX_NUM];是数组双向链表,一个线程对应其中一个队列子线程将client中的数据发给客户端,所以是多线程server.c -> main -> initThreadedIO(启动一定数量的线程) -> IOThreadMain(线程执行的方法) -> writeToClient -> connWrite -> connSocketWrite

    网络操作对应的一些方法,所有connection对象的type字段都是指向CT_Socket

    ConnectionType CT_Socket = {    .ae_handler = connSocketEventHandler,    .close = connSocketClose,    .write = connSocketWrite,    .read = connSocketRead,    .accept = connSocketAccept,    .connect = connSocketConnect,    .set_write_handler = connSocketSetWriteHandler,    .set_read_handler = connSocketSetReadHandler,    .get_last_error = connSocketGetLastError,    .blocking_connect = connSocketBlockingConnect,    .sync_write = connSocketSyncWrite,    .sync_read = connSocketSyncRead,    .sync_readline = connSocketSyncReadLine};

    作者:陈太汉
    出处:http://hlxs.cnblogs.com/

    展开全文
  • 网上查了人说“是因为io堵塞的原因,因为网速肯定不过cpu,单线程单io通道,而多线程多io通道“ 。我理解他的意思是:单线程因为网速慢赶不上cpu的处理速度,所以造成大量的堵塞,而多线程多io通道,所以堵塞...
    多线程从网上下载一个大文件为什么要更快(比之单线程)?网上查了有人说“是因为io堵塞的原因,因为网速肯定快不过cpu,单线程单io通道,而多线程多io通道“ 。我理解他的意思是:单线程因为网速慢赶不上cpu的处理速度,所以造成大量的堵塞,而多线程多io通道,所以堵塞减少。我的疑问是:同一个多核处理器,io通道会随着线程的增加而一直增加吗?单线的一个io通道和多线程中每个io通道速度都是一样的吗?单线程为什么不能通过提升io通道的速度进而提快速度呢?难道是因为io通道是一个硬件?其速度是受限于硬件的?如果io通道是硬件的话,那么一个处理器的最大io通道个数是不是就是和其核数相等呢?如果真的是我上面猜想的,那么是不是可以认为,如果是单核处理器,通过时间片实现的多线程下载大文件并不能更快呢? 

    c6005dd93611febec98fa7c5e19dd891.png

    决定用户下载大文件速度快慢的终极因素,在于用户下载进程实时抢占网络带宽的大小。其它的因素与它相比,可以忽略不计。 实时最大可用带宽任意一个与互联网通信的进程,理论上都有一个实时最大可用带宽,这是客观存在,不以用户意志为转移。 如果 用户进程实时抢占的带宽 = 实时网络可用带宽 那是最最理想的,用户进程100%利用网络带宽,无论进程(Process)是单线程(Thread)的还是多线程的,下载速度几乎没有任何区别。 理想是丰满的,但现实是骨感的,因为:  用户进程实时抢占的带宽 ≤实时网络可用带宽     Forever!!!  既然如此,如果能让用户进程实时抢占的带宽无限接近实时网络可用带宽,那也是非常完美的。可是,实时网络带宽是多少? 没有人知道!实时网络可用带宽每一刻都在变化! 操作系统很愿意为用户效劳,TCP通过流量探测机制,不间断地探测实时网络可用带宽,并将实时的发送速率与之匹配(相等)起来,这个骚操作看起来很美! 为什么这么说呢?传统的TCP流量探测机制有一个非常致命的缺陷:一旦检测到有丢包,立马将发送速率降为1/2。降速1/2后,如果没有丢包,将会在1/2速率的基础上,按照固定的增长值(线性增长),加大发送的速率。接下来就会一直按照这个节奏到达丢包的那一刻(实时可用带宽)为止。然后再1/2降速,循环往复,直到文件下载结束。 如果下一个检测周期依然有丢包现象,会在当前1/2速率的基础上继续降速1/2。剩下的故事情节以此类推。 

    55de8cb13333b438b81cfe98647655d1.png

    很显然,指数级降速,线性增速,这很不公平!降速很快,但升速却很漫长!造成的直接恶果就是真实的传输速率远远小于实时可用带宽。 多线程Vs 单线程多线程相比单线程的优势是,由于有多个线程在竞争实时可用带宽。尽管多线程逻辑上是并行的,但其实还是按时序的串行处理。所以每个线程处于的阶段并不一致。 在任意时刻,有的线程处于丢包被罚1/2降速,有的线程处于2倍增速阶段(SlowStart),而有的线程处于线性增长阶段。通过多个线程的下载速率的加权平均,得到的是一根相对平滑的下载曲线。这条平滑曲线在大多数时候应该位于单线程下载速率的上方。这就是多线程下载速率更有优势的体现。 但是,如果TCP流量探测机制更加智能,比如BBR算法。BBR算法最大的进步,就是摒弃传统TCP流量调度算法(基于是否丢包而升速或降速), BBR采取的是,实时测量网络最大的可用带宽,并将发送速率与之相匹配,一直在实时可用带宽附近小范围徘徊,避免大起大落的情况发生。测量速率能无限接近实时可用带宽,多线程相比单线程,优势就体现不出来了。  如何成为专业的网络安全工程师?2020会员招募
    展开全文
  • 你去电子城装电脑档口推销人员都会推销电脑时会给你说,我这电脑是多少多少核,多少多少线程大内存,大显存之类的。其中我们最关心的无非就CPU,内存,显卡显存,其中最关心的可能就是CPU了。为什么呢,因为...

    你去电子城装电脑档口推销人员都会推销电脑时会给你说,我这电脑是多少多少核,多少多少线程,多大内存,多大显存之类的。其中我们最关心的无非就CPU,内存,显卡显存,其中最关心的可能就是CPU了。为什么呢,因为其它的都是死的,只要不是假货,那些参数都非常容易选。CPU的性能就决定了你电脑的性能。

    不过其中的一些小坑小伙伴们得注意了。电脑发展太快,很多硬件追都追不上,不是整天接触这类东西的人都不知道现在市场硬件有哪些迭代。加上很多人对电脑并不懂,推销员看你不咋懂便会在介绍时忽悠你。比如经常会拿2核4线程的说成是4核。有人可能会问这有啥区别?双核就是CPU内置真正的2个核心,CPU运作时各自处理各自任务,互不干扰。线程又是什么,线程是指一个CPU分离出来的一个任务。本质就是一个核心通过CPU不断的切换同时进行的任务工作。因为CPU速度非常快,让你感觉不到有切换,但本身是只有一核心在工作。

    现在来说说多核多线程,CPU频率到底该怎么选购。各自又决定了哪些性能,其实如果不谈使用场景,那就是核越多越好,线程越多越好,CPU频率越高越好。如果不谈场景这样是没意义的,比如服务器用的CPU和我们用的CPU从性能上讲单个比自用的还差,他性能上某些方面并不高。为什么,因为服务器要的是稳定,CPU数,线程数,并发量等,需求是不一样的。

    回头说回自用多核多线程,多核数决定了你运作程序时最多能有多少程序独占一个核心工作互不干扰。多线程决定了CPU一个核心下同时处理多少任务互不干扰,当然带来的就是性能上的折扣。核数并非越多性能就一定越好,并不决定你运行单个程序的性能提升,这里还和程序上非常大的关系。。拿现在的3D大型游戏来说,也就最多4核工作,所以你弄个什么8核,16核对你玩游戏是不会有提升的。那该怎么选,这时就要看单核的外频高低了,这时单核外频的高低就决定了你玩游戏的性能,暂不谈显卡,显卡是死的,好的显卡就那些,看显存就可以了。

    如果你说我不是玩游戏,我是弄视频,图片,或3D建模的怎么选。现在这些程序都会有GPU加速,所以这类程序主要从显卡上选择,对CPU要求反而没那么高。

    如果你主要是用来处理多任务的,比如我需要非常多的程序同时运行,但这些程序对CPU外频要求又不高,这时就要考虑多核多线程的CPU了,CPU的外频高低可以放低一些。

    看完了你应该知道怎么选择了吧,总之不差钱,不考虑钱,就往核越多越好,频越高越好,线程越多越好撸之

    突然发现说了好像根没说一样呢?哈哈。。

    展开全文
  • 网上查了人说“是因为io堵塞的原因,因为网速肯定不过cpu,单线程单io通道,而多线程多io通道“ 。我理解他的意思是:单线程因为网速慢赶不上cpu的处理速度,所以造成大量的堵塞,而多线程多io通道,所以堵塞...
  • Python 到底是 线程 还是 进程 文章目录Python 到底是 线程 还是 进程 前言GIL全局解释器锁IO密集型计算密集型 前言 在探究这个 Python 中 到底是 线程 还是 进程 ...对于 IO密集型 的任务来说,多线程
  • 总结: redis是单线程线程安全 redis可以能够快速执行的原因: (1) 绝大部分请求是纯粹的内存操作(非常快速) (2) 采用单线程,避免了不必要的上下文切换和竞争条件 ...IO路复用中三种方式:s...
  • 多线程到底该设置多少个线程?

    千次阅读 2019-06-02 13:26:30
    作者:享学课堂老顾 微信公众号: 享学课堂online 一、前言 “不好了,线上服务器超时严重,请求非常...个严重误区,以为线程池设置太小了,调大点请求就会了。 今天就带着小伙伴们沟通一下,线程池的大小应该...
  • 一、Redis到底有多快 Redis采用的是基于内存的采用的是单进程单线程模型的 KV 数据库,由C语言编写,官方提供的数据是可以达到100000+的QPS(每秒内查询次数)。这个数据不比采用单进程多线程的同样基于内存的 KV ...
  • 一、前言 “不好了,线上服务器超时严重,...个严重误区,以为线程池设置太小了,调大点请求就会了。 今天就带着小伙伴们沟通一下,线程池的大小应该如何合理的设置其大小? 二、问题 如果两个任务需要处理,...
  • 写在前面,Java基础系列文章都是作者基于b站尚硅谷的Java基础视频所做的笔记,没有时间的同学可以认真看看,如果时间的同学,还是建议看看视频,毕竟笔记说到底还是自己的东西,每个人的习惯也是不一样的,所以...
  • threading和multiprocessing四核+三星250G-850-SSD自从用多进程和多线程进行编程,一致没搞懂到底谁更。网上很多都说python多进程更,因为GIL(全局解释器锁)。但是我在写代码的时候,测试时间却是多线程,...
  • 1.单线程架构 Redis基于Reator模式开发了自己的网络事件处理器:文件事件处理器。其架构图如下: 文件事件处理器的四部分:套接字、I/O路复用程序、文件事件分派器和事件处理器。 1.1.套接字Socket 文件事件就是...
  • python3.6threading和multiprocessing四核+三星250G-850-SSD自从用多进程和多线程进行编程,一致没搞懂到底谁更。网上很多都说python多进程更,因为GIL(全局解释器锁)。但是我在写代码的时候,测试时间却是...
  • 最后在山的中间接通,从而打通隧道,这感觉肯定比1了很多,好比多线程但是2成立的前提是必须两个工人。而我们的计算机中一般来说只有一个CPU,也就是说只有一个工人。多线程不过是CPU在不同的...
  • 自从用多进程和多线程进行编程,一致没搞懂到底谁更。网上很多都说python多进程更,因为GIL(全局解释器锁)。但是我在写代码的时候,测试时间却是多线程,所以这到底是怎么回事?最近再做分词工作,原来的...
  • python多进程和多线程谁更python3.6threading和multiprocessing四核+三星250G-850-SSD自从用多进程和多线程进行编程,一致没搞懂到底谁更。网上很多都说python多进程更,因为GIL(全局解释器锁)。但是我在写代码...
  • 自从用多进程和多线程进行编程,一致没搞懂到底谁更。网上很多都说python多进程更,因为GIL(全局解释器锁)。但是我在写代码的时候,测试时间却是多线程,所以这到底是怎么回事?最近再做分词工作,原来的代码...
  • 今天看见je上一帖,对于上亿数据求和的算法,采用多线程到底快还是慢,我认为需要按情况而定。1.单核,无IO,网络等资源操作情况下结果:多线程比单线程理论上要慢原因:多线程启动线程需要消耗cpu资源,多线程只是...
  • 【Redis到底有多快

    2017-10-13 21:09:14
    这个数据不比采用单进程多线程的同样基于内存的KV数据库Memcached差。   Redis的主要原因是: 完全基于内存 数据结构简单,对数据操作也简单 使用多路 I/O 复用模型     单进程单线程好处 代码更清晰...

空空如也

空空如也

1 2 3 4 5 ... 11
收藏数 201
精华内容 80
关键字:

多线程到底有多快