nvme的设备,可以调优的参数比较少,相关的代码如下:

blk_sysfs.c

static struct queue_sysfs_entry queue_requests_entry = {
.attr = {.name = "nr_requests", .mode = S_IRUGO | S_IWUSR },
.show = queue_requests_show,
.store = queue_requests_store,
}; static struct queue_sysfs_entry queue_ra_entry = {
.attr = {.name = "read_ahead_kb", .mode = S_IRUGO | S_IWUSR },
.show = queue_ra_show,
.store = queue_ra_store,
}; static struct queue_sysfs_entry queue_max_sectors_entry = {
.attr = {.name = "max_sectors_kb", .mode = S_IRUGO | S_IWUSR },
.show = queue_max_sectors_show,
.store = queue_max_sectors_store,
}; static struct queue_sysfs_entry queue_max_hw_sectors_entry = {
.attr = {.name = "max_hw_sectors_kb", .mode = S_IRUGO },
.show = queue_max_hw_sectors_show,
}; static struct queue_sysfs_entry queue_max_segments_entry = {
.attr = {.name = "max_segments", .mode = S_IRUGO },
.show = queue_max_segments_show,
}; static struct queue_sysfs_entry queue_max_integrity_segments_entry = {
.attr = {.name = "max_integrity_segments", .mode = S_IRUGO },
.show = queue_max_integrity_segments_show,
}; static struct queue_sysfs_entry queue_max_segment_size_entry = {
.attr = {.name = "max_segment_size", .mode = S_IRUGO },
.show = queue_max_segment_size_show,
}; static struct queue_sysfs_entry queue_iosched_entry = {
.attr = {.name = "scheduler", .mode = S_IRUGO | S_IWUSR },
.show = elv_iosched_show,
.store = elv_iosched_store,
}; static struct queue_sysfs_entry queue_hw_sector_size_entry = {
.attr = {.name = "hw_sector_size", .mode = S_IRUGO },
.show = queue_logical_block_size_show,
}; static struct queue_sysfs_entry queue_logical_block_size_entry = {
.attr = {.name = "logical_block_size", .mode = S_IRUGO },
.show = queue_logical_block_size_show,
}; static struct queue_sysfs_entry queue_physical_block_size_entry = {
.attr = {.name = "physical_block_size", .mode = S_IRUGO },
.show = queue_physical_block_size_show,
}; static struct queue_sysfs_entry queue_io_min_entry = {
.attr = {.name = "minimum_io_size", .mode = S_IRUGO },
.show = queue_io_min_show,
}; static struct queue_sysfs_entry queue_io_opt_entry = {
.attr = {.name = "optimal_io_size", .mode = S_IRUGO },
.show = queue_io_opt_show,
}; static struct queue_sysfs_entry queue_discard_granularity_entry = {
.attr = {.name = "discard_granularity", .mode = S_IRUGO },
.show = queue_discard_granularity_show,
}; static struct queue_sysfs_entry queue_discard_max_entry = {
.attr = {.name = "discard_max_bytes", .mode = S_IRUGO },
.show = queue_discard_max_show,
}; static struct queue_sysfs_entry queue_discard_zeroes_data_entry = {
.attr = {.name = "discard_zeroes_data", .mode = S_IRUGO },
.show = queue_discard_zeroes_data_show,
}; static struct queue_sysfs_entry queue_write_same_max_entry = {
.attr = {.name = "write_same_max_bytes", .mode = S_IRUGO },
.show = queue_write_same_max_show,
}; static struct queue_sysfs_entry queue_nonrot_entry = {
.attr = {.name = "rotational", .mode = S_IRUGO | S_IWUSR },
.show = queue_show_nonrot,
.store = queue_store_nonrot,
}; static struct queue_sysfs_entry queue_unpriv_sgio_entry = {
.attr = {.name = "unpriv_sgio", .mode = S_IRUGO | S_IWUSR },
.show = queue_show_unpriv_sgio,
.store = queue_store_unpriv_sgio,
}; static struct queue_sysfs_entry queue_nomerges_entry = {
.attr = {.name = "nomerges", .mode = S_IRUGO | S_IWUSR },
.show = queue_nomerges_show,
.store = queue_nomerges_store,
}; static struct queue_sysfs_entry queue_rq_affinity_entry = {
.attr = {.name = "rq_affinity", .mode = S_IRUGO | S_IWUSR },
.show = queue_rq_affinity_show,
.store = queue_rq_affinity_store,
}; static struct queue_sysfs_entry queue_iostats_entry = {
.attr = {.name = "iostats", .mode = S_IRUGO | S_IWUSR },
.show = queue_show_iostats,
.store = queue_store_iostats,
}; static struct queue_sysfs_entry queue_random_entry = {
.attr = {.name = "add_random", .mode = S_IRUGO | S_IWUSR },
.show = queue_show_random,
.store = queue_store_random,
};

参数列表如下:

