-
Optimal Trace Reduction for LRU-based Simulations
LRU is a well-known buffer management policy under which an element
buffer of size k always stores the k most recently used elements. Many
variants of the policy are widely used in memory systems (e.g., virtual
memory subsystems). We study a simple-to-state algorithmic problem called
the LRU trace reduction problem: for a sequence of references to elements
(a reference trace), compute the shortest sequence with identical LRU behavior
for buffers of at least a given size. Despite the straightforward statement
of the problem, its solution is non-trivial. We offer an efficient algorithm
with important practical applications in performance analysis.
-
Trace Reduction for Virtual Memory Simulations
The unmanageably large size of reference traces has spurred the development
of sophisticated trace reduction techniques. In this paper we present
two new algorithms for trace reduction-Safely Allowed Drop (SAD) and Optimal
LRU Reduction (OLR). Both achieve high reduction factors and guarantee
exact simulations for common replacement policies and for memories larger
than a user-defined threshold. In particular, simulation on OLR-reduced
traces is accurate for the LRU replacement algorithm, while simulation
on SAD-reduced traces is accurate for the LRU and OPT algorithms. OLR also
satisfies an optimality property: for a given trace and memory size it
produces the shortest possible trace that has the same LRU behavior as
the original for a memory of at least this size.
Our approach has multiple applications, especially in simulating virtual
memory systems; many page replacement algorithms are similar to LRU in
that more recently referenced pages are likely to be resident. For several
replacement algorithms in the literature, SAD-and OLR-reduced traces yield
exact simulations. For many other algorithms, our trace reduction eliminates
information that matters little: we present extensive measurements to show
that the error for simulations of the CLOCK and SEGQ (segmented queue)
replacement policies (the most common LRU approximations) is under 3% for
the majority of memory sizes. In nearly all cases, the error
is much smaller than that incurred by the well known stack deletion technique.
SAD and OLR have many desirable properties. In practice, they achieve
reduction factors up to several orders of magnitude. The reduction translates
to both storage savings and simulation speedups. Both techniques require
little memory and perform a single forward traversal of the original trace,
which makes them suitable for on-line trace reduction. Neither requires
that the simulator be modified to accept the reduced trace.
-
EELRU: Simple and Effective Adaptive Page Replacement
Despite the many replacement algorithms proposed throughout the years,
approximations of Least Recently Used (LRU) replacement are predominant
in actual virtual memory management systems because of their simplicity
and efficiency. LRU, however, exhibits well-known performance problems
for regular access patterns over more pages than the main memory can hold
(e.g., large loops). In this paper we present Early Eviction LRU
(EELRU). EELRU is a simple adaptive replacement algorithm, which
uses only the kind of information needed by LRU-how recently each page
has been touched relative to the
others. It exploits this information more effectively than LRU,
using a simple on-line cost/benefit analysis to guide its replacement decisions.
In the very common situations where LRU is good, EELRU is good because
it behaves like LRU. In common worst cases for LRU, EELRU is significantly
better, and in fact close to optimal as it opts to sacrifice some pages
to allow others to stay in memory longer. Overall, in its worst case, EELRU
cannot be more than a constant factor worse than LRU, while LRU can be
worse than EELRU by a factor almost equal to the number of pages in memory.
In simulation experiments with a variety of programs and wide ranges
of memory sizes, we show that EELRU does in fact outperform LRU, typically
reducing misses by ten to thirty percent, and occasionally by much more-sometimes
by a factor of two to ten. It rarely performs worse than LRU, and
then only by a small amount.
Overall, EELRU demonstrates several principles which could be widely
useful for adaptive page replacement algorithms: (1) it adapts to changes
in program behavior, distinguishing important behavior characteristics
for each workload. In particular, EELRU is not affected by high-frequency
behavior (e.g., loops much smaller than the memory size) as such behavior
may obscure important large-scale regularities; (2) EELRU chooses pages
to evict in a way that respects both the memory size and the aggregate
memory-referencing behavior of the program; (3) depending on the aggregate
memory-referencing behavior, EELRU can be ``fair'' (like LRU) or ``unfair'',
selectively allowing some pages to stay in memory longer while others are
evicted.
-
Architectural Styles as Adaptors
The essence of architectural styles is component communication. In
this paper, we relate architectural styles to adaptors in the GenVoca model
of software construction. GenVoca components are refinements that have
a wide range of implementations, from binaries to rule-sets of program
transformation systems. We explain that architectural styles can (1) be
understood as refinements (like other GenVoca components) and (2) that
they are generalizations of the OO concept of adaptors. By implementing
adaptors as program transformations, complex architectural styles can be
realized in GenVoca that simply could not be expressed using less powerful
implementation techniques (e.g., object adaptors). Examples from avionics
are given.
-
Implementing Layered Designs with Mixin Layers
Mixin layers are a technique for implementing layered object-oriented
designs (e.g., collaboration-based designs). Mixin layers are similar to
abstract subclasses (mixin classes) but scaled to a multiple-class granularity.
We describe mixin layers from a programming language viewpoint, discuss
checking the consistency of a mixin layer composition, and analyze the
language support issues involved.
-
JTS: Tools for Implementing Domain-Specific Languages
The Jakarta Tool Suite (JTS) aims to reduce substantially the cost
of generator development by providing domain-independent tools for creating
domain-specific languages and component-based generators called GenVoca
generators. JTS is a set of precompiler-compiler tools for extending industrial
programming languages (e.g., Java) with domain-specific constructs. JTS
is itself a GenVoca generator, where precompilers for JTS-extended languages
are constructed from components.
-
Implementing Reusable Object-Oriented Components
Object-Oriented (OO) classes are generally not reusable because they
are not meaningful in isolation; most classes only have meaning as members
of cooperating suites of classes (e.g., design patterns). These suites
usually arise in designs, but rarely exist as encapsulated entities in
OO implementations. In this paper we present a method for directly mapping
cooperating suites of classes into encapsulated C++ implementations. Our
method is an improvement over the VanHilst and Notkin approach for implementing
collaboration-based designs and constitutes a step towards more reusable
(object-oriented) components.
-
DiSTiL: a Transformation Library for Data Structures
DiSTiL is a software generator that implements a declarative domain-specific
language (DSL) for container data structures. DiSTiL is a representative
of a new approach to domain-specific language implementation. Instead of
being the usual one-of-a-kind stand-alone compiler, DiSTiL is an extension
library for the Intentional Programming (IP) transformation system (currently
under development by Microsoft Research). DiSTiL relies on several reusable,
general-purpose infrastructure tools offered by IP that substantially simplify
DSL implementation.
-
Scoping Constructs for Program Generators
Program generation is the process of generating code in a high-level
language (e.g., C, C++, Java) to implement an abstract specification of
a program. Generated programs are created by synthesizing and composing
code fragments. Binding identifiers in generated code with their correct
variable declarations has been the focus of a lot of research work in the
context of macro-expansion (e.g., hygienic macro expansion and syntactic
closures mechanisms). The common solutions include automatically maintaining
identifier environments, which determine the legal bindings for an identifier.
In this paper we present generation scoping: an adaptation of hygienic
macro-expansion techniques to general-purpose program generation. The conceptual
novelty of generation scoping lies in making identifier environments first-class
objects and organizing them explicitly into directed graphs. This approach
yields significant benefits: We are able to express scoping relationships
independently of the structure of the generated program. This way we get
a stronger tool for detecting errors in the specification of generated
code. Additionally, we are able to simplify the specification by employing
powerful implicit qualification. Thus, generation scoping becomes a useful
layer of infrastructure for implementing software generators: it both solves
binding problems and makes code specification more convenient.
-
Another Look at Architectural Styles and ADAGE
The relationship of architectural styles and ADAGE was explored in
previous reports, and extensions to GenVoca to support architectural styles
were proposed. In this report, we present a new way of achieving architectural
style customization within GenVoca and show that there is a straightforward
implementation of these ideas. The contribution of our work is that the
basic GenVoca concepts, namely realms, components, elastic interfaces,
and design rule checking, may be sufficient without extensions to express
software systems in a variety of useful architectural styles.