Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

in-memory database or 'backup to' seems to leak memory #307

Open
ksaurab opened this issue Dec 1, 2017 · 5 comments
Open

in-memory database or 'backup to' seems to leak memory #307

ksaurab opened this issue Dec 1, 2017 · 5 comments
Labels
bug Something isn't working help wanted Contributions are welcome

Comments

@ksaurab
Copy link

ksaurab commented Dec 1, 2017

We are trying to create a large SQLite in-memory database and once the DB is created we are dumping it to a file using 'backup to' comand. This is done as creating a large in-memory sqlite db is much faster.

Once the backup process is complete, sqlite connection and statement is closed. When we looked at the memory footprint, the off-heap memory shot by 10GB during in-memory db creation. Once all the resources are closed, reduction in off-heap memory was around 1.2GB. We are left in 8.8GB extra memory in off-heap area.

So, we suspect a memory leak either in in-memory database or 'backup to'.
Is there a specific way to release memory for in-memory sqlite db?

@xerial
Copy link
Owner

xerial commented Dec 1, 2017

Off-heap memory is out of control of JVM. So I think some allocated handler(s) inside JNI code is not released properly:
https://github.com/xerial/sqlite-jdbc/blob/master/src/main/java/org/sqlite/core/NativeDB.c#L1366

@xerial xerial added bug Something isn't working help wanted Contributions are welcome labels Dec 1, 2017
@trohwer
Copy link
Contributor

trohwer commented Jan 30, 2018

With the following program

import java.sql.*;

public class Test {
  public static void main(String[] args) throws Exception {
    Class.forName("org.sqlite.JDBC");
    String url= "jdbc:sqlite::memory:";
    Connection c= DriverManager.getConnection(url);
    Statement s= c.createStatement();
    s.execute("create table t (b);");
    String cnt= "with recursive cnt(x) as (select 1 union all select x+1 from cnt limit 1024) select x from cnt";
    s.execute("insert into t select zeroblob(1024*1024) from ("+cnt+");");
    System.out.println("alloc");
    Thread.sleep(20000);
    // s.execute("backup to '/dev/null'");
    s.execute("backup to 'x.sqlite'");
    c.close();
    System.out.println("dealloc");
    Thread.sleep(20000);
  }
}

I only see a possible leak (RSS size does not decrease after dealloc is printed) on a second run, when the file x.sqlite already exists. @ksaurab : Can you check, if you observe the leak when the backup file does not exist before initiating the backup?

@ppsanyal1
Copy link

ppsanyal1 commented May 22, 2018

we are doing the same thing using sqlcipher_export as below 👍

statement.execute("ATTACH DATABASE '" + path + fileName + "' AS encrypted KEY '" + password + "';");
statement.execute("SELECT sqlcipher_export('encrypted');");
statement.execute("DETACH DATABASE encrypted;");

maybe you should try this approach @ksaurab

@sjlombardo
Copy link
Contributor

@ppsanyal1 This is a good approach if using SQLCipher, but the sqlcipher_export function is not available in the standard SQLite library.

@hbobenicio
Copy link
Contributor

hbobenicio commented Feb 23, 2024

With the following program

import java.sql.*;

public class Test {
  public static void main(String[] args) throws Exception {
    Class.forName("org.sqlite.JDBC");
    String url= "jdbc:sqlite::memory:";
    Connection c= DriverManager.getConnection(url);
    Statement s= c.createStatement();
    s.execute("create table t (b);");
    String cnt= "with recursive cnt(x) as (select 1 union all select x+1 from cnt limit 1024) select x from cnt";
    s.execute("insert into t select zeroblob(1024*1024) from ("+cnt+");");
    System.out.println("alloc");
    Thread.sleep(20000);
    // s.execute("backup to '/dev/null'");
    s.execute("backup to 'x.sqlite'");
    c.close();
    System.out.println("dealloc");
    Thread.sleep(20000);
  }
}

I only see a possible leak (RSS size does not decrease after dealloc is printed) on a second run, when the file x.sqlite already exists. @ksaurab : Can you check, if you observe the leak when the backup file does not exist before initiating the backup?

don't forget to close the Connection and the Statement otherwise leaks may naturally happen. They both are AutoClosable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working help wanted Contributions are welcome
Projects
None yet
Development

No branches or pull requests

6 participants