Towards Safely Tolerating Memory Leaks for Garbage-Collected Languages Yan Tang, Qi Gao, and Feng Qin the Ohio State University {Tangya, Gaoq, Qin}@Cse.Ohio-State.Edu

Total Page:16

File Type:pdf, Size:1020Kb

Towards Safely Tolerating Memory Leaks for Garbage-Collected Languages Yan Tang, Qi Gao, and Feng Qin the Ohio State University {Tangya, Gaoq, Qin}@Cse.Ohio-State.Edu LeakSurvivor: Towards Safely Tolerating Memory Leaks for Garbage-Collected Languages Yan Tang, Qi Gao, and Feng Qin The Ohio State University {tangya, gaoq, qin}@cse.ohio-state.edu Abstract arithmetics. With tremendous advances of hardware and Just-In-Time (JIT) compiler techniques, garbage- Continuous memory leaks severely hurt program per- collected languages are now applied even in enterprise formance and software availability for garbage-collected server environments [3, 7]. programs. This paper presents a safe method, called Unfortunately, memory leaks still exist and severely LeakSurvivor, to tolerate continuous memory leaks at affect performance and availability for garbage- runtime for garbage-collected programs. Our main idea collected programs, even though garbage collectors can is to periodically swap out the “Potentially Leaked” (PL) reclaim unreachable memory objects [23]. Memory memory objects identified by leak detectors from the vir- leaks occur in a garbage-collected program when the tual memory to disks. As a result, the virtual memory program keeps references to memory objects that are space occupied by the PL objects can be reclaimed by no longer needed. As a result, the heap space occupied garbage collectors and available for future uses. If a by leaked memory objects cannot be reclaimed by swapped-out PL object is accesses later, LeakSurvivor garbage collectors. For long-running garbage-collected will restore it from disks to the memory for correct pro- programs, continuously-leaked memory objects take up gram execution. Furthermore, LeakSurvivor helps de- more and more space in the heap, leading to more fre- velopers to prune false positives. quent invocation of garbage collections (GC) at runtime. We have built the prototype of LeakSurvivor on top of Additionally, more leaked objects in the heap space Jikes RVM 2.4.2, a high performance Java-in-Java vir- increase the object traversal time during each GC phase. tual machine developed by IBM. We conduct the exper- Therefore, continuous memory leaks cumulatively iments with three Java applications including Eclipse, degrade overall program performance [12, 27]. Even SPECjbb2000 and Jigsaw. Among them, Eclipse and worse, memory leaks may exhaust system resources, Jigsaw contain memory leaks introduced by their devel- eventually causing program crashes [18, 27]. opers, while SPECjbb2000 contain a memory leak in- The performance degradation problem due to memory jected by us. Our results show that LeakSurvivor ef- leaks cannot be completely solved by the paging mech- fectively tolerates memory leaks for two applications anism used in OS memory management or by infinitely (Eclipse and SPECjbb2000), i.e., no cumulative perfor- increasing the heap size (e.g., in 64-bit machines). The mance degradation and no software failures when fac- OS paging mechanism swaps out physical memory to ing continuous memory leaks at runtime. For Jigsaw, disks when physical memory is under pressure, which LeakSurvivor extends the program lifetime by two times leaves the virtual memory space un-reclaimed. There- and improves the performance by 46% compared with fore, heap pressure (i.e., little available heap space) in native runs. Furthermore, when there are no memory the virtual memory due to memory leaks remains the leaks, LeakSurvivor imposes small runtime overhead, same, leading to cumulative performance degradation. i.e., 2.5% over the leak detector and 23.7% over the na- Alternatively, infinitely increasing the heap size, e.g., tive runs. in 64-bit machines, reduces the heap pressure and thus eliminates the increasing GC frequency. However, once 1 Introduction the working set of garbage collectors, i.e., the whole heap, becomes too large to fit into the available physi- Garbage-collected languages such as Java and C# be- cal memory, the program performance will be drastically come increasingly popular. This is partly because pro- degraded due to increased memory paging during each grams written in these languages are free of many types GC phase [44]. of memory errors, which are notorious for compromis- Therefore, it is imperative to devise mechanisms ing system availability and security [42]. For example, for tolerating continuous memory leaks at runtime for by forbidding explicit pointers, Java programs do not garbage-collected programs. The mechanisms must encounter memory corruptions due to incorrect pointer enable programs to maintain relatively stable perfor- USENIX Association USENIX ’08: 2008 USENIX Annual Technical Conference 307 mance and survive software failures caused by contin- its lifetime by two times and improves performance uous memory leaks. by 46% compared with native runs. There are only a few studies [13, 35, 24, 34] on tol- erating memory leaks. They are either unsafe or unable • LeakSurvivor incurs low overhead for programs to prevent performance degradation and out-of-memory during normal execution without memory leaks. errors. Cyclic memory allocation [34] tolerates memory This is because it only adds one extra check dur- leaks by restricting each allocation site to a fixed number ing GC phase. Our evaluation with DaCapo bench- of live objects. While this method may work for appli- marks shows that LeakSurvivor incurs small run- cations that have predictable memory requirements, it is time overhead, i.e., 2.5% over the leak detector and in general unsafe since the live objects could be over- 23.7% over the native runs, when there are no leaks. written. Melt [13] and Plug [35] isolate leaked objects from non-leaked objects and rely on the OS paging for • LeakSurvivor requires no modification in the appli- releasing the physical memory occupied by leaked ob- cations’ source codes. Therefore, it can be easily jects. While they are effective in alleviating the phys- applied to legacy garbage-collected programs. ical memory shortage caused by memory leaks, these methods cannot reduce heap usage in the virtual mem- • LeakSurvivor provides false positive information ory and will eventually trigger the out-of-memory errors. on memory leaks, if any, to developers for prun- Goldstein et al. proposed to dump large unused objects ing purposes. Once a PL object is restored to the to disks [24]. However, their approach does not handle memory, LeakSurvivor marks it as a false positive small leaked objects, which can insidiously cause perfor- and passes this information to the leak detectors. mance and availability problems. Furthermore, it lacks an automatic mechanism to detect leaked objects. 2 Main Idea of LeakSurvivor Our Contributions. In this paper, we propose a safe method for tolerating continuous memory leaks for The main idea of LeakSurvivor is to periodically swap garbage-collected programs at runtime. It can avoid cu- out “Potentially Leaked” (PL) objects from the vir- mulative performance degradation and software failures tual memory to disks so that garbage collectors can re- due to continuous memory leaks. In addition, it helps claim the heap space occupied by these objects. If all developers to prune false positives. leaked memory objects are identified as PL objects and Our idea is to periodically move the “Potentially swapped out, the heap pressure due to memory leaks is Leaked” (PL) memory objects identified by leak detec- eliminated. As a result, LeakSurvivor can avoid cumu- tors from the virtual memory to disks. As a result, the lative program performance degradation and future pro- heap space occupied by PL objects can be reclaimed by gram crashes due to continuous memory leaks. Upon garbage collectors and thus are available for future uses. accesses to some swapped-out PL objects during sub- If a swapped-out PL object is accesses later, LeakSur- sequent program execution, i.e., PL objects are falsely vivor will restore it from disks to the memory for correct identified, LeakSurvivor swaps them from disks to mem- program execution. ory so that the programs can continue execution cor- Based on the above idea, we build a tool called Leak- rectly. In this way, LeakSurvivor guarantees the safety Survivor in Jikes RVM [7], a high performance Java- of leak tolerance. Additionally, LeakSurvivor helps de- in-Java virtual machine developed by IBM, to tolerate velopers to prune false positives. memory leaks at runtime. We evaluate LeakSurvivor Figure 1 shows the process by which LeakSurvivor with three applications, including Eclipse, a popular tolerates memory leaks at runtime and guarantees the integrated development environment, SPECjbb2000, a correctness of subsequent program execution. During simulator of an order-processing server system, and Jig- program execution, LeakSurvivor periodically checks saw, a web server. Among them, Eclipse and Jigsaw whether there are PL objects marked by the integrated contain memory leaks introduced by their developers, leak detectors. If so, it swaps out the PL objects by copy- while SPECjbb2000 contain a memory leak injected by ing the object contents from memory to the leak space us. Unlike previous approaches, LeakSurvivor possesses (See Section 3.2.1), which is mainly on disks. Addition- the following advantages: ally, LeakSurvivor modifies all the PL objects’ incoming references, i.e., references from other objects to the PL • LeakSurvivor can safely and effectively tolerate objects, and outgoing references, i.e., references from memory leaks for garbage-collected program at the PL objects to other objects (See Section 3.2). After runtime. Our evaluation shows that it can tolerate this, the virtual memory space occupied by the PL ob- leaks for two of the three applications (Eclipse and jects can be safely reclaimed by garbage collectors and SPECjbb2000). For Jigsaw, LeakSurvivor extends are available for future uses. Figure 1(a)(b) shows the 308 USENIX ’08: 2008 USENIX Annual Technical Conference USENIX Association Virtual Physical Virtual Physical Virtual Physical Virtual Physical Memory Memory Memory Memory Memory Memory Memory Memory PL object Leak Space/Disk Leak Space/Disk Leak Space/Disk Leak Space/Disk (a) Mark a PL object (b) Swap out a PL object (c) Access a PL object (d) Swap in a PL object Figure 1: LeakSurvivor: The main idea (PL means “Potentially Leaked”).
Recommended publications
  • Memory Diagrams and Memory Debugging
    CSCI-1200 Data Structures | Spring 2020 Lab 4 | Memory Diagrams and Memory Debugging Checkpoint 1 (focusing on Memory Diagrams) will be available at the start of Wednesday's lab. Checkpoints 2 and 3 focus on using a memory debugger. It is highly recommended that you thoroughly read the instructions for Checkpoint 2 and Checkpoint 3 before starting. Memory debuggers will be a useful tool in many of the assignments this semester, and in C++ development if you work with the language outside of this course. While a traditional debugger lets you step through your code and examine variables, a memory debugger instead reports memory-related errors during execution and can help find memory leaks after your program has terminated. The next time you see a \segmentation fault", or it works on your machine but not on Submitty, try running a memory debugger! Please download the following 4 files needed for this lab: http://www.cs.rpi.edu/academics/courses/spring20/csci1200/labs/04_memory_debugging/buggy_lab4. cpp http://www.cs.rpi.edu/academics/courses/spring20/csci1200/labs/04_memory_debugging/first.txt http://www.cs.rpi.edu/academics/courses/spring20/csci1200/labs/04_memory_debugging/middle. txt http://www.cs.rpi.edu/academics/courses/spring20/csci1200/labs/04_memory_debugging/last.txt Checkpoint 2 estimate: 20-40 minutes For Checkpoint 2 of this lab, we will revisit the final checkpoint of the first lab of this course; only this time, we will heavily rely on dynamic memory to find the average and smallest number for a set of data from an input file. You will use a memory debugging tool such as DrMemory or Valgrind to fix memory errors and leaks in buggy lab4.cpp.
    [Show full text]
  • Automatic Detection of Uninitialized Variables
    Automatic Detection of Uninitialized Variables Thi Viet Nga Nguyen, Fran¸cois Irigoin, Corinne Ancourt, and Fabien Coelho Ecole des Mines de Paris, 77305 Fontainebleau, France {nguyen,irigoin,ancourt,coelho}@cri.ensmp.fr Abstract. One of the most common programming errors is the use of a variable before its definition. This undefined value may produce incorrect results, memory violations, unpredictable behaviors and program failure. To detect this kind of error, two approaches can be used: compile-time analysis and run-time checking. However, compile-time analysis is far from perfect because of complicated data and control flows as well as arrays with non-linear, indirection subscripts, etc. On the other hand, dynamic checking, although supported by hardware and compiler tech- niques, is costly due to heavy code instrumentation while information available at compile-time is not taken into account. This paper presents a combination of an efficient compile-time analysis and a source code instrumentation for run-time checking. All kinds of variables are checked by PIPS, a Fortran research compiler for program analyses, transformation, parallelization and verification. Uninitialized array elements are detected by using imported array region, an efficient inter-procedural array data flow analysis. If exact array regions cannot be computed and compile-time information is not sufficient, array elements are initialized to a special value and their utilization is accompanied by a value test to assert the legality of the access. In comparison to the dynamic instrumentation, our method greatly reduces the number of variables to be initialized and to be checked. Code instrumentation is only needed for some array sections, not for the whole array.
    [Show full text]
  • Memory Debugging
    Center for Information Services and High Performance Computing (ZIH) Memory Debugging HRSK Practical on Debugging, 03.04.2009 Zellescher Weg 12 Willers-Bau A106 Tel. +49 351 - 463 - 31945 Matthias Lieber ([email protected]) Tobias Hilbrich ([email protected]) Content Introduction Tools – Valgrind – DUMA Demo Exercise Memory Debugging 2 Memory Debugging Segmentation faults sometimes happen far behind the incorrect code Memory debuggers help to find the real cause of memory bugs Detect memory management bugs – Access non-allocated memory – Access memory out off allocated bounds – Memory leaks – when pointers to allocated areas get lost forever – etc. Different approaches – Valgrind: Simulation of the program run in a virtual machine which accurately observes memory operations – Libraries like ElectricFence, DMalloc, and DUMA: Replace memory management functions through own versions Memory Debugging 3 Memory Debugging with Valgrind Valgrind detects: – Use of uninitialized memory – Access free’d memory – Access memory out off allocated bounds – Access inappropriate areas on the stack – Memory leaks – Mismatched use of malloc and free (C, Fortran), new and delete (C++) – Wrong use of memcpy() and related functions Available on Deimos via – module load valgrind Simply run program under Valgrind: – valgrind ./myprog More Information: http://www.valgrind.org Memory Debugging 4 Memory Debugging with Valgrind Memory Debugging 5 Memory Debugging with DUMA DUMA detects: – Access memory out off allocated bounds – Using a
    [Show full text]
  • GC Assertions: Using the Garbage Collector to Check Heap Properties
    GC Assertions: Using the Garbage Collector to Check Heap Properties Edward Aftandilian Samuel Z. Guyer Tufts University Tufts University 161 College Ave 161 College Ave Medford MA Medford MA [email protected] [email protected] ABSTRACT The goal of this work is to develop a general mechanism, which GC assertion ex- This paper introduces GC assertions, a system interface that pro- we call a , that allows the programmer to express pected grammers can use to check for errors, such as data structure in- properties of data structures and convey this information to variant violations, and to diagnose performance problems, such as the garbage collector. The key is that many useful, non-trivial prop- memory leaks. GC assertions are checked by the garbage collec- erties can be easily checked by the garbage collector at GC time, tor, which is in a unique position to gather information and answer imposing little or no run-time overhead. The collector triggers the questions about the lifetime and connectivity of objects in the heap. assertion if it finds that the expected properties have been violated. We introduce several kinds of GC assertions, and we describe how While GC assertions require extra programmer effort, they cap- they are implemented in the collector. We also describe our report- ture application-specific properties that programmers want to check ing mechanism, which provides a complete path through the heap and can easily express. For example, we provide a GC assertion to to the offending objects. We show results for one type of asser- verify that a data structure is reclaimed at the next collection when tion that allows the programmer to indicate that an object should the programmer expects it to be garbage.
    [Show full text]
  • HALO: Post-Link Heap-Layout Optimisation
    HALO: Post-Link Heap-Layout Optimisation Joe Savage Timothy M. Jones University of Cambridge, UK University of Cambridge, UK [email protected] [email protected] Abstract 1 Introduction Today, general-purpose memory allocators dominate the As the gap between memory and processor speeds continues landscape of dynamic memory management. While these so- to widen, efficient cache utilisation is more important than lutions can provide reasonably good behaviour across a wide ever. While compilers have long employed techniques like range of workloads, it is an unfortunate reality that their basic-block reordering, loop fission and tiling, and intelligent behaviour for any particular workload can be highly subop- register allocation to improve the cache behaviour of pro- timal. By catering primarily to average and worst-case usage grams, the layout of dynamically allocated memory remains patterns, these allocators deny programs the advantages of largely beyond the reach of static tools. domain-specific optimisations, and thus may inadvertently Today, when a C++ program calls new, or a C program place data in a manner that hinders performance, generating malloc, its request is satisfied by a general-purpose allocator unnecessary cache misses and load stalls. with no intimate knowledge of what the program does or To help alleviate these issues, we propose HALO: a post- how its data objects are used. Allocations are made through link profile-guided optimisation tool that can improve the fixed, lifeless interfaces, and fulfilled by
    [Show full text]
  • Heapviz: Interactive Heap Visualization for Program Understanding and Debugging
    Heapviz: Interactive Heap Visualization for Program Understanding and Debugging 1 Abstract Understanding the data structures in a program is crucial to understanding how the program works, or why it doesn’t work. Inspecting the code that implements the data structures, however, is an arduous task and often fails to yield insights into the global organization of a program’s data. Inspecting the actual contents of the heap solves these problems but presents a significant challenge of its own: finding an effective way to present the enormous number of objects it contains. In this paper we present Heapviz, a tool for visualizing and exploring snapshots of the heap obtained from a running Java program. Unlike existing tools, such as tra- ditional debuggers, Heapviz presents a global view of the program state as a graph, together with powerful interactive capabilities for navigating it. Our tool employs sev- eral key techniques that help manage the scale of the data. First, we reduce the size and complexity of the graph by using algorithms inspired by static shape analysis to aggregate the nodes that make up a data structure. Second, we implement a power- ful visualization component whose interactive interface provides extensive support for exploring the graph. The user can search for objects based on type, connectivity, and field values; group objects; and color or hide and show each group. The user may also inspect individual objects to see their field values and neighbors in the graph. These interactive abilities help the user manage the complexity of these huge graphs. By applying Heapviz to both constructed and real-world examples, we show that Heapviz provides programmers with a powerful and intuitive tool for exploring program behavior.
    [Show full text]
  • Efficient and Programmable Support for Memory Access Monitoring And
    Appears in the Proceedings of the 13th International Symposium on High-Performance Computer Architecture (HPCA-13), February 2007. MemTracker: Efficient and Programmable Support for Memory Access Monitoring and Debugging ∗ Guru Venkataramani Brandyn Roemer Yan Solihin Milos Prvulovic Georgia Tech Georgia Tech North Carolina State University Georgia Tech [email protected] [email protected] [email protected] [email protected] Abstract many of these tasks, performance overheads of such tools are prohibitive, especially in post-deployment monitoring of live Memory bugs are a broad class of bugs that is becoming (production) runs where end users are directly affected by the increasingly common with increasing software complexity, overheads of the monitoring scheme. and many of these bugs are also security vulnerabilities. Un- One particularly important and broad class of program- fortunately, existing software and even hardware approaches ming errors is erroneous use or management of memory for finding and identifying memory bugs have considerable (memory bugs). This class of errors includes pointer arith- performance overheads, target only a narrow class of bugs, metic errors, use of dangling pointers, reads from unini- are costly to implement, or use computational resources in- tialized locations, out-of-bounds accesses (e.g. buffer over- efficiently. flows), memory leaks, etc. Many software tools have been This paper describes MemTracker, a new hardware sup- developed to detect some of these errors. For example, Pu- port mechanism that can be configured to perform different rify [8] and Valgrind [13] detect memory leaks, accesses to kinds of memory access monitoring tasks. MemTracker as- unallocated memory, reads from uninitialized memory, and sociates each word of data in memory with a few bits of some dangling pointer and out-of-bounds accesses.
    [Show full text]
  • Transparent Garbage Collection for C++
    Document Number: WG21/N1833=05-0093 Date: 2005-06-24 Reply to: Hans-J. Boehm [email protected] 1501 Page Mill Rd., MS 1138 Palo Alto CA 94304 USA Transparent Garbage Collection for C++ Hans Boehm Michael Spertus Abstract A number of possible approaches to automatic memory management in C++ have been considered over the years. Here we propose the re- consideration of an approach that relies on partially conservative garbage collection. Its principal advantage is that objects referenced by ordinary pointers may be garbage-collected. Unlike other approaches, this makes it possible to garbage-collect ob- jects allocated and manipulated by most legacy libraries. This makes it much easier to convert existing code to a garbage-collected environment. It also means that it can be used, for example, to “repair” legacy code with deficient memory management. The approach taken here is similar to that taken by Bjarne Strous- trup’s much earlier proposal (N0932=96-0114). Based on prior discussion on the core reflector, this version does insist that implementations make an attempt at garbage collection if so requested by the application. How- ever, since there is no real notion of space usage in the standard, there is no way to make this a substantive requirement. An implementation that “garbage collects” by deallocating all collectable memory at process exit will remain conforming, though it is likely to be unsatisfactory for some uses. 1 Introduction A number of different mechanisms for adding automatic memory reclamation (garbage collection) to C++ have been considered: 1. Smart-pointer-based approaches which recycle objects no longer ref- erenced via special library-defined replacement pointer types.
    [Show full text]
  • Secure Virtual Architecture: Using LLVM to Provide Memory Safety to the Entire Software Stack
    Secure Virtual Architecture: Using LLVM to Provide Memory Safety to the Entire Software Stack John Criswell, University of Illinois Andrew Lenharth, University of Illinois Dinakar Dhurjati, DoCoMo Communications Laboratories, USA Vikram Adve, University of Illinois What is Memory Safety? Intuitively, the guarantees provided by a safe programming language (e.g., Java, C#) Array indexing stays within object bounds No uses of uninitialized variables All operations are type safe No uses of dangling pointers Control flow obeys program semantics Sound operational semantics Benefits of Memory Safety for Commodity OS Code Security Memory error vulnerabilities in OS kernel code are a reality1 Novel Design Opportunities Safe kernel extensions (e.g. SPIN) Single address space OSs (e.g. Singularity) Develop New Solutions to Higher-Level Security Challenges Information flow policies Encoding security policies in type system 1. Month of Kernel Bugs (http://projects.info-pull.com/mokb/) Secure Virtual Architecture Commodity OS Virtual ISA Compiler + VM Hardware Native ISA Compiler-based virtual machine underneath software stack Uses analysis & transformation techniques from compilers Supports commodity operating systems (e.g., Linux) Typed virtual instruction set enables sophisticated program analysis Provide safe execution environment for commodity OSs Outline SVA Architecture SVA Safety Experimental Results SVA System Architecture Applications Safety Checking Compiler OS Kernel Drivers OS Memory Allocator SVA ISA Safety Verifier
    [Show full text]
  • An Evolutionary Study of Linux Memory Management for Fun and Profit Jian Huang, Moinuddin K
    An Evolutionary Study of Linux Memory Management for Fun and Profit Jian Huang, Moinuddin K. Qureshi, and Karsten Schwan, Georgia Institute of Technology https://www.usenix.org/conference/atc16/technical-sessions/presentation/huang This paper is included in the Proceedings of the 2016 USENIX Annual Technical Conference (USENIX ATC ’16). June 22–24, 2016 • Denver, CO, USA 978-1-931971-30-0 Open access to the Proceedings of the 2016 USENIX Annual Technical Conference (USENIX ATC ’16) is sponsored by USENIX. An Evolutionary Study of inu emory anagement for Fun and rofit Jian Huang, Moinuddin K. ureshi, Karsten Schwan Georgia Institute of Technology Astract the patches committed over the last five years from 2009 to 2015. The study covers 4587 patches across Linux We present a comprehensive and uantitative study on versions from 2.6.32.1 to 4.0-rc4. We manually label the development of the Linux memory manager. The each patch after carefully checking the patch, its descrip- study examines 4587 committed patches over the last tions, and follow-up discussions posted by developers. five years (2009-2015) since Linux version 2.6.32. In- To further understand patch distribution over memory se- sights derived from this study concern the development mantics, we build a tool called MChecker to identify the process of the virtual memory system, including its patch changes to the key functions in mm. MChecker matches distribution and patterns, and techniues for memory op- the patches with the source code to track the hot func- timizations and semantics. Specifically, we find that tions that have been updated intensively.
    [Show full text]
  • Declarative Computation Model Memory Management Last Call
    Memory Management Declarative Computation Model Memory management (VRH 2.5) • Semantic stack and store sizes during computation – analysis using operational semantics Carlos Varela – recursion used for looping RPI • efficient because of last call optimization October 5, 2006 – memory life cycle Adapted with permission from: – garbage collection Seif Haridi KTH Peter Van Roy UCL C. Varela; Adapted w/permission from S. Haridi and P. Van Roy 1 C. Varela; Adapted w/permission from S. Haridi and P. Van Roy 2 Last call optimization Last call optimization • Consider the following procedure ST: [ ({Loop10 0}, E0) ] proc {Loop10 I} ST: [({Browse I}, {I→i ,...}) proc {Loop10 I} 0 if I ==10 then skip ({Loop10 I+1}, {I→i ,...}) ] else if I ==10 then skip 0 else σ : {i =0, ...} {Browse I} 0 {Browse I} Recursive call {Loop10 I+1} {Loop10 I+1} end is the last call end ST: [({Loop10 I+1}, {I→i0,...}) ] end end σ : {i0=0, ...} • This procedure does not increase the size of the STACK ST: [({Browse I}, {I→i1,...}) • It behaves like a looping construct ({Loop10 I+1}, {I→i1,...}) ] σ : {i0=0, i1=1,...} C. Varela; Adapted w/permission from S. Haridi and P. Van Roy 3 C. Varela; Adapted w/permission from S. Haridi and P. Van Roy 4 Stack and Store Size Garbage collection proc {Loop10 I} proc {Loop10 I} ST: [({Browse I}, {I→ik,...}) ST: [({Browse I}, {I→ik,...}) if I ==10 then skip if I ==10 then skip ({Loop10 I+1}, {I i ,...}) ] ({Loop10 I+1}, {I i ,...}) ] else → k else → k {Browse I} σ : {i0=0, i1=1,..., ik-i=k-1, ik=k,..
    [Show full text]
  • Ubuntu Server Guide Basic Installation Preparing to Install
    Ubuntu Server Guide Welcome to the Ubuntu Server Guide! This site includes information on using Ubuntu Server for the latest LTS release, Ubuntu 20.04 LTS (Focal Fossa). For an offline version as well as versions for previous releases see below. Improving the Documentation If you find any errors or have suggestions for improvements to pages, please use the link at thebottomof each topic titled: “Help improve this document in the forum.” This link will take you to the Server Discourse forum for the specific page you are viewing. There you can share your comments or let us know aboutbugs with any page. PDFs and Previous Releases Below are links to the previous Ubuntu Server release server guides as well as an offline copy of the current version of this site: Ubuntu 20.04 LTS (Focal Fossa): PDF Ubuntu 18.04 LTS (Bionic Beaver): Web and PDF Ubuntu 16.04 LTS (Xenial Xerus): Web and PDF Support There are a couple of different ways that the Ubuntu Server edition is supported: commercial support and community support. The main commercial support (and development funding) is available from Canonical, Ltd. They supply reasonably- priced support contracts on a per desktop or per-server basis. For more information see the Ubuntu Advantage page. Community support is also provided by dedicated individuals and companies that wish to make Ubuntu the best distribution possible. Support is provided through multiple mailing lists, IRC channels, forums, blogs, wikis, etc. The large amount of information available can be overwhelming, but a good search engine query can usually provide an answer to your questions.
    [Show full text]