Summary: Merging the results directories of targets on buck projects involved creating symbolic links into buck-out. The bulk of files are .attr files: one per procedure. Creating these links can be a bottleneck, and the merge phase can be slower than the analysis phases on projects with many procedures. This diff introduces multilinks to speed up merge. A multilink is a file `multilink.txt` containing a sequence of paths ``` path/to/file1.ext path/to/file2.ext ... ``` A multilink file is a compact way to represent a link for each entry. This diff creates a multilink file for each `attributes/dir` directory, instead of one symbolic link for each file. Reviewed By: jberdine Differential Revision: D4067428 fbshipit-source-id: 911f8a9master
parent
a31658a9b8
commit
47c623ff51
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015 - present Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*/
|
||||||
|
open! Utils;
|
||||||
|
|
||||||
|
let module F = Format;
|
||||||
|
|
||||||
|
let module L = Logging;
|
||||||
|
|
||||||
|
let multilink_file_name = "multilink.txt";
|
||||||
|
|
||||||
|
type t = StringHash.t string;
|
||||||
|
|
||||||
|
let add multilinks fname => StringHash.replace multilinks (Filename.basename fname) fname;
|
||||||
|
|
||||||
|
let create () :t => StringHash.create 1;
|
||||||
|
|
||||||
|
/* Cache of multilinks files read from disk */
|
||||||
|
let multilink_files_cache = StringHash.create 1;
|
||||||
|
|
||||||
|
let reset_cache () => StringHash.reset multilink_files_cache;
|
||||||
|
|
||||||
|
let read dir::dir :option t => {
|
||||||
|
let multilink_fname = Filename.concat dir multilink_file_name;
|
||||||
|
switch (Utils.read_file multilink_fname) {
|
||||||
|
| None => None
|
||||||
|
| Some lines =>
|
||||||
|
let links = create ();
|
||||||
|
IList.iter (fun line => StringHash.add links (Filename.basename line) line) lines;
|
||||||
|
StringHash.add multilink_files_cache dir links;
|
||||||
|
Some links
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Write a multilink file in the given directory */
|
||||||
|
let write multilinks dir::dir => {
|
||||||
|
let fname = Filename.concat dir multilink_file_name;
|
||||||
|
let outc = open_out fname;
|
||||||
|
StringHash.iter (fun _ src => output_string outc (src ^ "\n")) multilinks;
|
||||||
|
close_out outc
|
||||||
|
};
|
||||||
|
|
||||||
|
let lookup dir::dir =>
|
||||||
|
try (Some (StringHash.find multilink_files_cache dir)) {
|
||||||
|
| Not_found => read dir::dir
|
||||||
|
};
|
||||||
|
|
||||||
|
let resolve fname => {
|
||||||
|
let fname_s = DB.filename_to_string fname;
|
||||||
|
if (Sys.file_exists fname_s) {
|
||||||
|
fname
|
||||||
|
} else {
|
||||||
|
let base = Filename.basename fname_s;
|
||||||
|
let dir = Filename.dirname fname_s;
|
||||||
|
switch (lookup dir::dir) {
|
||||||
|
| None => fname
|
||||||
|
| Some links =>
|
||||||
|
try (DB.filename_from_string (StringHash.find links base)) {
|
||||||
|
| Not_found => fname
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015 - present Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*/
|
||||||
|
open! Utils;
|
||||||
|
|
||||||
|
let module F = Format;
|
||||||
|
|
||||||
|
let module L = Logging;
|
||||||
|
|
||||||
|
|
||||||
|
/** In-memory representation of multilink files. */
|
||||||
|
type t;
|
||||||
|
|
||||||
|
|
||||||
|
/** Add a link. */
|
||||||
|
let add: t => string => unit;
|
||||||
|
|
||||||
|
|
||||||
|
/** Create a new multilink. */
|
||||||
|
let create: unit => t;
|
||||||
|
|
||||||
|
|
||||||
|
/** Name of the multilink file.
|
||||||
|
A multilink file is recognized by its file name. */
|
||||||
|
let multilink_file_name: string;
|
||||||
|
|
||||||
|
|
||||||
|
/** Read a multilink file from disk. */
|
||||||
|
let read: dir::string => option t;
|
||||||
|
|
||||||
|
|
||||||
|
/** Resolve a filename following multilinks.
|
||||||
|
The cache is updated if a new multilinks file is read. */
|
||||||
|
let resolve: DB.filename => DB.filename;
|
||||||
|
|
||||||
|
|
||||||
|
/** Reset the cache of multilink files */
|
||||||
|
let reset_cache: unit => unit;
|
||||||
|
|
||||||
|
|
||||||
|
/** Write a multilink file in the given directory */
|
||||||
|
let write: t => dir::string => unit;
|
Loading…
Reference in new issue