Skip to content

Commit

Permalink
feat(wip)!: Creational Flyweights to reduce the memory usage footprin…
Browse files Browse the repository at this point in the history
…t and common Argument(s) that only need to be created once
  • Loading branch information
TheRustifyer committed Jun 21, 2024
1 parent 226099c commit aac336b
Show file tree
Hide file tree
Showing 11 changed files with 300 additions and 105 deletions.
47 changes: 47 additions & 0 deletions zork++/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions zork++/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ path = "src/bin/main.rs"
toml = "0.5.11"
glob = "0.3.1"
serde = { version = "1.0.202", features = ["derive"] }
typetag = "0.2"
clap = { version = "4.0.32", features = ["derive"] }
log = "0.4.17"
env_logger = "0.11.3"
Expand Down
9 changes: 6 additions & 3 deletions zork++/src/lib/cache/compile_commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ pub type CompileCommands = Vec<CompileCommand>;
/// Generates the `compile_commands.json` file, that acts as a compilation database
/// for some static analysis external tools, like `clang-tidy`, and populates it with
/// the generated commands for the translation units
pub(crate) fn map_generated_commands_to_compilation_db(cache: &ZorkCache) -> Result<CompileCommands> {
pub(crate) fn map_generated_commands_to_compilation_db(
cache: &ZorkCache,
) -> Result<CompileCommands> {
log::trace!("Generating the compilation database...");

let generated_commands = cache.get_all_commands_iter();
let mut compilation_db_entries: Vec<CompileCommand> =
Vec::with_capacity(cache.count_total_generated_commands());
Expand All @@ -30,9 +32,10 @@ pub(crate) fn map_generated_commands_to_compilation_db(cache: &ZorkCache) -> Res
File::create(compile_commands_path)
.with_context(|| "Error creating the compilation database")?;
}

utils::fs::serialize_object_to_file(Path::new(compile_commands_path), &compilation_db_entries)
.with_context(move || "Error saving the compilation database")?;

Ok(compilation_db_entries)
}

Expand Down
64 changes: 42 additions & 22 deletions zork++/src/lib/cache/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ use std::{
path::{Path, PathBuf},
};

