Skip to content

Commit

Permalink
Break up generated Rust code into three crates.
Browse files Browse the repository at this point in the history
This patch continues the effort to speed up re-compilation of DDlog
programs.  A recent commit enabled incremental Rust compilation,
which in theory means that the compiler should be able to intelligently
re-compile only parts of the program that changed.  While incremental
compilation does have some clear benefits, it is quite fragile with
small changes (e.g., adding an empty line can trigger a long
re-compilation).

To improve things further, we take advantage of the fact that with
incremental compilation Rust performs LTO at the granularity of a
crate; thus by splitting the code into several crates we can more
reliably contain the effect of each change on compilation time to the
crate(s) that changed.

Concretely, we break the generated code up into three crates:

* 'types' crate containing DDlog type declarations and all imported Rust
  library code.
* 'value' crate that declares relations and value types.
* 'main' crate that contains rule definitions in Rust and imports the
  other two crates.

Some results using the `ovn-northd-ddlog` test case:
- Complete recompilation from scratch:                   10m 21s
- Remove a rule and recompile:                            0m 36s
- Add a rule and recompile:                               0m 37s
- Add a new relation (and no rules):                      5m 53s
- Add a rule for the new relation:                        0m 38s
- Modify a function                                       0m 46s
  • Loading branch information
ryzhyk committed Feb 14, 2020
1 parent c755492 commit 7dad9d5
Show file tree
Hide file tree
Showing 19 changed files with 583 additions and 371 deletions.
16 changes: 8 additions & 8 deletions lib/intern.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ use serde;
use std::collections;
use std::marker;
use std::sync;
use std::thread;
use std::vec;

/* FlatBuffers bindings generated by `ddlog` */
#[cfg(feature = "flatbuf")]
use flatbuf::{
FBIter, FromFlatBuffer, ToFlatBuffer, ToFlatBufferTable, ToFlatBufferVectorElement, __String,
};
use flatbuf::{FromFlatBuffer, ToFlatBuffer, ToFlatBufferTable, ToFlatBufferVectorElement};

/* `flatc`-generated declarations re-exported by `flatbuf.rs` */
#[cfg(feature = "flatbuf")]
use flatbuf::fb;

/* FlatBuffers runtime */
#[cfg(feature = "flatbuf")]
Expand Down Expand Up @@ -151,15 +151,15 @@ impl<'b> ToFlatBuffer<'b> for intern_IString {
}

