GVKun编程网logo

SQLite性能基准测试–为什么:memory:这么慢……只有磁盘速度的1.5倍?

12

如果您对SQLite性能基准测试–为什么:memory:这么慢……只有磁盘速度的1.5倍?感兴趣,那么这篇文章一定是您不可错过的。我们将详细讲解SQLite性能基准测试–为什么:memory:这么慢…

如果您对SQLite性能基准测试–为什么:memory:这么慢……只有磁盘速度的1.5倍?感兴趣,那么这篇文章一定是您不可错过的。我们将详细讲解SQLite性能基准测试–为什么:memory:这么慢……只有磁盘速度的1.5倍?的各种细节,此外还有关于c – 为什么boost :: circular_buffer在我的基准测试中这么慢?、C使用SQLite为什么这么慢?、Golang 函数测试中的性能基准测试、golang函数的性能基准测试详解的实用技巧。

本文目录一览:

SQLite性能基准测试–为什么:memory:这么慢……只有磁盘速度的1.5倍?

SQLite性能基准测试–为什么:memory:这么慢……只有磁盘速度的1.5倍?

为什么在sqlite中:memory:这么慢?

我一直在尝试查看通过使用内存中的sqlite与基于磁盘的sqlite是否可以获得任何性能改进。基本上,我想以启动时间和内存为代价来获得非常快速的查询,这些查询在应用程序运行期间
不会 对磁盘造成影响。

但是,以下基准测试只能使我提高速度1.5倍。在这里,我正在生成一百万行随机数据,并将其加载到同一表的基于磁盘和内存的版本中。然后,我在两个数据库上运行随机查询,返回大小约为300k的集合。我期望基于内存的版本会更快,但是如上所述,我的速度只有1.5倍。

我尝试了其他几种大小的数据库和查询集。内存:优势 似乎上升为行的分贝数增加了。我不确定为什么优势如此之小,尽管我有一些假设:

  • 所用的表不够大(成行),无法形成:memory:一个巨大的赢家
  • 更多的联接/表将使:memory:优势更加明显
  • 在连接或操作系统级别进行某种缓存,以便以某种方式可以访问以前的结果,从而破坏基准
  • 我没有看到某种隐藏的磁盘访问(我还没有尝试过lsof,但是我确实关闭了PRAGMA的日志功能)

我在这里做错什么了吗?为什么:memory:没有产生几乎即时的查询?这是基准:

==> sqlite_memory_vs_disk_benchmark.py <==#!/usr/bin/env python"""Attempt to see whether :memory: offers significant performance benefits."""import osimport timeimport sqlite3import numpy as npdef load_mat(conn,mat):    c = conn.cursor()    #Try to avoid hitting disk, trading safety for speed.    #http://stackoverflow.com/questions/304393    c.execute(''PRAGMA temp_store=MEMORY;'')    c.execute(''PRAGMA journal_mode=MEMORY;'')    # Make a demo table    c.execute(''create table if not exists demo (id1 int, id2 int, val real);'')    c.execute(''create index id1_index on demo (id1);'')    c.execute(''create index id2_index on demo (id2);'')    for row in mat:        c.execute(''insert into demo values(?,?,?);'', (row[0],row[1],row[2]))    conn.commit()def querytime(conn,query):    start = time.time()    foo = conn.execute(query).fetchall()    diff = time.time() - start    return diff#1) Build some fake data with 3 columns: int, int, floatnn   = 1000000 #numrowscmax = 700    #num uniques in 1st colgmax = 5000   #num uniques in 2nd colmat = np.zeros((nn,3),dtype=''object'')mat[:,0] = np.random.randint(0,cmax,nn)mat[:,1] = np.random.randint(0,gmax,nn)mat[:,2] = np.random.uniform(0,1,nn)#2) Load it into both dbs & build indicestry: os.unlink(''foo.sqlite'')except OSError: passconn_mem = sqlite3.connect(":memory:")conn_disk = sqlite3.connect(''foo.sqlite'')load_mat(conn_mem,mat)load_mat(conn_disk,mat)del mat#3) Execute a series of random queries and see how long it takes each of thesenumqs = 10numqrows = 300000 #max number of ids of each kindresults = np.zeros((numqs,3))for qq in range(numqs):    qsize = np.random.randint(1,numqrows,1)    id1a = np.sort(np.random.permutation(np.arange(cmax))[0:qsize]) #ensure uniqueness of ids queried    id2a = np.sort(np.random.permutation(np.arange(gmax))[0:qsize])    id1s = '',''.join([str(xx) for xx in id1a])    id2s = '',''.join([str(xx) for xx in id2a])    query = ''select * from demo where id1 in (%s) AND id2 in (%s);'' % (id1s,id2s)    results[qq,0] = round(querytime(conn_disk,query),4)    results[qq,1] = round(querytime(conn_mem,query),4)    results[qq,2] = int(qsize)#4) Now look at the resultsprint "  disk | memory | qsize"print "-----------------------"for row in results:    print "%.4f | %.4f | %d" % (row[0],row[1],row[2])