use crate::bounds::TranslationUnit;
use crate::cache::compile_commands::CompileCommands;
use crate::project_model::modules::{ModuleImplementationModel, ModuleInterfaceModel};
use crate::project_model::sourceset::SourceFile;
use crate::{
cli::{
Expand All @@ -27,9 +30,6 @@ use crate::{
};
use serde::{Deserialize, Serialize};
use walkdir::WalkDir;
use crate::bounds::TranslationUnit;
use crate::cache::compile_commands::CompileCommands;
use crate::project_model::modules::{ModuleImplementationModel, ModuleInterfaceModel};

/// Standalone utility for load from the file system the Zork++ cache file
/// for the target [`CppCompiler`]
Expand Down Expand Up @@ -87,7 +87,7 @@ pub fn save(
.with_context(move || "Error saving data to the Zork++ cache")
}

#[derive(Serialize, Deserialize, Debug, Default, Clone)]
#[derive(Serialize, Deserialize, Default)]
pub struct ZorkCache {
pub compiler: CppCompiler,
pub last_program_execution: DateTime<Utc>,
Expand All @@ -96,27 +96,43 @@ pub struct ZorkCache {
}

impl ZorkCache {
pub fn new() -> Self {
Self {
compiler: todo!(),
last_program_execution: todo!(),
compilers_metadata: todo!(),
generated_commands: todo!(),
}
}
pub fn last_program_execution(&self) -> &DateTime<Utc> {
&self.last_program_execution
}
pub fn get_module_ifc_cmd(&self, module_interface_model: &ModuleInterfaceModel) -> Option<&SourceCommandLine>{
self.generated_commands.interfaces.iter().find(|mi|
module_interface_model.file() == (*mi).path()
)
pub fn get_module_ifc_cmd(
&self,
module_interface_model: &ModuleInterfaceModel,
) -> Option<&SourceCommandLine> {
self.generated_commands
.interfaces
.iter()
.find(|mi| module_interface_model.file() == (*mi).path())
}

pub fn get_module_impl_cmd(&self, module_impl_model: &ModuleImplementationModel) -> Option<&SourceCommandLine>{
self.generated_commands.implementations.iter().find(|mi|
module_impl_model.file() == (*mi).path()
)
pub fn get_module_impl_cmd(
&self,
module_impl_model: &ModuleImplementationModel,
) -> Option<&SourceCommandLine> {
self.generated_commands
.implementations
.iter()
.find(|mi| module_impl_model.file() == (*mi).path())
}

// pub fn get_source_cmd(&self, module_impl_model: &Source) -> Option<&SourceCommandLine>{
// self.generated_commands.implementations.iter().find(|mi|
// module_impl_model.file() == (*mi).path()
// )
// }

/// Returns a [`Option`] of [`CommandDetails`] if the file is persisted already in the cache
pub fn is_file_cached(&self, _path: impl AsRef<Path>) -> Option<&CommandDetail> {
// let last_iteration_details = self.generated_commands.last();
Expand Down Expand Up @@ -161,9 +177,11 @@ impl ZorkCache {
// {
// compile_commands::map_generated_commands_to_compilation_db(self)?;
// }
//
if let Some(_new_commands) = self.save_generated_commands(commands, program_data, test_mode) {
if program_data.project.compilation_db { // TODO:: pass the new commands
//
if let Some(_new_commands) = self.save_generated_commands(commands, program_data, test_mode)
{
if program_data.project.compilation_db {
// TODO:: pass the new commands
compile_commands::map_generated_commands_to_compilation_db(self)?;
}
}
Expand Down Expand Up @@ -199,10 +217,10 @@ impl ZorkCache {
// } else {
// 1
// };

// Generating the compilation database if enabled, and some file has been added, modified
// or comes from a previous failure status

// TODO: oh, fk, I get it finally. We should only regenerate the compilation database if
// the generated command line has changed! (which is highly unlikely)
// TODO: Create a wrapper enumerated over the Vec<Command>, so that we can store in the
Expand All @@ -213,9 +231,11 @@ impl ZorkCache {
// let at_least_one_changed = commands.
self.generated_commands = commands;

self.get_all_commands_iter()// TODO: Review the conditions and ensure that are the ones that we're looking for
.any(|cmd| cmd.need_to_build || cmd.execution_result.eq(&CommandExecutionResult::Success));

self.get_all_commands_iter() // TODO: Review the conditions and ensure that are the ones that we're looking for
.any(|cmd| {
cmd.need_to_build || cmd.execution_result.eq(&CommandExecutionResult::Success)
});

// INSTEAD OF THIS, we just can return an Optional with the compilation database, so we can serialize the args in the compile_commands.json
// format and then join them in a one-liner string, so they're easy to read and/or copy
None
Expand Down Expand Up @@ -260,7 +280,7 @@ impl ZorkCache {
// TODO: read_only_iterator (better name) and docs pls
pub fn get_all_commands_iter(&self) -> impl Iterator<Item = &SourceCommandLine> + Debug + '_ {
let generated_commands = &self.generated_commands;

generated_commands
.pre_tasks
.iter()
Expand Down
4 changes: 2 additions & 2 deletions zork++/src/lib/cli/output/arguments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use std::{borrow::Borrow, ffi::OsStr, path::PathBuf};
use serde::{Deserialize, Serialize};

/// Wrapper type for represent and storing a command line argument
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Argument(String);

impl Argument {
Expand Down Expand Up @@ -144,7 +144,7 @@ pub mod clang_args {
// The Windows variant is a Zork++ feature to allow the users to write `import std;`
// under -std=c++20 with clang linking against GCC with
// some MinGW installation or similar
pub(crate) fn implicit_module_maps(out_dir: &Path) -> Argument {
pub(crate) fn implicit_module_map(out_dir: &Path) -> Argument {
if std::env::consts::OS.eq("windows") {
Argument::from(format!(
"-fmodule-map-file={}",
Expand Down
29 changes: 19 additions & 10 deletions zork++/src/lib/cli/output/commands.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
//! Contains helpers and data structures to be processed in a nice and neat way the commands generated to be executed
//! by Zork++

use std::collections::HashMap;
use std::fmt::Debug;
use std::slice::Iter;
Expand All @@ -8,9 +11,7 @@ use std::{

use crate::bounds::TranslationUnit;
use crate::cli::output::arguments::Arguments;
/// Contains helpers and data structure to process in
/// a nice and neat way the commands generated to be executed
/// by Zork++
use crate::compiler::data_factory::{CommonArgs, CompilerCommonArguments};
use crate::{
cache::{self, ZorkCache},
project_model::{compiler::CppCompiler, ZorkModel},
Expand Down Expand Up @@ -175,9 +176,9 @@ impl SourceCommandLine {
}

pub fn for_translation_unit(
// TODO init it as a args holder, but doesn't have the status yet
tu: impl TranslationUnit,
args: Arguments
// TODO init it as a args holder, but doesn't have the status yet
tu: impl TranslationUnit,
args: Arguments,
) -> Self {
Self {
directory: tu.path(),
Expand Down Expand Up @@ -216,24 +217,32 @@ impl LinkerCommandLine {
}

/// Holds the generated command line arguments for a concrete compiler
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[derive(Serialize, Deserialize, Default)]
pub struct Commands {
pub compiler: CppCompiler,
pub pre_tasks: Vec<SourceCommandLine>, // TODO: since there's no really pre-tasks (only build the std_lib), create named entries for std and std.compat
pub system_modules: HashMap<String, Arguments>,

pub general_args: CommonArgs,
pub compiler_common_args: Box<dyn CompilerCommonArguments>,

pub interfaces: Vec<SourceCommandLine>,
pub implementations: Vec<SourceCommandLine>,
pub sources: Vec<SourceCommandLine>,
pub linker: LinkerCommandLine,
}

Check failure on line 233 in zork++/src/lib/cli/output/commands.rs

View workflow job for this annotation

GitHub Actions / Verify code formatting

Diff in /home/runner/work/Zork/Zork/zork++/src/lib/cli/output/commands.rs

impl Commands {
pub fn new(compiler: CppCompiler) -> Self {
pub fn new(model: &ZorkModel<'_>, general_args: CommonArgs, compiler_specific_common_args: Box<dyn CompilerCommonArguments>) -> Self {
Self {
// TODO: try to see if its possible to move around the code and have a From<T>, avoiding default initialization,
// since this will always cause reallocations, and from may be able to allocate at the exact required capacity
// since this will always cause reallocations, and 'from' may be able to allocate at the exact required capacity
// of every collection
compiler,
compiler: model.compiler.cpp_compiler,

general_args,
compiler_common_args: compiler_specific_common_args,

pre_tasks: Vec::with_capacity(0),
system_modules: HashMap::with_capacity(0),
interfaces: Vec::with_capacity(0),
Expand Down
Empty file.
Loading

0 comments on commit aac336b

Please sign in to comment.