#[cfg(feature = "flatbuf")]
impl<'a> FromFlatBuffer<__String<'a>> for intern_IString {
fn from_flatbuf(v: __String<'a>) -> Response<Self> {
impl<'a> FromFlatBuffer<fb::__String<'a>> for intern_IString {
fn from_flatbuf(v: fb::__String<'a>) -> Response<Self> {
Ok(intern_string_intern(&String::from_flatbuf(v)?))
}
}

#[cfg(feature = "flatbuf")]
impl<'b> ToFlatBufferTable<'b> for intern_IString {
type Target = __String<'b>;
type Target = fb::__String<'b>;
fn to_flatbuf_table(
&self,
fbb: &mut fbrt::FlatBufferBuilder<'b>,
Expand Down
2 changes: 0 additions & 2 deletions lib/std.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,12 @@ use std::fmt::Display;
use std::hash::Hash;
use std::hash::Hasher;
use std::iter::FromIterator;
use std::marker;
use std::ops;
use std::slice;
use std::vec;
use std::vec::Vec;
use twox_hash::XxHash;

/* FlatBuffers bindings generated by `ddlog` */
#[cfg(feature = "flatbuf")]
use flatbuf::{FBIter, FromFlatBuffer, ToFlatBuffer, ToFlatBufferTable, ToFlatBufferVectorElement};

Expand Down
16 changes: 9 additions & 7 deletions rust/template/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ members = [
"differential_datalog",
"distributed_datalog",
"ovsdb",
"types",
"value"
]

[build-dependencies]
Expand All @@ -25,6 +27,12 @@ path = "./cmd_parser"
[dependencies.ddlog_ovsdb_adapter]
path = "./ovsdb"

[dependencies.types]
path = "./types"

[dependencies.value]
path = "./value"

[dependencies]
abomonation = "0.7"
cpuprofiler = {version = "0.0", optional = true}
Expand All @@ -38,16 +46,10 @@ serde = {version = "1.0", features = ["derive"]}
time = "0.1"
timely = "0.11"
twox-hash = "1.1"
typetag = "0.1"

# FlatBuffers dependency enabled by the `flatbuf` feature.
# flatbuffers crate version must be in sync with the flatc compiler and Java
# libraries: flatbuffers "0.6" <-> FlatBuffers "1.11.0".
flatbuffers = {version = "0.6", optional = true}

[features]
default = []
flatbuf = ["flatbuffers", "differential_datalog/flatbuf"]
flatbuf = ["differential_datalog/flatbuf", "types/flatbuf", "value/flatbuf"]
profile = ["cpuprofiler"]

[profile.release]
Expand Down
11 changes: 5 additions & 6 deletions rust/template/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ use std::ptr;
use std::slice;
use std::sync::{Arc, Mutex};

use libc::size_t;

use differential_datalog::ddval::*;
use differential_datalog::program::*;
use differential_datalog::record;
Expand All @@ -28,10 +26,10 @@ use super::*;

/* FlatBuffers bindings generated by `ddlog` */
#[cfg(feature = "flatbuf")]
use flatbuf;
use value::flatbuf;

#[cfg(feature = "flatbuf")]
use flatbuf::FromFlatBuffer;
use types::flatbuf::FromFlatBuffer;

// TODO: Move HDDlog into the differential_datalog crate.
#[derive(Debug)]
Expand Down Expand Up @@ -252,8 +250,9 @@ impl DDlog for HDDlog {
#[cfg(feature = "flatbuf")]
fn apply_updates_from_flatbuf(&self, buf: &[u8]) -> Result<(), String> {
let cmditer = flatbuf::updates_from_flatbuf(buf)?;
let upds: Result<Vec<Update<DDValue>>, String> =
cmditer.map(|cmd| Update::from_flatbuf(cmd)).collect();
let upds: Result<Vec<Update<DDValue>>, String> = cmditer
.map(|cmd| flatbuf::DDValueUpdate::from_flatbuf(cmd).map(|x| x.0))
.collect();
self.apply_valupdates(upds?.into_iter())
}

Expand Down
178 changes: 5 additions & 173 deletions rust/template/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,9 @@
clippy::missing_safety_doc
)]

use std::borrow;
use std::boxed;
use std::convert::TryFrom;
use std::ffi;
use std::fmt;
use std::fs;
use std::hash::Hash;
use std::hash::Hasher;
use std::io::Write;
use std::mem;
use std::ops::Deref;
use std::os::raw;
use std::os::unix;
use std::os::unix::io::{FromRawFd, IntoRawFd};
use std::os::unix::io::IntoRawFd;
use std::ptr;
use std::result;
use std::sync;
Expand All @@ -36,65 +25,26 @@ use timely::communication;
use timely::dataflow::scopes;
use timely::worker;

use serde::Deserialize;
use serde::Serialize;

use differential_datalog::arcval;

use differential_datalog::ddval::*;
use differential_datalog::decl_ddval_convert;
use differential_datalog::decl_enum_into_record;
use differential_datalog::decl_record_mutator_enum;
use differential_datalog::decl_record_mutator_struct;
use differential_datalog::decl_record_mutator_val_enum;
use differential_datalog::decl_struct_into_record;
use differential_datalog::decl_val_enum_into_record;
use differential_datalog::int::*;
use differential_datalog::program::*;
use differential_datalog::record;
use differential_datalog::record::FromRecord;
use differential_datalog::record::IntoRecord;
use differential_datalog::record::RelIdentifier;
use differential_datalog::record::UpdCmd;
use differential_datalog::uint::*;
use differential_datalog::DDlogConvert;

use fnv::{FnvHashMap, FnvHashSet};
use lazy_static::lazy_static;
use libc::size_t;
use fnv::FnvHashMap;
use num_traits::identities::One;

use crate::api::updcmd2upd;
use types::*;
pub use value::*;

pub mod api;
pub mod log;
pub mod ovsdb;
pub mod update_handler;

use log::*;

/* FlatBuffers bindings generated by `ddlog` */
#[cfg(feature = "flatbuf")]
pub mod flatbuf;

/* FlatBuffers code generated by `flatc` */
#[cfg(feature = "flatbuf")]
pub mod flatbuf_generated;

pub trait Val: Eq + Ord + Clone + Hash + PartialEq + PartialOrd {}

impl<T> Val for T where T: Eq + Ord + Clone + Hash + PartialEq + PartialOrd {}

pub fn string_append_str(mut s1: String, s2: &str) -> String {
s1.push_str(s2);
s1
}

#[allow(clippy::ptr_arg)]
pub fn string_append(mut s1: String, s2: &String) -> String {
s1.push_str(s2.as_str());
s1
}
use crate::api::updcmd2upd;

/// A default implementation of `DDlogConvert` that just forwards calls
/// to generated functions of equal name.
Expand All @@ -115,129 +65,11 @@ impl DDlogConvert for DDlogConverter {
}
}

impl TryFrom<&RelIdentifier> for Relations {
type Error = ();

fn try_from(rel_id: &RelIdentifier) -> result::Result<Self, Self::Error> {
match rel_id {
RelIdentifier::RelName(rname) => Relations::try_from(rname.as_ref()),
RelIdentifier::RelId(id) => Relations::try_from(*id),
}
}
}

/*- !!!!!!!!!!!!!!!!!!!! -*/
// Don't edit this line
// Code below this point is needed to test-compile template
// code and is not part of the template.

#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum Relations {
X = 0,
}

#[allow(clippy::trivially_copy_pass_by_ref)]
impl Relations {
pub fn is_input(&self) -> bool {
panic!("Relations::is_input not implemented")
}

pub fn is_output(&self) -> bool {
panic!("Relations::is_output not implemented")
}
}

impl TryFrom<&str> for Relations {
type Error = ();

fn try_from(rname: &str) -> result::Result<Self, Self::Error> {
panic!("Relations::try_from::<&str> not implemented")
}
}

impl TryFrom<RelId> for Relations {
type Error = ();

fn try_from(rid: RelId) -> result::Result<Self, Self::Error> {
panic!("Relations::try_from::<RelId> not implemented")
}
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum Indexes {
X = 0,
}

impl TryFrom<&str> for Indexes {
type Error = ();

fn try_from(_iname: &str) -> result::Result<Self, Self::Error> {
panic!("Indexes::try_from::<&str> not implemented")
}
}

impl TryFrom<IdxId> for Indexes {
type Error = ();

fn try_from(_iid: IdxId) -> result::Result<Self, Self::Error> {
panic!("Indexes::try_from::<IdxId> not implemented")
}
}

pub fn relval_from_record(
_rel: Relations,
_rec: &record::Record,
) -> result::Result<DDValue, String> {
panic!("relval_from_record not implemented")
}

pub fn relkey_from_record(
_rel: Relations,
_rec: &record::Record,
) -> result::Result<DDValue, String> {
panic!("relkey_from_record not implemented")
}

pub fn idxkey_from_record(idx: Indexes, _rec: &record::Record) -> result::Result<DDValue, String> {
panic!("idxkey_from_record not implemented")
}

pub fn relid2name(_rid: RelId) -> Option<&'static str> {
panic!("relid2name not implemented")
}

pub fn relid2cname(_rid: RelId) -> Option<&'static ffi::CStr> {
panic!("relid2cname not implemented")
}