[root@localhost queue]# ls -alrt *
-rw-r--r-- root root Dec : read_ahead_kb
-rw-r--r-- root root Dec : nomerges
-rw-r--r-- root root Dec : rq_affinity
-rw-r--r-- root root Dec : max_sectors_kb
-rw-r--r-- root root Dec : nr_requests
-rw-r--r-- root root Dec : iostats
-r--r--r-- root root Dec : write_same_max_bytes
-rw-r--r-- root root Dec : unpriv_sgio
-rw-r--r-- root root Dec : scheduler
-rw-r--r-- root root Dec : rotational
-r--r--r-- root root Dec : physical_block_size
-r--r--r-- root root Dec : optimal_io_size
-r--r--r-- root root Dec : minimum_io_size
-r--r--r-- root root Dec : max_segments
-r--r--r-- root root Dec : max_segment_size
-r--r--r-- root root Dec : max_integrity_segments
-r--r--r-- root root Dec : max_hw_sectors_kb
-r--r--r-- root root Dec : logical_block_size
-r--r--r-- root root Dec : hw_sector_size
-r--r--r-- root root Dec : discard_zeroes_data
-r--r--r-- root root Dec : discard_max_bytes
-r--r--r-- root root Dec : discard_granularity
-rw-r--r-- root root Dec : add_random

其中属性为只读的,肯定直接通过/sys/没法修改,有的硬编码的跟驱动相关,可以尝试修改驱动。其余可以尝试调优的参数如下:

1.nomerges (RW)
------------- This enables the user to disable the lookup logic involved with IO merging requests in the block layer. By default (0) all merges are enabled. When set to 1 only simple one-hit merges will be tried. When set to 2 no merge algorithms will be tried (including one-hit or more complex tree/hash lookups).

这个根据打开的统计,发现iostat里面前面的两列关于merge的,都一直为0,所以干脆设置为不要merge,可以减少一段代码逻辑,代码中会判断queue的merge属性,

当其值为0,说明  QUEUE_FLAG_NOXMERGES 和 QUEUE_FLAG_NOMERGES 都没有设置。这个设置为2,表示不需要merge,机械盘一般设置为需要merge,相关代码如下:

static ssize_t queue_nomerges_store(struct request_queue *q, const char *page,
size_t count)
{
unsigned long nm;
ssize_t ret = queue_var_store(&nm, page, count); if (ret < )
return ret; spin_lock_irq(q->queue_lock);
queue_flag_clear(QUEUE_FLAG_NOMERGES, q);
queue_flag_clear(QUEUE_FLAG_NOXMERGES, q);
if (nm == )
queue_flag_set(QUEUE_FLAG_NOMERGES, q);-----------值为2,则设置QUEUE_FLAG_NOMERGES
else if (nm)
queue_flag_set(QUEUE_FLAG_NOXMERGES, q); ----------值为非0,则设置QUEUE_FLAG_NOXMERGES
spin_unlock_irq(q->queue_lock);
return ret;
}

2.rq_affinity (RW)
---------------- If this option is '1', the block layer will migrate request completions to the cpu "group" that originally submitted the request. For some workloads this provides a significant reduction in CPU cycles due to caching effects.
For storage configurations that need to maximize distribution of completion processing setting this option to '2' forces the completion to run on the requesting cpu (bypassing the "group" aggregation logic).

因为cache的命中,这个设置为2,可以减少cpu使用。

3.add_random (RW)
---------------- This file allows to trun off the disk entropy contribution. Default value of this file is '1'(on).

这个最好设置为0,可以减少一点点性能消耗。

readahead参数,是如何影响nvme的性能的?一开始以为这个对机械盘影响较大,后来根据追踪代码,发现对io的及时性还是有较大的提高。

下面的代码描述了初始化阶段设置的大小,这个如果可以的话,建议设置大一些,比如1M。

struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id)
{
struct request_queue *q;
struct queue_limits_aux *limits_aux = NULL;
int err; q = kmem_cache_alloc_node(blk_requestq_cachep,
gfp_mask | __GFP_ZERO, node_id);
if (!q)
return NULL; q->id = ida_simple_get(&blk_queue_ida, , , gfp_mask);
if (q->id < )
goto fail_q; q->backing_dev_info.ra_pages =
(VM_MAX_READAHEAD * ) / PAGE_CACHE_SIZE;//初始化预读参数,默认为128k

4.中断绑核

我们知道,nvme的队列名称,其实是根据核数来编号的,因为admin的队列和io队列的第一个是共享一个中断的,所以他俩的中断数会相对比其他io队列多一些,由于队列默认就是跟随

cpu号而绑定的,所以中断号,最好送到指定的cpu上去,因为中断上下文毕竟是要访问内存的,具体怎么绑,可以参照如下:

查看/proc/interrupt,中断名称是nvme0q0,当然类似的nvme1q0也是,以此类推,这个肯定是admin队列。

io队列就是nvme0q1----nvme0qx,其中x就是cpu的核数。

nvme0q1这个对列,其实默认就是在cpu0上,那么对应的中断,最好也绑在cpu0上。

nvme0q30这个队列,默认在cpu29上,那么对应的中断,最好也绑在cpu29上。以此类推。


linux的nvme驱动参数调优的更多相关文章

  1. Linux内核 TCP/IP参数调优

    http://www.360doc.com/content/14/0606/16/3300331_384326124.shtml

  2. Linux内核 TCP/IP、Socket参数调优

    Linux内核 TCP/IP.Socket参数调优 2014-06-06  Harrison....   阅 9611  转 165 转藏到我的图书馆   微信分享:   Doc1: /proc/sy ...

  3. Linux Linux内核参数调优

    Linux内核参数调优 by:授客 QQ:1033553122 关于调优的建议: 1.出错时,可以查看操作系统日志,可能会找到一些有用的信息 2.尽量不要“批量”修改内核参数,笔者就曾这么干过,结果“ ...

  4. (转)linux IO 内核参数调优 之 参数调节和场景分析

    1. pdflush刷新脏数据条件 (linux IO 内核参数调优 之 原理和参数介绍)上一章节讲述了IO内核调优介个重要参数参数. 总结可知cached中的脏数据满足如下几个条件中一个或者多个的时 ...

  5. Linux上TCP的几个内核参数调优

    Linux作为一个强大的操作系统,提供了一系列内核参数供我们进行调优.光TCP的调优参数就有50多个.在和线上问题斗智斗勇的过程中,笔者积累了一些在内网环境应该进行调优的参数.在此分享出来,希望对大家 ...

  6. linux 服务器安全加固和内核参数调优 nf_conntrack

    0.内部设置跳板机,服务器只能通过跳板机登录1.禁止ROOT用户远程登录和登录端口 禁止ROOT用户远程登录 .打开 /etc/ssh/sshd_config PermitRootLogin no . ...

  7. 大数据集群Linux CentOS 7.6 系统调优篇

    大数据集群Linux CentOS 7.6 系统调优篇 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.设置主机hosts文件 1>.修改主机名 [root@node100 ...

  8. (转)JVM参数调优八大技巧

    这里和大家分享一下JVM参数调优的八条经验,JVM参数调优,这是很头痛的问题,设置的不好,JVM不断执行FullGC,导致整个系统变得很慢,网站停滞时间能达10秒以上,相信通过本文的学习你对JVM参数 ...

  9. JVM性能参数调优实践,不会执行Full GC,网站无停滞

    原文来自:http://bbs.csdn.net/topics/310110257 本文只做整理记录,供个人学习. 1 JVM参数调优是个很头痛的问题,设置的不好,JVM不断执行Full GC,导致整 ...

随机推荐

  1. [Python学习] Django 权限控制

    本文为大家讲解 Django 框架里自带的权限模型,从理论到实战演练,带领大家了解 Django 里权限是怎么一回事. 一.主要内容 1.什么是权限管理? 2.Web 权限 3.Django 权限机制 ...

  2. vmware一步步安装centos

    软件环境:vmware10.0破解版 centos版本:6.4 1.启动vmware,新建虚拟机,选择自定义安装 2,出现如下界面,保持默认,点击下一步 3.这个步骤要特别注意,选择“稍后安装”,我们 ...

  3. springboot 注册服务注册中心(zk)的两种方式

    在使用springboot进行开发的过程中,我们经常需要处理这样的场景:在服务启动的时候,需要向服务注册中心(例如zk)注册服务状态,以便当服务状态改变的时候,可以故障摘除和负载均衡. 我遇到过两种注 ...

  4. 我的Python学习笔记(三):私有变量

    一.私有变量的定义 在Python中,有以下几种方式来定义变量: xx:公有变量 _xx:单前置下划线,私有化属性或方法,类对象和子类可以访问,from somemodule import *禁止导入 ...

  5. tensorflow核心概念和原理介绍

    关于 TensorFlow TensorFlow 是一个采用数据流图(data flow graphs),用于数值计算的开源软件库. 节点(Nodes)在图中表示数学操作,图中的线(edges)则表示 ...

  6. 管理 MariaDB 用户账户

    哪些用户可以连接到MariaDB 服务器,他们都可以从哪些地方连接,连接到服务器后又能够做什么等,都是本文将涉及到的内容. 用户的权限信息都保存在 mysql 库中的几个权限表中.对 MariaDB ...

  7. Python 浅析线程(threading模块)和进程(process)

    线程是操作系统能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际运作单位.一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务 进程与线程 什么 ...

  8. mac 上安装服务,查看服务,重启和关闭

    首先了解下的Mac的 homebrew ,官网:https://brew.sh/index_zh-cn.html 简单的说: Homebrew 能干什么? 答:使用 Homebrew 安装 Apple ...

  9. 带新手走进神秘的HTTP协议

    在开发的时候经常需要访问网络,比如Android就有好多这方面的框架:Volley.OkHttp.Retrofit等,当你看这些框架源码时,可能会很好奇关于http的部分,它的首部字段是什么意思,ht ...

  10. C#学习笔记-基础知识篇(不定期更新)

    1.父类必须包含构造函数么? 父类必须要有一个构造函数,有参无参都可以. 构造函数是对象的基本,没有构造函数就没有对象,若父类中显示的有参数的构造函数,在子类继承就必须写一个构造函数来调用父类的构造函 ...