这是结果。请注意,对于相当大范围的查询大小,磁盘占用的内存大约是内存的1.5倍。

[ramanujan:~]$python -OO sqlite_memory_vs_disk_clean.py  disk | memory | qsize-----------------------9.0332 | 6.8100 | 126309.0905 | 6.6953 | 58949.0078 | 6.8384 | 177989.1179 | 6.7673 | 608509.0629 | 6.8355 | 948548.9688 | 6.8093 | 179409.0785 | 6.6993 | 580039.0309 | 6.8257 | 856639.1423 | 6.7411 | 660479.1814 | 6.9794 | 11345

RAM是否应该相对于磁盘而言几乎是即时的?这是怎么了

编辑

这里有一些好的建议。

我想对我来说,主要的收获是可能没有办法使:memory: 绝对更快 ,但是有一种方法可以使磁盘访问 相对较慢。

换句话说,基准测试足以衡量内存的实际性能,但不能衡量磁盘的实际性能(例如,因为cache_size编译指示太大或因为我没有写数据)。我会弄乱那些参数,并在有机会时发布我的发现。

就是说,如果有人认为我可以从内存数据库中挤出更多的速度(除了提高我将要做的cache_size和default_cache_size的能力),我全都…

答案1

小编典典

它与SQLite具有页面缓存的事实有关。根据文档,默认页面缓存为2000个1K页面或大约2Mb。由于这大约占您数据的75%到90%,因此这两个数字非常相似也就不足为奇了。我的猜测是,除了SQLite页面缓存外,其余数据仍在OS磁盘缓存中。如果让SQLite刷新页面缓存(和磁盘缓存),您将看到一些真正的显着差异。

c – 为什么boost :: circular_buffer在我的基准测试中这么慢?

c – 为什么boost :: circular_buffer在我的基准测试中这么慢?

阅读 rationale,boost :: circular_buffer看起来很有希望:

Suitability for real-time and performance critical applications.

Fast constant-time insertion and removal of elements from the front and back.

当我运行一个模拟我的用例的简单基准测试时,将其用作字节缓冲区:

>写一个更大的块
>读取较小的块直到空
>重复一遍

性能绝对糟糕,比我自己的hack和spsc_queue慢了超过4000x.

lin : 101  // 10240x
lock: 109  // 10240x
circ: 427  // 10x

请注意,circular的loopcount为10,其他的loopcount为10 * 1024.参见工作示例here.

我使用它是完全错误还是只是没有设计基本/ POD类型?

编辑:

采用提供的更改的基准测试并不能完全解决MSVC2015上的问题.还有100倍的因素.

lin : 69   // 10240x
lock: 79   // 10240x
circ: 9688 // 10240x

一次插入几个项目是如此之慢是有问题的.分配将在此特殊情况下起作用,因为缓冲区在插入之前已耗尽,但这不是一般解决方案.在恢复中,spsc_queue在所有前端获胜,其快速,可以在不耗尽的情况下使用,并且可以在多线程环境中使用(在单个生产者单个消费者场景中).

解决方法

首先,确保基准测试是合理的.如果您不使用计算结果,编译器会在您最不期望的时候将其作为死代码消除.

>你的循环删除看起来不是最理想的.请改用:

buffer.erase_begin(1024); // or indeed,use checked size see below

UPDATE

>第二件影响性能的事情 – 严重 – 是插入调用.在你的用例中,你可以使用assign,就像在竞争者中一样,被编译成mempcy或memmove.
>确保禁用调试(定义NDEBUG和/或BOOST_CB_disABLE_DEBUG)

这是我使用Nonius:http://paste.ubuntu.com/15222217/的重构基准

时钟分辨率:平均值为18.6412 ns(40960002次迭代)

benchmarking linear
collecting 100 samples,1 iterations each,in estimated 3.93727 s
mean: 39.0804 ms,lb 39.0567 ms,ub 39.1051 ms,ci 0.95
std dev: 124.19 μs,lb 111.153 μs,ub 141.079 μs,ci 0.95
found 0 outliers among 100 samples (0%)
variance is unaffected by outliers

benchmarking lockfree
collecting 100 samples,in estimated 4.78513 s
mean: 37.0188 ms,lb 37.0106 ms,ub 37.0277 ms,ci 0.95
std dev: 43.5788 μs,lb 37.3685 μs,ub 52.8458 μs,ci 0.95
found 3 outliers among 100 samples (3%)
variance is unaffected by outliers

benchmarking circular
collecting 100 samples,in estimated 9.78763 s
mean: 62.884 ms,lb 62.8657 ms,ub 62.9041 ms,ci 0.95
std dev: 98.0325 μs,lb 85.6543 μs,ub 119.395 μs,ci 0.95
found 1 outliers among 100 samples (1%)
variance is unaffected by outliers

互动结果:http://stackoverflow-sehe.s3.amazonaws.com/57c2bfea-3e9d-4503-8d23-3b88209fc3ce/stats.html

enter image description here

没有nonius:Live On Coliru

产量

lin : 101 (checksum: -1741910392)
lock: 89 (checksum: -1741910392)
circ: 102 (checksum: -1741910392)