lazy_static! {
pub static ref RELIDMAP: FnvHashMap<Relations, &'static str> = { FnvHashMap::default() };
}

lazy_static! {
pub static ref INPUT_RELIDMAP: FnvHashMap<Relations, &'static str> = { FnvHashMap::default() };
}

lazy_static! {
pub static ref OUTPUT_RELIDMAP: FnvHashMap<Relations, &'static str> = { FnvHashMap::default() };
}

pub fn indexid2name(_iid: IdxId) -> Option<&'static str> {
panic!("indexid2name not implemented")
}

pub fn indexid2cname(_iid: IdxId) -> Option<&'static ffi::CStr> {
panic!("indexid2cname not implemented")
}

pub fn indexes2arrid(idx: Indexes) -> ArrId {
panic!("indexes2arrid not implemented")
}

pub fn prog(__update_cb: Box<dyn CBFn>) -> Program {
panic!("prog not implemented")
}

lazy_static! {
pub static ref IDXIDMAP: FnvHashMap<Indexes, &'static str> = { FnvHashMap::default() };
}
3 changes: 2 additions & 1 deletion rust/template/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use differential_datalog::DDlog;
use num_traits::cast::ToPrimitive;
use rustop::opts;
use time::precise_time_ns;
use types::log_set_default_callback;

#[cfg(feature = "profile")]
use cpuprofiler::PROFILER;
Expand All @@ -42,7 +43,7 @@ fn handle_cmd(
.and(match cmd {
Command::Start => hddlog.transaction_start(),
Command::LogLevel(level) => {
log::log_set_default_callback(
log_set_default_callback(
Some(Box::new(move |level, msg| {
println!("LOG ({}): {}", level, msg);
})),
Expand Down
2 changes: 0 additions & 2 deletions rust/template/src/ovsdb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

use std::convert::TryFrom;
use std::ffi::{CStr, CString};
use std::io::Write;
use std::os::raw::{c_char, c_int};
use std::sync;

Expand All @@ -12,7 +11,6 @@ use differential_datalog::program::*;
use differential_datalog::record::{IntoRecord, UpdCmd};
use differential_datalog::record_upd_cmds;
use differential_datalog::DeltaMap;
use differential_datalog::RecordReplay;

use crate::api::{updcmd2upd, HDDlog};
use crate::DDlogConverter;
Expand Down
1 change: 0 additions & 1 deletion rust/template/src/update_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ use std::sync::mpsc::*;
use std::sync::{Arc, Barrier, Mutex, MutexGuard};
use std::thread::*;

use differential_datalog::ddval::*;
use differential_datalog::Callback;
use differential_datalog::DeltaMap;

Expand Down

0 comments on commit 7dad9d5

Please sign in to comment.