如何在phantomjs中实现快速,可查询和持久的数据库?

我一直在使用phantomjs在服务器端环境中为我做一些繁重的工作。 直到现在,我一直在内存中的数据结构(即没有做任何特别的事情),一切都很好。 但最近在一些使用情况下,我开始遇到以下问题:

  1. 内存使用率变得太高,使交换踢,严重影响我的performance。
  2. 由于内存中的数据结构不是永久的,所以不能从最后的保存点恢复(显然)

这迫使我寻找一个数据库解决scheme在幻像上使用,但我又遇到问题,而决定一个解决scheme:

  1. 我不想让自己的performance受到影响。
  2. 它必须是持久的和可查询的
  3. 我甚至如何连接到从幻影脚本里面的数据库。

谁能指导我一个令人满意的解决scheme?

注意:我几乎决定使用sqlite但是从幻影连接到它仍然是一个问题。 Nodejs提供了sqlite3节点模块,我正在尝试为幻影进行浏览。

Note注意: Browserify没有工作! 回到地面零! 🙁

感谢提前!

Phantomjs的文件系统API允许您读取和写入二进制文件:

 buf = fs.read(FILENAME, 'b') and fs.write(FILENAME, buf, 'b') 

sql.js( https://github.com/kripken/sql.js/ )为您提供了一个可以在phantomjs中运行的JavaScript SQLite实现。

结合2,你有一个快速,持久,可查询的SQL数据库。

示例演练

  1. 获取JavaScript SQLite实现(保存到/tmp/sql.js)

    $ wget https://raw.githubusercontent.com/kripken/sql.js/master/js/sql.js -O /tmp/sql.js

  2. 使用命令行sqlite3应用程序创build一个testingSQLite数据库(显示它是phantomjs应用程序的持久性和外部的)。

    sqlite3 /tmp/eg.db

    sqlite> CREATE TABLE IF NOT EXISTS test(id INTEGER PRIMARY KEY AUTOINCREMENT,created INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP);

    sqlite> .quit

  3. 保存此testingphantomjs脚本以将条目添加到testing数据库并validation行为。

$ cat /tmp/eg.js

 var fs = require('fs'), sqlite3 = require('./sql.js'), dbfile = '/tmp/eg.db', sql = 'INSERT INTO test(id) VALUES (NULL)', // fs.read returns binary 'string' (not 'String' or 'Uint8Array') read = fs.read(dbfile, 'b'), // Database argument must be a 'string' (binary) not 'Uint8Array' db = new sqlite3.Database(read), write, uint8array; try { db.run(sql); } catch (e) { console.error('ERROR: ' + e); phantom.exit(); } // db.export() returns 'Uint8Array' but we must pass binary 'string' to write uint8array = db.export(); write = String.fromCharCode.apply(null, Array.prototype.slice.apply(uint8array)); fs.write(dbfile, write, 'b'); db.close(); phantom.exit(); 
  1. 运行phantomjs脚本来testing

    $ /usr/local/phantomjs-2.0.0-macosx/bin/phantomjs /tmp/eg.js

  2. 使用外部工具来validation更改是否持续。

    sqlite3 /tmp/eg.db

    sqlite> SELECT * FROM test;

    编号创build

    1 2015-03-28 10:21:09

    sqlite的>

有些事情要记住:

  1. 数据库仅在调用fs.write时在磁盘上进行修改。 在调用fs.write之前,对外部程序访问相同的SQLite数据库文件所做的任何更改都是不可见的。
  2. 整个数据库用fs.read读入内存。 根据应用程序和表中的数据量,可能需要为不同的表或表版本提供不同的操作系统文件,以解决您提到的内存需求。
  3. 将sqlite3.export()返回的内容传递给fs.write会损坏磁盘上的SQLite数据库文件(它不再是有效的SQLite数据库文件)。 Uint8Array不是fs.write参数的正确types。

在phantomjs中编写一个二进制数据是这样工作的:

var db_file = fs.open(db_name, {mode: 'wb', charset: ''}); db_file.write(String.fromCharCode.apply(null, db.export())); db_file.close();

您必须将字符集设置为'' ,否则写入错误。