C使用SQLite为什么这么慢?

C使用SQLite为什么这么慢?

高手指教!我在C中使用SQLite,插入100条记录就花了10s,咋的这么慢呢?使用SQLite的JDBC驱动,插入10000条记录用了不到1s。这是这是为什么啊!C使用SQLite的性能不应该低于Java啊!

请高手解决,万分感谢!

Golang 函数测试中的性能基准测试

Golang 函数测试中的性能基准测试

go 中的性能基准测试衡量函数效率,通过在以 benchmark 开头的函数中编写基准测试代码实现。testing.b 类型提供 resettimer()、stoptimer() 和 n 属性控制基准测试行为。例如,计算斐波那契数的函数基准测试表明执行 fib(30) 需要约 2,767,425 纳秒。优化基准测试代码以避免开销,多次运行以获得准确结果。

Golang 函数测试中的性能基准测试

Go 函数测试中的性能基准测试

性能基准测试是衡量函数效率的重要工具。在 Go 中,testing 包提供了针对函数执行时间的基准测试功能。

编写性能基准测试

立即学习“go语言免费学习笔记(深入)”;

编写一个性能基准测试需要创建一个以 Benchmark 开头的函数,后面跟上要测试的函数名:

func BenchmarkFib(b *testing.B) {
    // 基准测试代码
}
登录后复制

使用 testing.B

testing.B 类型提供以下方法来控制基准测试:

  • ResetTimer(): 重置计时器。
  • StopTimer(): 停止计时器并记录时间。
  • N: 执行基准测试的次数。

实战案例

让我们对一个计算斐波那契数的函数进行基准测试:

func Fib(n int) int {
    if n <= 1 {
        return n
    }
    return Fib(n-1) + Fib(n-2)
}

func BenchmarkFib(b *testing.B) {
    for i := 0; i < b.N; i++ {
        Fib(30)
    }
}
登录后复制

在终端中运行测试:

go test -bench=.
登录后复制

输出将如下所示:

BenchmarkFib  2767425 ns/op
登录后复制

这意味着用 30 作为参数执行 Fib 函数的基准测试需要大约 2,767,425 纳秒(2767 毫秒)。

提示

  • 使用 -benchmem 标志来测量基准测试的内存分配。
  • 优化基准测试代码以避免开销,例如创建不必要的变量。
  • 多次运行基准测试以获得更准确的结果。

以上就是Golang 函数测试中的性能基准测试的详细内容,更多请关注php中文网其它相关文章!

golang函数的性能基准测试详解

golang函数的性能基准测试详解

golang函数的性能基准测试详解

Go 函数的性能基准测试

基准测试是衡量函数或代码段性能的关键工具。它可以帮助识别瓶颈、优化代码并确保应用程序的可扩展性。Go 提供了一个内置的 testing 包,用于执行基准测试。

设置基准测试

为了设置一个基准测试,需要在 testing 包中创建一个 Benchmark 函数。该函数的命名规则为 Benchmark.

立即学习“go语言免费学习笔记(深入)”;

import (
    "testing"
)

func BenchmarkExample(b *testing.B) {
    // 基准测试代码
}
登录后复制

b 参数是一个 testing.B 类型的指针,它提供了用于运行基准测试的各种方法。

运行基准测试

要运行基准测试,可以在命令行中使用 go test 命令,并指定 -bench 标志。

go test -bench=.
登录后复制

这将运行所有以 Benchmark 开头的函数作为基准测试。

测量结果

testing 包会收集基准测试的各种统计信息,包括:

  • ns/op: 执行单个操作所需的时间(以纳秒为单位)。
  • B/op: 执行单个操作所需的操作数(以字节为单位)。
  • allocs/op: 执行单个操作分配的内存对象数量。

这些结果可以帮助分析和优化代码。

实战案例:比较字符串相等

考虑比较两个字符串相等的两种常见的 Go 方法:

// 使用 == 操作符
func equals1(a, b string) bool {
    return a == b
}

// 使用 strings.EqualFold 函数
func equals2(a, b string) bool {
    return strings.EqualFold(a, b)
}
登录后复制

为了比较它们的性能,可以编写一个基准测试函数:

func BenchmarkEquals(b *testing.B) {
    a := "example"
    b := "Example"

    for i := 0; i < b.N; i++ {
        equals1(a, b)
    }
    for i := 0; i < b.N; i++ {
        equals2(a, b)
    }
}
登录后复制

运行此基准测试将显示 equals1 明显快于 equals2。这是因为 == 操作符进行位比较,而 strings.EqualFold 还会执行大小写无关的字符串比较。

以上就是golang函数的性能基准测试详解的详细内容,更多请关注php中文网其它相关文章!

关于SQLite性能基准测试–为什么:memory:这么慢……只有磁盘速度的1.5倍?的介绍现已完结,谢谢您的耐心阅读,如果想了解更多关于c – 为什么boost :: circular_buffer在我的基准测试中这么慢?、C使用SQLite为什么这么慢?、Golang 函数测试中的性能基准测试、golang函数的性能基准测试详解的相关知识,请在本站寻找。

本文标签: