High Performance Python 2nd Edition Micha Gorelick Ian Ozsvald
High Performance Python 2nd Edition Micha Gorelick Ian Ozsvald
High Performance Python 2nd Edition Micha Gorelick Ian Ozsvald
Basics and rules of probability with real-life usesravatkaran694
An introduction to Prepositions for beginners.pptxdrsiddhantnagine
The Minister of Tourism, Culture and Creative Arts, Abla Dzifa Gomashie has e...nservice241
Health-The-Ultimate-Treasure (1).pdf/8th class science curiosity /samyans edu...Sandeep Swamy
INTESTINALPARASITES OR WORM INFESTATIONS.pptxPRADEEP ABOTHU
Ad
High Performance Python 2nd Edition Micha Gorelick Ian Ozsvald
1. High Performance Python 2nd Edition Micha
Gorelick Ian Ozsvald download
https://ebookbell.com/product/high-performance-python-2nd-
edition-micha-gorelick-ian-ozsvald-42370716
Explore and download more ebooks at ebookbell.com
2. Here are some recommended products that we believe you will be
interested in. You can click the link to download.
High Performance Python Practical Performant Programming For Humans
2nd Edition Micha Gorelick
https://ebookbell.com/product/high-performance-python-practical-
performant-programming-for-humans-2nd-edition-micha-gorelick-24064792
High Performance Python Practical Performant Programming For Humans
Micha Gorelick
https://ebookbell.com/product/high-performance-python-practical-
performant-programming-for-humans-micha-gorelick-4766942
High Performance Python 2nd Edition Micha Gorelick Ian Ozsvald
https://ebookbell.com/product/high-performance-python-2nd-edition-
micha-gorelick-ian-ozsvald-42305640
High Performance Python 2nd Edition Micha Gorelick Ian Ozsvald
https://ebookbell.com/product/high-performance-python-2nd-edition-
micha-gorelick-ian-ozsvald-47965494
3. High Performance Python 1st Edition Micha Gorelick
https://ebookbell.com/product/high-performance-python-1st-edition-
micha-gorelick-56948254
High Performance Python Ian Ozsvald Micha Gorelick
https://ebookbell.com/product/high-performance-python-ian-ozsvald-
micha-gorelick-10825332
High Performance Python Ozsvald Ian Gorelick Micha
https://ebookbell.com/product/high-performance-python-ozsvald-ian-
gorelick-micha-61033454
High Performance Python Micha Gorelick
https://ebookbell.com/product/high-performance-python-micha-
gorelick-170625196
Python High Performance 2nd Edition Gabriele Lanaro
https://ebookbell.com/product/python-high-performance-2nd-edition-
gabriele-lanaro-49052724
6. 1. Foreword
2. Preface
a. Who This Book Is For
b. Who This Book Is Not For
c. What You’ll Learn
d. Python 3
e. Changes from Python 2.7
f. License
g. How to Make an Attribution
h. Errata and Feedback
i. Conventions Used in This Book
j. Using Code Examples
k. O’Reilly Online Learning
l. How to Contact Us
m. Acknowledgments
3. 1. Understanding Performant Python
a. The Fundamental Computer System
i. Computing Units
ii. Memory Units
iii. Communications Layers
b. Putting the Fundamental Elements Together
7. i. Idealized Computing Versus the Python
Virtual Machine
c. So Why Use Python?
d. How to Be a Highly Performant Programmer
i. Good Working Practices
ii. Some Thoughts on Good Notebook
Practice
iii. Getting the Joy Back into Your Work
4. 2. Profiling to Find Bottlenecks
a. Profiling Efficiently
b. Introducing the Julia Set
c. Calculating the Full Julia Set
d. Simple Approaches to Timing—print and a
Decorator
e. Simple Timing Using the Unix time Command
f. Using the cProfile Module
g. Visualizing cProfile Output with SnakeViz
h. Using line_profiler for Line-by-Line
Measurements
i. Using memory_profiler to Diagnose Memory
Usage
j. Introspecting an Existing Process with PySpy
k. Bytecode: Under the Hood
8. i. Using the dis Module to Examine
CPython Bytecode
ii. Different Approaches, Different
Complexity
l. Unit Testing During Optimization to Maintain
Correctness
i. No-op @profile Decorator
m. Strategies to Profile Your Code Successfully
n. Wrap-Up
5. 3. Lists and Tuples
a. A More Efficient Search
b. Lists Versus Tuples
i. Lists as Dynamic Arrays
ii. Tuples as Static Arrays
c. Wrap-Up
6. 4. Dictionaries and Sets
a. How Do Dictionaries and Sets Work?
i. Inserting and Retrieving
ii. Deletion
iii. Resizing
iv. Hash Functions and Entropy
b. Dictionaries and Namespaces
c. Wrap-Up
9. 7. 5. Iterators and Generators
a. Iterators for Infinite Series
b. Lazy Generator Evaluation
c. Wrap-Up
8. 6. Matrix and Vector Computation
a. Introduction to the Problem
b. Aren’t Python Lists Good Enough?
i. Problems with Allocating Too Much
c. Memory Fragmentation
i. Understanding perf
ii. Making Decisions with perf’s Output
iii. Enter numpy
d. Applying numpy to the Diffusion Problem
i. Memory Allocations and In-Place
Operations
ii. Selective Optimizations: Finding What
Needs to Be Fixed
e. numexpr: Making In-Place Operations Faster
and Easier
f. A Cautionary Tale: Verify “Optimizations”
(scipy)
g. Lessons from Matrix Optimizations
h. Pandas
10. i. Pandas’s Internal Model
ii. Applying a Function to Many Rows of
Data
iii. Building DataFrames and Series from
Partial Results Rather than
Concatenating
iv. There’s More Than One (and Possibly a
Faster) Way to Do a Job
v. Advice for Effective Pandas
Development
i. Wrap-Up
9. 7. Compiling to C
a. What Sort of Speed Gains Are Possible?
b. JIT Versus AOT Compilers
c. Why Does Type Information Help the Code
Run Faster?
d. Using a C Compiler
e. Reviewing the Julia Set Example
f. Cython
i. Compiling a Pure Python Version
Using Cython
g. pyximport
i. Cython Annotations to Analyze a Block
of Code
ii. Adding Some Type Annotations
11. h. Cython and numpy
i. Parallelizing the Solution with OpenMP
on One Machine
i. Numba
i. Numba to Compile NumPy for Pandas
j. PyPy
i. Garbage Collection Differences
ii. Running PyPy and Installing Modules
k. A Summary of Speed Improvements
l. When to Use Each Technology
i. Other Upcoming Projects
m. Graphics Processing Units (GPUs)
i. Dynamic Graphs: PyTorch
ii. Basic GPU Profiling
iii. Performance Considerations of GPUs
iv. When to Use GPUs
n. Foreign Function Interfaces
i. ctypes
ii. cffi
iii. f2py
iv. CPython Module
o. Wrap-Up
12. 10. 8. Asynchronous I/O
a. Introduction to Asynchronous Programming
b. How Does async/await Work?
i. Serial Crawler
ii. Gevent
iii. tornado
iv. aiohttp
c. Shared CPU–I/O Workload
i. Serial
ii. Batched Results
iii. Full Async
d. Wrap-Up
11. 9. The multiprocessing Module
a. An Overview of the multiprocessing Module
b. Estimating Pi Using the Monte Carlo Method
c. Estimating Pi Using Processes and Threads
i. Using Python Objects
ii. Replacing multiprocessing with Joblib
iii. Random Numbers in Parallel Systems
iv. Using numpy
d. Finding Prime Numbers
i. Queues of Work
13. e. Verifying Primes Using Interprocess
Communication
i. Serial Solution
ii. Naive Pool Solution
iii. A Less Naive Pool Solution
iv. Using Manager.Value as a Flag
v. Using Redis as a Flag
vi. Using RawValue as a Flag
vii. Using mmap as a Flag
viii. Using mmap as a Flag Redux
f. Sharing numpy Data with multiprocessing
g. Synchronizing File and Variable Access
i. File Locking
ii. Locking a Value
h. Wrap-Up
12. 10. Clusters and Job Queues
a. Benefits of Clustering
b. Drawbacks of Clustering
i. $462 Million Wall Street Loss Through
Poor Cluster Upgrade Strategy
ii. Skype’s 24-Hour Global Outage
c. Common Cluster Designs
d. How to Start a Clustered Solution
14. e. Ways to Avoid Pain When Using Clusters
f. Two Clustering Solutions
i. Using IPython Parallel to Support
Research
ii. Parallel Pandas with Dask
g. NSQ for Robust Production Clustering
i. Queues
ii. Pub/sub
iii. Distributed Prime Calculation
h. Other Clustering Tools to Look At
i. Docker
i. Docker’s Performance
ii. Advantages of Docker
j. Wrap-Up
13. 11. Using Less RAM
a. Objects for Primitives Are Expensive
i. The array Module Stores Many
Primitive Objects Cheaply
ii. Using Less RAM in NumPy with
NumExpr
b. Understanding the RAM Used in a Collection
c. Bytes Versus Unicode
d. Efficiently Storing Lots of Text in RAM
15. i. Trying These Approaches on 11 Million
Tokens
e. Modeling More Text with Scikit-Learn’s
FeatureHasher
f. Introducing DictVectorizer and FeatureHasher
i. Comparing DictVectorizer and
FeatureHasher on a Real Problem
g. SciPy’s Sparse Matrices
h. Tips for Using Less RAM
i. Probabilistic Data Structures
i. Very Approximate Counting with a 1-
Byte Morris Counter
ii. K-Minimum Values
iii. Bloom Filters
iv. LogLog Counter
v. Real-World Example
14. 12. Lessons from the Field
a. Streamlining Feature Engineering Pipelines
with Feature-engine
i. Feature Engineering for Machine
Learning
ii. The Hard Task of Deploying Feature
Engineering Pipelines
iii. Leveraging the Power of Open Source
Python Libraries
16. iv. Feature-engine Smooths Building and
Deployment of Feature Engineering
Pipelines
v. Helping with the Adoption of a New
Open Source Package
vi. Developing, Maintaining, and
Encouraging Contribution to Open
Source Libraries
b. Highly Performant Data Science Teams
i. How Long Will It Take?
ii. Discovery and Planning
iii. Managing Expectations and Delivery
c. Numba
i. A Simple Example
ii. Best Practices and Recommendations
iii. Getting Help
d. Optimizing Versus Thinking
e. Adaptive Lab’s Social Media Analytics (2014)
i. Python at Adaptive Lab
ii. SoMA’s Design
iii. Our Development Methodology
iv. Maintaining SoMA
v. Advice for Fellow Engineers
17. f. Making Deep Learning Fly with
RadimRehurek.com (2014)
i. The Sweet Spot
ii. Lessons in Optimizing
iii. Conclusion
g. Large-Scale Productionized Machine Learning
at Lyst.com (2014)
i. Cluster Design
ii. Code Evolution in a Fast-Moving Start-
Up
iii. Building the Recommendation Engine
iv. Reporting and Monitoring
v. Some Advice
h. Large-Scale Social Media Analysis at Smesh
(2014)
i. Python’s Role at Smesh
ii. The Platform
iii. High Performance Real-Time String
Matching
iv. Reporting, Monitoring, Debugging, and
Deployment
i. PyPy for Successful Web and Data Processing
Systems (2014)
i. Prerequisites
ii. The Database
18. iii. The Web Application
iv. OCR and Translation
v. Task Distribution and Workers
vi. Conclusion
j. Task Queues at Lanyrd.com (2014)
i. Python’s Role at Lanyrd
ii. Making the Task Queue Performant
iii. Reporting, Monitoring, Debugging, and
Deployment
iv. Advice to a Fellow Developer
15. Index
21. 2020-04-30: First release
See http://oreilly.com/catalog/errata.csp?isbn=9781492055020
for release details.
The O’Reilly logo is a registered trademark of O’Reilly Media,
Inc. High Performance Python, the cover image, and related
trade dress are trademarks of O’Reilly Media, Inc.
The views expressed in this work are those of the authors, and
do not represent the publisher’s views. While the publisher and
the authors have used good faith efforts to ensure that the
information and instructions contained in this work are
accurate, the publisher and the authors disclaim all
responsibility for errors or omissions, including without
limitation responsibility for damages resulting from the use of or
reliance on this work. Use of the information and instructions
contained in this work is at your own risk. If any code samples
or other technology this work contains or describes is subject
to open source licenses or the intellectual property rights of
others, it is your responsibility to ensure that your use thereof
complies with such licenses and/or rights.
High Performance Python is available under the Creative
Commons Attribution-NonCommercial-NoDerivs 3.0
International License.
978-1-492-05502-0
[LSI]
23. Foreword
When you think about high performance computing, you might
imagine giant clusters of machines modeling complex weather
phenomena or trying to understand signals in data collected
about far-off stars. It’s easy to assume that only people building
specialized systems should worry about the performance
characteristics of their code. By picking up this book, you’ve
taken a step toward learning the theory and practices you’ll
need to write highly performant code. Every programmer can
benefit from understanding how to build performant systems.
There are an obvious set of applications that are just on the
edge of possible, and you won’t be able to approach them
without writing optimally performant code. If that’s your
practice, you’re in the right place. But there is a much broader
set of applications that can benefit from performant code.
We often think that new technical capabilities are what drives
innovation, but I’m equally fond of capabilities that increase the
accessibility of technology by orders of magnitude. When
something becomes ten times cheaper in time or compute
costs, suddenly the set of applications you can address is
wider than you imagined.
The first time this principle manifested in my own work was
over a decade ago, when I was working at a social media
company, and we ran an analysis over multiple terabytes of
24. data to determine whether people clicked on more photos of
cats or dogs on social media.
It was dogs, of course. Cats just have better branding.
This was an outstandingly frivolous use of compute time and
infrastructure at the time! Gaining the ability to apply
techniques that had previously been restricted to sufficiently
high-value applications, such as fraud detection, to a
seemingly trivial question opened up a new world of now-
accessible possibilities. We were able to take what we learned
from these experiments and build a whole new set of products
in search and content discovery.
For an example that you might encounter today, consider a
machine-learning system that recognizes unexpected animals
or people in security video footage. A sufficiently performant
system could allow you to embed that model into the camera
itself, improving privacy or, even if running in the cloud, using
significantly less compute and power—benefiting the
environment and reducing your operating costs. This can free
up resources for you to look at adjacent problems, potentially
building a more valuable system.
We all desire to create systems that are effective, easy to
understand, and performant. Unfortunately, it often feels like
we have to pick two (or one) out of the three! High
Performance Python is a handbook for people who want to
make things that are capable of all three.
25. This book stands apart from other texts on the subject in three
ways. First, it’s written for us—humans who write code. You’ll
find all of the context you need to understand why you might
make certain choices. Second, Gorelick and Ozsvald do a
wonderful job of curating and explaining the necessary theory
to support that context. Finally, in this updated edition, you’ll
learn the specific quirks of the most useful libraries for
implementing these approaches today.
This is one of a rare class of programming books that will
change the way you think about the practice of programming.
I’ve given this book to many people who could benefit from the
additional tools it provides. The ideas that you’ll explore in its
pages will make you a better programmer, no matter what
language or environment you choose to work in.
Enjoy the adventure.
Hilary Mason,
Data Scientist in Residence at Accel
26. Preface
Python is easy to learn. You’re probably here because now that
your code runs correctly, you need it to run faster. You like the
fact that your code is easy to modify and you can iterate with
ideas quickly. The trade-off between easy to develop and runs
as quickly as I need is a well-understood and often-bemoaned
phenomenon. There are solutions.
Some people have serial processes that have to run faster.
Others have problems that could take advantage of multicore
architectures, clusters, or graphics processing units. Some
need scalable systems that can process more or less as
expediency and funds allow, without losing reliability. Others
will realize that their coding techniques, often borrowed from
other languages, perhaps aren’t as natural as examples they
see from others.
In this book we will cover all of these topics, giving practical
guidance for understanding bottlenecks and producing faster
and more scalable solutions. We also include some war stories
from those who went ahead of you, who took the knocks so
you don’t have to.
Python is well suited for rapid development, production
deployments, and scalable systems. The ecosystem is full of
27. people who are working to make it scale on your behalf,
leaving you more time to focus on the more challenging tasks
around you.
28. Who This Book Is For
You’ve used Python for long enough to have an idea about why
certain things are slow and to have seen technologies like
Cython, numpy, and PyPy being discussed as possible
solutions. You might also have programmed with other
languages and so know that there’s more than one way to
solve a performance problem.
While this book is primarily aimed at people with CPU-bound
problems, we also look at data transfer and memory-bound
solutions. Typically, these problems are faced by scientists,
engineers, quants, and academics.
We also look at problems that a web developer might face,
including the movement of data and the use of just-in-time (JIT)
compilers like PyPy and asynchronous I/O for easy-win
performance gains.
It might help if you have a background in C (or C++, or maybe
Java), but it isn’t a prerequisite. Python’s most common
interpreter (CPython—the standard you normally get if you type
python at the command line) is written in C, and so the hooks
and libraries all expose the gory inner C machinery. There are
lots of other techniques that we cover that don’t assume any
knowledge of C.
You might also have a lower-level knowledge of the CPU,
memory architecture, and data buses, but again, that’s not
30. Who This Book Is Not For
This book is meant for intermediate to advanced Python
programmers. Motivated novice Python programmers may be
able to follow along as well, but we recommend having a solid
Python foundation.
We don’t cover storage-system optimization. If you have a SQL
or NoSQL bottleneck, then this book probably won’t help you.
What You’ll Learn
Your authors have been working with large volumes of data, a
requirement for I want the answers faster! and a need for
scalable architectures, for many years in both industry and
academia. We’ll try to impart our hard-won experience to save
you from making the mistakes that we’ve made.
At the start of each chapter, we’ll list questions that the
following text should answer. (If it doesn’t, tell us and we’ll fix it
in the next revision!)
We cover the following topics:
Background on the machinery of a computer so you
know what’s happening behind the scenes
Lists and tuples—the subtle semantic and speed
differences in these fundamental data structures
Dictionaries and sets—memory allocation strategies
and access algorithms in these important data
31. structures
Iterators—how to write in a more Pythonic way and
open the door to infinite data streams using iteration
Pure Python approaches—how to use Python and its
modules effectively
Matrices with numpy—how to use the beloved numpy
library like a beast
Compilation and just-in-time computing—processing
faster by compiling down to machine code, making
sure you’re guided by the results of profiling
Concurrency—ways to move data efficiently
multiprocessing—various ways to use the built-in
multiprocessing library for parallel computing and
to efficiently share numpy matrices, and some costs
and benefits of interprocess communication (IPC)
Cluster computing—convert your multiprocessing
code to run on a local or remote cluster for both
research and production systems
Using less RAM—approaches to solving large
problems without buying a humungous computer
Lessons from the field—lessons encoded in war stories
from those who took the blows so you don’t have to
Python 3
Python 3 is the standard version of Python as of 2020, with
Python 2.7 deprecated after a 10-year migration process. If
you’re still on Python 2.7, you’re doing it wrong—many libraries
32. are no longer supported for your line of Python, and support
will become more expensive over time. Please do the
community a favor and migrate to Python 3, and make sure
that all new projects use Python 3.
In this book, we use 64-bit Python. Whilst 32-bit Python is
supported, it is far less common for scientific work. We’d
expect all the libraries to work as usual, but numeric precision,
which depends on the number of bits available for counting, is
likely to change. 64-bit is dominant in this field, along with *nix
environments (often Linux or Mac). 64-bit lets you address
larger amounts of RAM. *nix lets you build applications that can
be deployed and configured in well-understood ways with well-
understood behaviors.
If you’re a Windows user, you’ll have to buckle up. Most of
what we show will work just fine, but some things are OS-
specific, and you’ll have to research a Windows solution. The
biggest difficulty a Windows user might face is the installation
of modules: research in sites like Stack Overflow should give
you the solutions you need. If you’re on Windows, having a
virtual machine (e.g., using VirtualBox) with a running Linux
installation might help you to experiment more freely.
Windows users should definitely look at a packaged solution
like those available through Anaconda, Canopy, Python(x,y), or
Sage. These same distributions will make the lives of Linux
and Mac users far simpler too.
33. Changes from Python 2.7
If you’ve upgraded from Python 2.7, you might not be aware of
a few relevant changes:
/ meant integer division in Python 2.7, whereas it
performs float division in Python 3.
str and unicode were used to represent text data in
Python 2.7; in Python 3, everything is a str, and these
are always Unicode. For clarity, a bytes type is used if
we’re using unencoded byte sequences.
If you’re in the process of upgrading your code, two good
guides are “Porting Python 2 Code to Python 3” and
“Supporting Python 3: An in-depth guide”. With a distribution
like Anaconda or Canopy, you can run both Python 2 and
Python 3 simultaneously—this will simplify your porting.
License
This book is licensed under Creative Commons Attribution-
NonCommercial-NoDerivs 3.0.
You’re welcome to use this book for noncommercial purposes,
including for noncommercial teaching. The license allows only
for complete reproductions; for partial reproductions, please
contact O’Reilly (see “How to Contact Us”). Please attribute the
book as noted in the following section.
34. We negotiated that the book should have a Creative Commons
license so the contents could spread further around the world.
We’d be quite happy to receive a beer if this decision has
helped you. We suspect that the O’Reilly staff would feel
similarly about the beer.
How to Make an Attribution
The Creative Commons license requires that you attribute your
use of a part of this book. Attribution just means that you
should write something that someone else can follow to find
this book. The following would be sensible: “High Performance
Python, 2nd ed., by Micha Gorelick and Ian Ozsvald (O’Reilly).
Copyright 2020 Micha Gorelick and Ian Ozsvald, 978-1-492-
05502-0.”
Errata and Feedback
We encourage you to review this book on public sites like
Amazon—please help others understand if they would benefit
from this book! You can also email us at
[email protected].
We’re particularly keen to hear about errors in the book,
successful use cases where the book has helped you, and high
performance techniques that we should cover in the next
edition. You can access the web page for this book at
https://oreil.ly/high-performance-python-2e.
35. Complaints are welcomed through the instant-complaint-
transmission-service > /dev/null.
Conventions Used in This Book
The following typographical conventions are used in this book:
Italic
Indicates new terms, URLs, email addresses, filenames,
and file extensions.
Constant width
Used for program listings, as well as within paragraphs to
refer to program elements such as variable or function
names, databases, datatypes, environment variables,
statements, and keywords.
Constant width bold
Shows commands or other text that should be typed literally
by the user.
Constant width italic
Shows text that should be replaced with user-supplied
values or by values determined by context.
TIP
This element signifies a tip, suggestion, or critical thinking question.
36. NOTE
This element signifies a general note.
WARNING
This element indicates a warning or caution.
Using Code Examples
Supplemental material (code examples, exercises, etc.) is
available for download at
https://github.com/mynameisfiber/high_performance_python_2
e.
If you have a technical question or a problem using the code
examples, please send email to [email protected].
This book is here to help you get your job done. In general, if
example code is offered with this book, you may use it in your
programs and documentation. You do not need to contact us
for permission unless you’re reproducing a significant portion of
the code. For example, writing a program that uses several
chunks of code from this book does not require permission.
Selling or distributing examples from O’Reilly books does
require permission. Answering a question by citing this book
and quoting example code does not require permission.
Incorporating a significant amount of example code from this
37. book into your product’s documentation does require
permission.
If you feel your use of code examples falls outside fair use or
the permission given above, feel free to contact us at
[email protected].
O’Reilly Online Learning
NOTE
For more than 40 years, O’Reilly Media has provided technology and
business training, knowledge, and insight to help companies succeed.
Our unique network of experts and innovators share their
knowledge and expertise through books, articles, and our
online learning platform. O’Reilly’s online learning platform
gives you on-demand access to live training courses, in-depth
learning paths, interactive coding environments, and a vast
collection of text and video from O’Reilly and 200+ other
publishers. For more information, visit http://oreilly.com.
How to Contact Us
Please address comments and questions concerning this book
to the publisher:
O’Reilly Media, Inc.
38. 1005 Gravenstein Highway North
Sebastopol, CA 95472
800-998-9938 (in the United States or Canada)
707-829-0515 (international or local)
707-829-0104 (fax)
Email [email protected] to comment or ask technical
questions about this book.
For news and more information about our books and courses,
see our website at http://oreilly.com.
Find us on Facebook: http://facebook.com/oreilly
Follow us on Twitter: http://twitter.com/oreillymedia
Watch us on YouTube: http://youtube.com/oreillymedia
Acknowledgments
Hilary Mason wrote our foreword—thanks for composing such
a wonderful opening narrative for our book. Giles Weaver and
Dimitri Denisjonok provided invaluable technical feedback on
this edition; great work, chaps.
Thanks to Patrick Cooper, Kyran Dale, Dan Foreman-Mackey,
Calvin Giles, Brian Granger, Jamie Matthews, John
39. Montgomery, Christian Schou Oxvig, Matt “snakes” Reiferson,
Balthazar Rouberol, Michael Skirpan, Luke Underwood, Jake
Vanderplas, and William Winter for invaluable feedback and
contributions.
Ian thanks his wife, Emily, for letting him disappear for another
eight months to write this second edition (thankfully, she’s
terribly understanding). Ian apologizes to his dog for sitting and
writing rather than walking in the woods quite as much as she’d
have liked.
Micha thanks Marion and the rest of his friends and family for
being so patient while he learned to write.
O’Reilly editors are rather lovely to work with; do strongly
consider talking to them if you want to write your own book.
Our contributors to the “Lessons from the Field” chapter very
kindly shared their time and hard-won lessons. We give thanks
to Soledad Galli, Linda Uruchurtu, Vanentin Haenel, and
Vincent D. Warmerdam for this edition and to Ben Jackson,
Radim Řehůřek, Sebastjan Trepca, Alex Kelly, Marko Tasic,
and Andrew Godwin for their time and effort during the
previous edition.
40. Chapter 1. Understanding
Performant Python
QUESTIONS YOU’LL BE ABLE TO ANSWER AFTER THIS
CHAPTER
What are the elements of a computer’s architecture?
What are some common alternate computer architectures?
How does Python abstract the underlying computer architecture?
What are some of the hurdles to making performant Python code?
What strategies can help you become a highly performant programmer?
Programming computers can be thought of as moving bits of
data and transforming them in special ways to achieve a
particular result. However, these actions have a time cost.
Consequently, high performance programming can be thought
of as the act of minimizing these operations either by reducing
the overhead (i.e., writing more efficient code) or by changing
the way that we do these operations to make each one more
meaningful (i.e., finding a more suitable algorithm).
Let’s focus on reducing the overhead in code in order to gain
more insight into the actual hardware on which we are moving
these bits. This may seem like a futile exercise, since Python
works quite hard to abstract away direct interactions with the
hardware. However, by understanding both the best way that
41. bits can be moved in the real hardware and the ways that
Python’s abstractions force your bits to move, you can make
progress toward writing high performance programs in Python.
The Fundamental Computer System
The underlying components that make up a computer can be
simplified into three basic parts: the computing units, the
memory units, and the connections between them. In addition,
each of these units has different properties that we can use to
understand them. The computational unit has the property of
how many computations it can do per second, the memory unit
has the properties of how much data it can hold and how fast
we can read from and write to it, and finally, the connections
have the property of how fast they can move data from one
place to another.
Using these building blocks, we can talk about a standard
workstation at multiple levels of sophistication. For example,
the standard workstation can be thought of as having a central
processing unit (CPU) as the computational unit, connected to
both the random access memory (RAM) and the hard drive as
two separate memory units (each having different capacities
and read/write speeds), and finally a bus that provides the
connections between all of these parts. However, we can also
go into more detail and see that the CPU itself has several
memory units in it: the L1, L2, and sometimes even the L3 and
L4 cache, which have small capacities but very fast speeds
(from several kilobytes to a dozen megabytes). Furthermore,
42. new computer architectures generally come with new
configurations (for example, Intel’s SkyLake CPUs replaced the
frontside bus with the Intel Ultra Path Interconnect and
restructured many connections). Finally, in both of these
approximations of a workstation we have neglected the
network connection, which is effectively a very slow connection
to potentially many other computing and memory units!
To help untangle these various intricacies, let’s go over a brief
description of these fundamental blocks.
Computing Units
The computing unit of a computer is the centerpiece of its
usefulness—it provides the ability to transform any bits it
receives into other bits or to change the state of the current
process. CPUs are the most commonly used computing unit;
however, graphics processing units (GPUs) are gaining
popularity as auxiliary computing units. They were originally
used to speed up computer graphics but are becoming more
applicable for numerical applications and are useful thanks to
their intrinsically parallel nature, which allows many
calculations to happen simultaneously. Regardless of its type,
a computing unit takes in a series of bits (for example, bits
representing numbers) and outputs another set of bits (for
example, bits representing the sum of those numbers). In
addition to the basic arithmetic operations on integers and real
numbers and bitwise operations on binary numbers, some
computing units also provide very specialized operations, such
43. as the “fused multiply add” operation, which takes in three
numbers, A, B, and C, and returns the value A * B + C.
The main properties of interest in a computing unit are the
number of operations it can do in one cycle and the number of
cycles it can do in one second. The first value is measured by
its instructions per cycle (IPC), while the latter value is
measured by its clock speed. These two measures are always
competing with each other when new computing units are
being made. For example, the Intel Core series has a very high
IPC but a lower clock speed, while the Pentium 4 chip has the
reverse. GPUs, on the other hand, have a very high IPC and
clock speed, but they suffer from other problems like the slow
communications that we discuss in “Communications Layers”.
Furthermore, although increasing clock speed almost
immediately speeds up all programs running on that
computational unit (because they are able to do more
calculations per second), having a higher IPC can also
drastically affect computing by changing the level of
vectorization that is possible. Vectorization occurs when a CPU
is provided with multiple pieces of data at a time and is able to
operate on all of them at once. This sort of CPU instruction is
known as single instruction, multiple data (SIMD).
In general, computing units have advanced quite slowly over
the past decade (see Figure 1-1). Clock speeds and IPC have
both been stagnant because of the physical limitations of
making transistors smaller and smaller. As a result, chip
1
44. manufacturers have been relying on other methods to gain
more speed, including simultaneous multithreading (where
multiple threads can run at once), more clever out-of-order
execution, and multicore architectures.
Hyperthreading presents a virtual second CPU to the host
operating system (OS), and clever hardware logic tries to
interleave two threads of instructions into the execution units
on a single CPU. When successful, gains of up to 30% over a
single thread can be achieved. Typically, this works well when
the units of work across both threads use different types of
execution units—for example, one performs floating-point
operations and the other performs integer operations.
Out-of-order execution enables a compiler to spot that some
parts of a linear program sequence do not depend on the
results of a previous piece of work, and therefore that both
pieces of work could occur in any order or at the same time. As
long as sequential results are presented at the right time, the
program continues to execute correctly, even though pieces of
work are computed out of their programmed order. This
enables some instructions to execute when others might be
blocked (e.g., waiting for a memory access), allowing greater
overall utilization of the available resources.
Finally, and most important for the higher-level programmer,
there is the prevalence of multicore architectures. These
architectures include multiple CPUs within the same unit, which
increases the total capability without running into barriers to
45. making each individual unit faster. This is why it is currently
hard to find any machine with fewer than two cores—in this
case, the computer has two physical computing units that are
connected to each other. While this increases the total number
of operations that can be done per second, it can make writing
code more difficult!
Figure 1-1. Clock speed of CPUs over time (from CPU DB)
Simply adding more cores to a CPU does not always speed up
a program’s execution time. This is because of something
known as Amdahl’s law. Simply stated, Amdahl’s law is this: if
a program designed to run on multiple cores has some
subroutines that must run on one core, this will be the limitation
for the maximum speedup that can be achieved by allocating
more cores.
For example, if we had a survey we wanted one hundred
people to fill out, and that survey took 1 minute to complete, we
could complete this task in 100 minutes if we had one person
asking the questions (i.e., this person goes to participant 1,
asks the questions, waits for the responses, and then moves to
participant 2). This method of having one person asking the
questions and waiting for responses is similar to a serial
process. In serial processes, we have operations being
satisfied one at a time, each one waiting for the previous
operation to complete.
However, we could perform the survey in parallel if we had two
people asking the questions, which would let us finish the
46. process in only 50 minutes. This can be done because each
individual person asking the questions does not need to know
anything about the other person asking questions. As a result,
the task can easily be split up without having any dependency
between the question askers.
Adding more people asking the questions will give us more
speedups, until we have one hundred people asking questions.
At this point, the process would take 1 minute and would be
limited simply by the time it takes a participant to answer
questions. Adding more people asking questions will not result
in any further speedups, because these extra people will have
no tasks to perform—all the participants are already being
asked questions! At this point, the only way to reduce the
overall time to run the survey is to reduce the amount of time it
takes for an individual survey, the serial portion of the problem,
to complete. Similarly, with CPUs, we can add more cores that
can perform various chunks of the computation as necessary
until we reach a point where the bottleneck is the time it takes
for a specific core to finish its task. In other words, the
bottleneck in any parallel calculation is always the smaller
serial tasks that are being spread out.
Furthermore, a major hurdle with utilizing multiple cores in
Python is Python’s use of a global interpreter lock (GIL). The
GIL makes sure that a Python process can run only one
instruction at a time, regardless of the number of cores it is
currently using. This means that even though some Python
code has access to multiple cores at a time, only one core is
47. running a Python instruction at any given time. Using the
previous example of a survey, this would mean that even if we
had 100 question askers, only one person could ask a question
and listen to a response at a time. This effectively removes any
sort of benefit from having multiple question askers! While this
may seem like quite a hurdle, especially if the current trend in
computing is to have multiple computing units rather than
having faster ones, this problem can be avoided by using other
standard library tools, like multiprocessing (Chapter 9),
technologies like numpy or numexpr (Chapter 6), Cython
(Chapter 7), or distributed models of computing (Chapter 10).
NOTE
Python 3.2 also saw a major rewrite of the GIL, which made the system
much more nimble, alleviating many of the concerns around the system
for single-thread performance. Although it still locks Python into running
only one instruction at a time, the GIL now does better at switching
between those instructions and doing so with less overhead.
Memory Units
Memory units in computers are used to store bits. These could
be bits representing variables in your program or bits
representing the pixels of an image. Thus, the abstraction of a
memory unit applies to the registers in your motherboard as
well as your RAM and hard drive. The one major difference
between all of these types of memory units is the speed at
which they can read/write data. To make things more
48. complicated, the read/write speed is heavily dependent on the
way that data is being read.
For example, most memory units perform much better when
they read one large chunk of data as opposed to many small
chunks (this is referred to as sequential read versus random
data). If the data in these memory units is thought of as pages
in a large book, this means that most memory units have better
read/write speeds when going through the book page by page
rather than constantly flipping from one random page to
another. While this fact is generally true across all memory
units, the amount that this affects each type is drastically
different.
In addition to the read/write speeds, memory units also have
latency, which can be characterized as the time it takes the
device to find the data that is being used. For a spinning hard
drive, this latency can be high because the disk needs to
physically spin up to speed and the read head must move to
the right position. On the other hand, for RAM, this latency can
be quite small because everything is solid state. Here is a short
description of the various memory units that are commonly
found inside a standard workstation, in order of read/write
speeds:
Spinning hard drive
Long-term storage that persists even when the computer is
shut down. Generally has slow read/write speeds because
the disk must be physically spun and moved. Degraded
2
49. performance with random access patterns but very large
capacity (10 terabyte range).
Solid-state hard drive
Similar to a spinning hard drive, with faster read/write
speeds but smaller capacity (1 terabyte range).
RAM
Used to store application code and data (such as any
variables being used). Has fast read/write characteristics
and performs well with random access patterns, but is
generally limited in capacity (64 gigabyte range).
L1/L2 cache
Extremely fast read/write speeds. Data going to the CPU
must go through here. Very small capacity (megabytes
range).
Figure 1-2 gives a graphic representation of the differences
between these types of memory units by looking at the
characteristics of currently available consumer hardware.
A clearly visible trend is that read/write speeds and capacity
are inversely proportional—as we try to increase speed,
capacity gets reduced. Because of this, many systems
implement a tiered approach to memory: data starts in its full
state in the hard drive, part of it moves to RAM, and then a
much smaller subset moves to the L1/L2 cache. This method
of tiering enables programs to keep memory in different places
depending on access speed requirements. When trying to
optimize the memory patterns of a program, we are simply
50. optimizing which data is placed where, how it is laid out (in
order to increase the number of sequential reads), and how
many times it is moved among the various locations. In
addition, methods such as asynchronous I/O and preemptive
caching provide ways to make sure that data is always where it
needs to be without having to waste computing time—most of
these processes can happen independently, while other
calculations are being performed!
51. Figure 1-2. Characteristic values for different types of memory units (values from
February 2014)
Communications Layers
52. Finally, let’s look at how all of these fundamental blocks
communicate with each other. Many modes of communication
exist, but all are variants on a thing called a bus.
The frontside bus, for example, is the connection between the
RAM and the L1/L2 cache. It moves data that is ready to be
transformed by the processor into the staging ground to get
ready for calculation, and it moves finished calculations out.
There are other buses, too, such as the external bus that acts
as the main route from hardware devices (such as hard drives
and networking cards) to the CPU and system memory. This
external bus is generally slower than the frontside bus.
In fact, many of the benefits of the L1/L2 cache are attributable
to the faster bus. Being able to queue up data necessary for
computation in large chunks on a slow bus (from RAM to
cache) and then having it available at very fast speeds from the
cache lines (from cache to CPU) enables the CPU to do more
calculations without waiting such a long time.
Similarly, many of the drawbacks of using a GPU come from
the bus it is connected on: since the GPU is generally a
peripheral device, it communicates through the PCI bus, which
is much slower than the frontside bus. As a result, getting data
into and out of the GPU can be quite a taxing operation. The
advent of heterogeneous computing, or computing blocks that
have both a CPU and a GPU on the frontside bus, aims at
reducing the data transfer cost and making GPU computing
53. more of an available option, even when a lot of data must be
transferred.
In addition to the communication blocks within the computer,
the network can be thought of as yet another communication
block. This block, though, is much more pliable than the ones
discussed previously; a network device can be connected to a
memory device, such as a network attached storage (NAS)
device or another computing block, as in a computing node in a
cluster. However, network communications are generally much
slower than the other types of communications mentioned
previously. While the frontside bus can transfer dozens of
gigabits per second, the network is limited to the order of
several dozen megabits.
It is clear, then, that the main property of a bus is its speed:
how much data it can move in a given amount of time. This
property is given by combining two quantities: how much data
can be moved in one transfer (bus width) and how many
transfers the bus can do per second (bus frequency). It is
important to note that the data moved in one transfer is always
sequential: a chunk of data is read off of the memory and
moved to a different place. Thus, the speed of a bus is broken
into these two quantities because individually they can affect
different aspects of computation: a large bus width can help
vectorized code (or any code that sequentially reads through
memory) by making it possible to move all the relevant data in
one transfer, while, on the other hand, having a small bus width
but a very high frequency of transfers can help code that must
54. do many reads from random parts of memory. Interestingly,
one of the ways that these properties are changed by computer
designers is by the physical layout of the motherboard: when
chips are placed close to one another, the length of the
physical wires joining them is smaller, which can allow for
faster transfer speeds. In addition, the number of wires itself
dictates the width of the bus (giving real physical meaning to
the term!).
Since interfaces can be tuned to give the right performance for
a specific application, it is no surprise that there are hundreds
of types. Figure 1-3 shows the bitrates for a sampling of
common interfaces. Note that this doesn’t speak at all about
the latency of the connections, which dictates how long it takes
for a data request to be responded to (although latency is very
computer-dependent, some basic limitations are inherent to the
interfaces being used).
56. Thence passing into the Piazza del Gesù, we can visit the
CHURCH OF THE JESUITS (Il Gesu),
one of the finest in Rome. Its interior is rich in stuccoes, paintings,
and sculptures. The frescoes of the tribune, the dome, and the roof
are by Baciccio. The Chapel of S. Ignatius is very fine; the columns
and ball over the altar are composed of lapis-lazuli. Beneath the
altar, in an urn of gilt bronze, is the body of the saint. The small
circular chapel close by is rich in paintings and stained-glass
windows.
It is well worth a visit there to hear mass, vespers, or one of the
fathers preaching.
The wind generally blows in the piazza, which is thus accounted for.
One day the wind and the devil were out for a ramble; and, on
arriving at this square, the old gentleman asked the wind to stop a
moment while he went into the church. The wind is still stopping for
the devil, who has not yet come out.
The Via Cesarini, down the new Corso Vittorio Emanuele, leads to the
Piazza of S. Nicola a Cesarini. In the court of No. 56 is
THE TEMPLE OF CASTOR.
The remains show that it was a circular building. It stood near the
Flaminian Circus. (Vitruvius, iv. 7.) Four fluted tufa columns exist.
From Piazza del Gesù we proceed up Via Ara Cœli. Before us is
THE CAPITOLINE HILL.
It was originally called the Hill of Saturn (Dionysius, ii. 1), being
occupied by Romulus as a defence for the Palatine Hill (Plutarch, in
"Rom."), and was betrayed to the Sabines by Tarpeia, the daughter
57. of the commandant of the fortress (Livy, i. 11). When the Palatine
and Capitoline Hills were united into one city, and the two kings
reigned together, the name of the hill was changed and called the
Tarpeian Hill. In the 138th year after the foundation of Rome, when
Tarquin the Great was making the foundations for the great Temple
of Jupiter, they found a human head; and the oracle told them that
the spot where the head was found should become the head of the
world; and so they changed the name of the hill again, and called it
the Capitoline Hill,—from caput, a head (Livy, i. 55; Pliny, xxviii. 4).
The whole hill was the Arx or Citadel of Rome, just the same as at
Athens, Veii, Tusculum, &c. Several ancient authors agree in this.
The shape of the hill is a saddle-back,—the centre being depressed,
with an eminence at each end. The one on our left is known as the
Ara Cœli height, and the one on our right as the Caffarella height.
On the Ara Cœli height stood the great Temple of Jupiter, facing
south, and approached from the Area Capitolina (Piazza del
Campidoglio) by a flight of steps. On the opposite or Caffarella
height stood the Temple of Juno Moneta or the Mint, and the Temple
of Concord, both built by Camillus; and the Temple of Jupiter
Feretrius, founded by Romulus. Many other temples, altars, and
shrines occupied the space inside the citadel, which was approached
by three ascents upon its eastern side,—the Clivus Capitolinus, the
Pass of the Two Groves, and the Hundred Steps. The ascents upon
its western side date from 1348, when the marble stairs on our left,
leading up to the Ara Cœli, were erected out of the stairs that led up
to the Temple of Quirinus (Romulus) upon the Quirinal Hill. The
ascent to the Square was made in 1536 for the entry of Charles V.
The roadway on its right is quite recent. In forming it some remains
of the tufa walls that protected the arx on this side were found, and
can still be seen inside the iron gate.
On the balustrade at the bottom of the ascent to the Capitol are two
Egyptian lionesses. At the top of the ascent are two colossal statues
of Castor and Pollux, found in the Ghetto, and by their side are the
miscalled Trophies of Marius. They belonged to the decorations of
the Nymphæum of Alexander Severus, the picturesque ruins of
58. which are on the Esquiline Hill, and which are represented on a coin.
They were placed upon the balustrade of the Capitol, their present
site, by Pope Sixtus V. Originally they formed part of the
ornamentation of the Basilica Ulpia, and were erected in honour of
Trajan by the Apollinarian and Valerian legions. Next to the trophies
are two statues of Cæsar and Augustus Constantine; and in the
same row, on the left, the stone that marked the seventh and, on
the right, the stone that marked the first mile on the Via Appia.
In the centre of the Square is
THE EQUESTRIAN STATUE OF MARCUS AURELIUS,
the finest piece of bronze work of ancient times. It now stands upon
the Square of the Capitol, where it was erected by Michael Angelo in
1538. Before that, it stood at the Lateran, where it had been placed
in 1187, having been taken from near the Column of Phocas in the
Forum. It belongs to the canons of the Lateran, who receive yearly,
in the shape of a bouquet of flowers, a peppercorn rent for it from
the mayor of Rome. It is said that Michael Angelo on passing by
used to say, "Gee up, cammina;" and that the horse had only to
plant the raised hoof upon the ground to complete the illusion that it
was a living creature.
In front of us is the mayor's residence; on the left the Museum of
the Capitol; and on the right the halls of the town council. These
buildings were erected by Michael Angelo in 1544–1550. The
residence for the senator was first erected on the top of the ruins of
the Tabularium in 1389–1394 by Pope Boniface IX., but this gave
place to the present edifice.
The ascent from the Arch of Severus to the Square of the Capitol
was anciently the Pass of the Two Groves. At the top of the pass was
the Gate of Janus, the gate of the citadel, betrayed by Tarpeia. The
ascent from the Forum, on our right, was the Clivus Capitolinus, a
continuation of the Via Sacra. It is only at its termination that the
59. present road is on the site of the ancient slope, where some of the
pavement may still be seen. The gate which here gave access to the
arx was called the Gate of Saturn.
On the right of the old museum some steps lead up to
THE CHURCH OF ARA CŒLI.
The nave is formed by twenty-two columns, the spoils of ancient
buildings. The third one on the left has engraved upon it—
A CVBICVLO AVGVSTORVM,
showing that it came from the Palatine Hill. At the end of the nave
are two Gothic ambones with mosaic work. The altar urn of red
porphyry formerly, it is said, contained the body of Constantine's
mother. This church is rendered famous as being the place where,
on the 15th of October 1764, Gibbon "sat musing amidst the ruins of
the Capitol, and conceived the idea of writing the 'Decline and Fall of
the Roman Empire.'"
60. VIEW OF THE CAPITOL.
View larger image.
The church is the residence of the celebrated Santissimo Bambino,
carved out of a tree from the Mount of Olives, and painted by S.
Luke. This image is highly decorated with jewellery, and has a two-
horse carriage at its disposal, with coachmen and footmen, when it
pays a visit to the sick. "As thy faith, so be it unto thee." Apply at
the sacristy to see it. The floor of the church is of the kind called
opus-Alexandrinum, tesselated mosaic, and slab tombs of medieval
period. A grand ceremony is held here on Christmas day, and at the
Epiphany children recite the story of Christ.
In the left transept an isolated octagonal chapel, dedicated to S.
Helena, is said by the church authorities to stand on the site of an
altar erected by Augustus—Ara primogeniti Dei—to commemorate
the Cumæan sibyl's prophecy of the coming of the Saviour. Its
present name is traceable to this altar. Some traces of Gothic can be
seen in the walls and windows of this church, which stands on the
site of
THE TEMPLE OF JUPITER CAPITOLINUS.
"It stood upon a high rock, and was 800 feet in circuit, each side
containing near 200; the length does not exceed the width by quite
15 feet. For the temple that was built in the time of our fathers,
upon the same foundations with the first, which was consumed by
fire, is found to differ from the ancient temple in nothing but in
magnificence and the richness of the materials, having three rows of
columns in the south front, and two on each side. The body is
divided into three temples, parallel to one another, the partition walls
forming their common sides. The middle temple is dedicated to
Jupiter; and on one side stands that of Juno, and on the other that
of Minerva. And all three have but one pediment and one roof."
(Dionysius, iv. 61. See also Tacitus, "Hist." iii. 72; Livy, i. 55;
Plutarch, in "Publicola;" Tacitus, "Hist." iv. 53.)
61. TEMPLE OF JUPITER
CAPITOLINUS.
View larger image.
Four different temples have been erected on this site, and now it is
occupied by a Christian church. The first, built by Tarquinius
Superbus, and consecrated by Horatius the consul, was burned in
the civil war. The second, erected by Sylla, and consecrated by
Catulus, was destroyed under Vitellius. The third, erected by
Vespasian, was burned before it was consecrated. The fourth was
built by Domitian.
Access is now to be had to some curious vaults below the convent,
which were formerly closed by the monks. Supporting these vaults
are some remains of massive tufa walls—one piece in particular
being about 36 feet long and 8 feet high—consisting of single blocks
of stone, of which the other fragments seem to be continuations.
These appear to have been built originally as substructions, and run
parallel with the Via Marforio, and could not have been part of the
city wall, for that is within the city of the two hills. Nibby records that
tufa walls remain under the stairs leading up to the Ara Cœli Church.
We think them to be part of the foundations of the celebrated
Temple of Jupiter Capitolinus.
We may mention that among the rubbish contained in the vaults of
the convent are two slender columns of Pentelic marble. May not
these have belonged to the temple?
The strongest evidence of the
position of the Temple of Jupiter
"supremely good and great" is
pictorial. We have it represented
on the relief in the Palazzo dei
Conservatori which formed part
of the Arch of Marcus Aurelius.
That emperor is there, after a
victory, offering sacrifice upon
the Capitoline Hill; and in the
background is a representation
of the Temple of Jupiter
Capitolinus: it has three doors,
62. and the figures of Minerva, Jupiter, and Juno. This is to the
spectator's left, and faces south, as we are told the temple faced.
This relief is further corroborated by another in the Louvre, in the
background of which is likewise a representation of a temple of the
Corinthian order, facing the same way and to the left of the
spectator, and having over the door the words Iovi Capitolinus. Upon
a relief in the Capitol Museum, another building appears upon a
lower level, ornamented with pilasters, having Doric capitals. This
building corresponds with the front of the Tabularium towards the
Capitol.
To the right of the Palazzo dei Conservatori (New Museum) a road,
through a gate, leads to the German Embassy. In the garden Bunsen
found the remains of the Temple of Jupiter Feretrius, which have
lately been covered in; but a fine piece of the wall of the Temple of
Juno may yet be seen. By applying at the Embassy, permission will
be given to enter the garden.
TEMPLE OF JUPITER FERETRIUS (The Trophy-Bearer).
The first temple built in Rome by Romulus, to receive the spoils
captured from Acron, King of Cænina.
"After the procession and sacrifice, Romulus built a small temple, on
the top of the Capitoline Hill, to Jupiter, whom the Romans call
Feretrius. For the ancient traces of it still remain, of which the
longest sides are less than fifteen feet" (Dionysius, ii. 34. See Livy, i.
10).
It was enlarged A.U.C. 121 (Livy, i. 33); and was repaired by
Augustus on the advice of Atticus (Nepos. See Livy, iv. 20).
Opposite the gate leading into the garden we can look over the
parapet, down the scarped rock, to the base beneath, which is
reached from below by taking the Via Tor dei Specchi on the right,
looking towards the Capitol, and the Vicolo Rupe Tarpeia on the left.
63. TARPEIAN
ROCK.
View larger
image.
It was here that the terrible scene described in Hawthorne's
"Transformation" took place.
The road leads to the New German Archæological Institute. It was
about here that the messenger from Veii got into the citadel, and
where the Gauls tried to do the same, when the sacred geese in
Juno's temple awoke the garrison. The two bronze "geese" shown in
the Hall of the Conservators are ducks.
Passing on under the archway, turn to the left; at a little distance the
Via Monte Tarpeia turns off to the right—follow this; at the end, the
house facing us is built up against the point of the hill used for the
public executions.
THE TARPEIAN ROCK.
After the name of the hill was changed for the
last time, one part, we are told, retained the
name of the Tarpeian Rock, from being the
burial-place of Tarpeia, and the spot from which
the traitors were hurled off in sight of the people
assembled in the Forum. The house in front of
us is built upon a ledge of the rock below, and
has upon it the following inscription:—
"Hinc ad Tarpeiam sedem, et Capitolia ducit,
Aurea nunc, olim, silvestribus horrida dumis."
Virgil, Æn. viii. 347.
GREGORIUS XIII. PONT. MAX. VIAM TARPEIAM APERINT
HIER. ALTERIUS AEDILIS SECUNDO } CURABANT
PAULUS BUBALUS AEDILIS SEXTO }
ANNO DOMINI MDLXXXI.
64. "The quæstors led the man [Spurius Cassius] to the top of the
precipice that commands the Forum, and in the presence of all the
citizens threw him down from the rock. For this was the established
punishment at that time among the Romans for those who were
condemned to die"—A.U.C. 269—(Dionysius, viii. 78).
If we look back up the street we came down, the height will be seen
in the garden above us. It must be remembered that the top of the
hill has been levelled, and the valley below filled in thirty feet;
allowing for this there would have been a fall of upwards of 160 feet.
The steps on our left formed the third ancient approach to the arx,
the Centum Gradus, up which the Vitellians climbed when they took
the citadel. On the site of the garden above stood
CAMILLUS'S TEMPLES TO CONCORD AND JUNO.
The first Temple of Concord of which we have any notice was that
dedicated by Camillus, A.U.C. 388.
"When the dictator was one day sitting on the tribunal in the Forum,
the people called out to drag him from his seat; but he led off the
patricians to the senate house. Previous to his entering it he turned
towards the Capitol [this shows that the senate house was not on
the Capitol, as some would have us believe; for if so, he would not
have turned towards the Capitol before entering the senate house—
he would have already faced it], and besought the gods to put a
happy end to the present disturbances, vowing to build a temple to
Concord when the tumult should be appeased.... Next day they
assembled and voted that the temple which Camillus had vowed to
Concord should, on account of this great event, be built upon a spot
viewing from a height the Forum and place of assembly" (Plutarch,
in "Camillus"). Ovid, speaking of the same temple ("Fasti," i. 640),
says: "Fair Concord, the succeeding day places thee in a snow-white
shrine, near where elevated Moneta raises her steps on high: now
with ease wilt thou look down upon the Latin crowd. Now have the
august hands of Cæsar restored thee,"—referring to its rebuilding by
65. Tiberius, A.D. 11. From both these authors we learn that it had a
commanding prospect, and Ovid adds that it was near the Temple of
Moneta, which was likewise founded by Camillus, A.U.C. 411, as we
learn from Livy (vii. 28, and vi. 20. See Plutarch). "The site chosen
was that spot in the Citadel where the house of Manlius had stood."
The site of the Temple of Concord was on the Tarpeian Rock, at the
top of the Centum Gradus, and Camillus's Temple of Moneta was
near it.
Livy (xxvi. 23) says: "In A.U.C. 542, at the Temple of Concord, a
statue of Victory, which stood on the summit of the roof, being
struck by lightning, and shaken at its base, fell and stuck among the
ensigns of the goddess which were on the pediment." This temple,
with a statue of Victory upon the summit, is represented on a coin of
Tiberius, who restored it.
Under the wall, on our left, which supports the garden, some blocks
of tufa, in situ, are the remains of the Temple of Concord, and the
wall in the garden of the German Embassy is part of the Temple of
Juno.
Passing down the street on our right, a left half-turn will bring us to
the old entrance of
THE TABULARIUM.
(Public Record Office.)
Open every day from 10 till 3; fee, half lira.
We have now to speak of a building, the vast remains of which
impress us with the grandeur of the later republic. In the year of the
city 675 (B.C. 78) a building was erected against the Capitoline Hill,
and facing the Forum, to contain the public records, which were
engraved on bronze plates. Before that time they had been kept in
various temples.
66. "A decree was made by the senate that the records should be kept
in the Temple of Ceres with the public ædiles"—A.U.C. 306—(Livy, iii.
55).
"Treaties (such as between Pyrrhus and Rome) were then usual, and
the ædiles had them in their keeping in the Temple of Jupiter
Capitolinus, engraved on plates of copper" (Polybius, iii.).
That this was the usual way of keeping the records we learn from
the same author, who saw and copied those which "Hannibal left at
Lacinium—engraved tablets or records on copper of the events of his
stay in Italy."
"The censors went up immediately to the Temple of Liberty, where
they sealed the books of the public records, shut up the office, and
dismissed the clerks, affirming that they should do no kind of public
business until the judgment of the people was passed on them"—
A.U.C. 686—(Livy, xliii. 16).
We have no mention in classic history as to when this building was
erected, but fortunately an inscription has been handed down to us,
in which Quintus Lutatius Catulus (who dedicated the temple to
Jupiter Capitolinus) is expressly named, not only as the founder of
the Tabularium, but also of the substructions, the most difficult
portion of the whole, and which claim our fullest admiration.
Q . LVTATIVS . Q. F. Q. N. CATVLVS . COS . SVBSTRVCTIONEM . ET .
TABVLARIVM . EX . SEN . SENT . FACIENDVM . COERAVIT .
EADEMQVE . PROBAVIT .
The remains form the substructions of the present Capitol, or
senator's residence, consisting of a massive wall of Gabii stone 240
feet long and 37 feet high, supporting the portico on the side of the
Forum, which consisted of a series of arches, 23 feet by 15 feet,
ornamented with sixteen Doric columns. Below this portico or arcade
are a series of small chambers, with windows looking into the
Forum, opening out of one another, approached by a short flight of
steps, and probably used to store the records. At the back of the
67. arcade are a series of large vaulted rooms or offices. At one end a
grand flight of steps (repaired) leads up into what has been a grand
arcade on the side of the Area Capitolina: its piers now partly sustain
the modern building. At the farther end of this arcade is a flight of
steep travertine steps, sixty-seven in number, leading down into the
Forum, the exit to which has been blocked up by the Temple of
Vespasian being built against the entrance.
This building must have presented a grand front to the Forum in the
olden time, though now it only sustains the buildings of Michael
Angelo. In 1389–1394, Pope Boniface IX. first erected on the
Capitoline Hill, on the ruins of the Tabularium, a residence for the
senator and his assessors. The prospect was altered so that what
was the front became the back, and it faced on to what was
anciently the Area Capitolina, now the Piazza del Campidoglio,
instead of the Forum.
The north side wall seems to have been cut down when the present
edifice was erected, as outside the present wall are the remains of
the ancient one; thus it was somewhat longer than we now see it. In
the sort of vestibule which gives admittance to the chambers under
the portico are remains of stairs, evidently leading up to some
chambers above the portico. These were probably not very lofty, so
that the view of the temples on the hill was not shut out from the
Forum, or perhaps they only led up to the flat roof above the arcade.
These old remains have been used as a prison and as a salt store,
which latter has eaten the stone away in a curious manner. It is now
used as a museum of fragments. The arches of the portico were
filled in when the great master utilized it. Although we know an arch
is as strong as a wall, it is feared to open them, and one only has
been so treated.
Suetonius tells us: "Vespasian undertook to restore the three
thousand tablets of brass which had been destroyed in the fire which
consumed the Capitol; searching in all quarters for copies of those
curious and ancient records, in which were contained the decrees of
68. the senate almost from the building of the city, as well as the acts of
the people relative to alliances, treaties, and privileges granted to
any person" (Vespasian, viii.).
Pliny (xxxiv. 21) says: "It is upon tablets of brass that our public
enactments are engraved."
From the Tabularium a new iron stair leads up to
THE TOWER OF THE CAPITOL,
whence a fine view of Rome and its environs can be enjoyed,
standing, as it were, between ancient and medieval Rome. It is the
best position for study in the world.
From this height the huge mass of the Colosseum appears elegant
and light. The famous Seven Hills may be made out, notwithstanding
the alteration in the soil: on the left is the Quirinal, beyond that the
Viminal, and beyond that the Esquiline; to the extreme right is the
Aventine; before us is the Palatine, with the Cœlian beyond it; whilst
we occupy the Capitoline. The contemplation of the city, however,
produces the effect of a vast and solid reading of history. Each of the
great representations of the city, always and differently mistress of
the world, seems to have chosen its respective quarter—the Rome of
the kings and emperors is spread out on the Palatine, Esquiline, and
Quirinal; republican Rome occupies the Capitol and Aventine; whilst
Christian Rome, isolated and solitary, reigns on the Cœlian and
Vatican eminences.
THE SEVEN HILLS OF ROME.
The Palatine, which has ever had the preference, whether so-called
from the people Palantes, or Palatini, or from the bleating and
strolling of cattle, in Latin, balare and palare, or from Pales, the
pastoral goddess, or from the burying-place of Pallas, is disputed
amongst authors. It was on this hill that Romulus, according to
69. popular tradition, laid the foundations of the city, in a quadrangular
form. Here Romulus and Tullus Hostilius kept their courts, as did
afterwards Augustus, and all the succeeding emperors, on which
account the word Palatium came to signify a royal seat (Rosin,
"Antiq." i. 4).
The Aventine derives its name from Aventinus, an Alban king (Varro,
"De Ling. Lat." iv.), or from the river Avens (ibid.), or from Avibus,
from the birds which used to fly thither in great flocks from the Tiber
(ibid.). It was also called Murcius, from Murcia, the goddess of sleep,
who had a temple here (Sextus Pompeius, Festus). Also Collis
Dianæ, from the Temple of Diana (Martial). Likewise Remonius, from
Remus, who wished the city to be commenced here, and who was
buried here (Plutarch, in "Romulus"). This hill was added by Ancus
Martius ("Eutropius," i.).
The Capitoline, formerly Saturn, then Tarpeian, took its name from
Tarpeia, a Roman virgin, who betrayed the city to the Sabines at this
point (Plutarch, in "Romulus"). It was also called Mons Saturni and
Saturnius, in honour of Saturn, who is reported to have lived here,
and was the titular deity of this part of the city. It was afterwards
called Capitoline, from the head of a man found here when digging
the foundations of the famous Temple of Jupiter. It was added to the
city when the Sabines were permitted by Romulus to incorporate
themselves with the Romans (Dionysius).
The Quirinal was either so called from the Temple of Quirinus,
another name of Romulus, or from the Curetes, a people that
removed hither with Tatius from Cures, a Sabine city (Sextus
Pompeius, Festus). It afterwards changed its name to Caballus, from
two marble horses, each having a man holding it, which are still
standing, and were the works of Phidias and Praxiteles ("Fabricii
Roma," iii.), made to represent Alexander the Great and Bucephalus,
and presented to Nero by Tiridates, king of Armenia. Numa added
this hill to the city (Dionysius, ii.).
70. The Esquiline was anciently called Cispius and Oppius ("Fabricii
Roma," 3). The name Esquilinus was varied for the easier
pronunciation from Exquilinus, a corruption of Excubinus, ab
Excubiis, from the watch that Romulus kept there ("Propert." ii. 8). It
was taken in by Servius Tullius, who had his palace here (Livy, i. 44).
The Viminal derives its name from Vimina, signifying osiers, which
grew here in large quantities. This hill was added by Servius Tullius
(Dionysius, iv.).
The Cœlian owes its name to Cœlius or Cœles, a famous Tuscan
general, who encamped here when he came to assist the Romans
against the Sabines (Varro, "De Ling. Lat." iv.). The other names by
which it was sometimes known were Querculanus or
Querquetulanus, and Augustus: the first, on account of its growth of
oaks; and the second, because the Emperor Tiberius built on it after
a fire (Tacit. "Ann." iv.; Suet. in "Tib." xlviii.). One part was called
Cœliolus, and Minor Cœliolus ("Fabricii Roma," 3). Livy (i. 30) and
Dionysius (iii.) attribute the taking of it into the city to Tullus
Hostilius, but Strabo ("Georg." v.) to Ancus Martius.
Whilst on the subject of the hills of Rome, three others are equally
famous.
The Janiculum, or Janicularis, so called either from an old town of the
same name, said to have been built by Janus, or because Janus
dwelt and was buried here (Ovid, "F." i. 246), or because it was a
janua, a sort of gate to the Romans, whence they issued out upon
the Tuscans (Festus). Its yellow sand gave it the name of Mons
Aureus, corrupted into Montorius ("Fabricii Roma," i. 3). From an
epigram of Martial, we may observe that it is the fittest place to take
one's standing for a full prospect of the city (Martial, "Epig." iv. 64).
It is famous for the sepulchres of Numa and Statius the poet
("Fabricii Roma," i. 3), and in more recent times as the grave of
Tasso, and the spot where tradition holds that S. Peter was
executed.
71. The Vatican owes its name to the vates, or prophets, who used to
give their answers here, or from the god Vaticanus or Vagitanus
(Festus). Formerly celebrated for the Gardens and Circus of Nero,
the scene of the Christian martyrdoms, and in our time for S. Peter's
and the Vatican. It was enclosed in the time of Aurelian, but was
considered as very unhealthy (Tacitus, "H." ii. 93).
The Pincio (Collis Hortulorum, or Hortorum) took its name from the
gardens of Sallust adjoining it (Rosin, i. 2). It was afterwards called
Pincius, from the Pincii, a noble family who had their seat here
(ibid.). Aurelian first enclosed it (ibid.).
The Capitol tower is crowned by a statue of Roma; and the great
bell formerly announced, by a strange contrast, the death of the
Pope and the opening of the Carnival.
Passing up into the square, in facing the Capitol, on the right, is the
PALAZZO DEI CONSERVATORI.
(New Capitoline Museum.)
Open every day. Fee, half lira. The principal objects in the Courtyard
are, right:—
1. Statue of Julius Cæsar; the only authentic portrait of him.
2, 4, 9. Colossal fragments, found near the Basilica of Constantine.
Supposed to have belonged to the statue of Apollo brought from
Pontus by Lucullus. Square base, which contained the bones of
Agrippina the elder.
11. Lion attacking a horse. Found in the river Almo, outside Porta S.
Paolo.
12, 14. Captive Kings.
13. Large seated statue of Roma.
72. 15. Colossal bronze head of a colossal statue of Apollo, found near
the Colosseum. Reliefs of figures representing provinces; and reliefs
of military trophies, recently found in the Piazza di Pietra.
28. Statue of the Emperor Augustus.
30. Modern rostral column, with ancient inscription. (See page 26.)
STAIRCASE AND LANDING.
36. Base Capitolina, an altar dedicated to Hadrian, whose bust it
now supports, by the inspectors of the streets. On the sides are
engraved the names of the magistrates who presided over the
streets, which are named, of five of the fourteen regions into which
Rome was divided. It has afforded much useful information to
archæologists.
41. Alto-relief which formed part of the Arch of Antoninus Pius,
found in the Piazza Sciarra, which spanned the Corso, and was
destroyed in 1527.
42, 43, 44. Alto-reliefs, part of the Arch of Marcus Aurelius, which
stood at the Via della Vita, in the Corso, and was pulled down in
1665.
45. Curious bas-relief, representing Mettus Curtius, on horseback,
floundering in the marsh where is now the Forum. Found near the
Church of S. Maria Liberatrice.
49, 50. Alto-reliefs from an arch which stood in the Corso in honour
of Antoninus Pius.
At the top of the stairs on this floor are several rooms. On passing
the turnstile keep straight on. The authorities number these rooms
in the reverse way to ours.
74. PLAN OF THE PALAZZO DEI CONSERVATORI.
NEW CAPITOLINE MUSEUM.
View larger image.
First Room contains a collection of majolica from the Cini family.
Second Room.—The vault is by Caracci. On the right of the door are S.
Luke; S. Alexio, by Romanelli; the Virgin, by Andrea Allovisi, called
L'Ingegno, pupil of Perugino; S. Cecilia, by Romanelli; S. Mark. On
the left are S. John, S. Albertorn, and S. Eustachio, by Romanelli; S.
Matthew.
75. Third Room, turn left.—Frescoes of the Punic wars by Bonfigli.
Fourth Room.—Frescoes from the wars of Scipio, and tapestries from
the hospital of S. Michael. Right, the Boys of Falerii scourging their
Schoolmaster, B.C. 392 (Livy, v. 27); the Vestal Tuccia, B.C. 144
(Dionysius, ii. 69); Romulus and Remus; busts of Italian patriots.
Fifth Room.—Garibaldi Museum. Frescoes of the school of Zuccari,
representing games in the Circus Maximus, etc. There is a bust in
rosso-antico called Appius Claudius, a bronze bust of Michael Angelo,
and other busts. Two ducks in bronze are pointed out as the geese
which saved the Capitol. Between them is a curious bronze vase,
evidently a female portrait. Copy of Raphael's Holy Family.
Sixth Room.—On the wall of this room are preserved the Fasti
Consulares, dating from B.C. 481 to the end of the Republic. These
fragments were found in the Forum, and faced the podium of the
Temple-Tomb of Cæsar. The frescoes are by Benedetto Bonfigli.
Seventh Room.—Frescoes: Triumph of Marius, and Defeat of the
Cimbri, by Daniele da Volterra. Near the door is a relief, representing
the Temple at Jerusalem; and in front of it a team of oxen drawing
on a car the molten sea (1 Kings vii. 23; 2 Chron. iv. 2).
Eighth Room.—Scenes of the Roman Republic, by Lauretti.
Ninth Room.—Frescoes from the history of the kings, by Arpino.
Passing through the rooms of the Fasti, from 1540 A.D., we enter the
Hall of Busts, comprising statesmen, poets, painters, authors,
sculptors, all noted in Italian history. At the end is a monument to
Canova.
A door on the right opens into the
FIRST HALL OF BRONZES.
(For numbers, see plan.)
76. 1, 2. Cases of small bronze articles found at various times. 3. A
bronze biga, or two-horse chariot, with reliefs depicting scenes from
the circus; restored upon a wooden frame, and given by Signor A.
Castellani. 4. A bisellium, or chair of state. 8. Lectica, or sedan chair.
"These infirmities caused him [Claudius] to be carried in a close
chair, which no Roman had ever used before; and from thence have
the emperors and the rest of us consular men taken the custom of
using chairs of that sort, for neither Augustus nor Tiberius used
anything but small litters, which are still in fashion for the women"
(Dion Cassius). 9, 10. Shelves containing household utensils, &c. 11.
Fragments of columns of Bigio marble.
ROOM OF COINS.
The beautiful alabaster pavement of this room was found, as now
fixed, upon the Esquiline Hill, on Christmas eve, 1874. It formed part
of the House of the Larmæ, where the statues were found. The
coins formed part of the Campana Collection, and are of great value.
The small case of gems is worth looking into; it contains some
fragments not unlike the Portland vase, white reliefs on a blue
ground.
We now enter the new
OCTAGONAL HALL.
(The order is liable to alteration, as objects are constantly being
added.)
This museum is formed of the remains found in the excavations of
the municipality since Rome was made the capital of united Italy.
The new circular hall, designed by Signor Vespignani, presents a
light and elegant effect. Amongst the most important subjects
placed in the new hall, we may mention No. 2, the monument of
Quintus Sulpicius Maximus, found in 1870 in the Old Porta Salaria.
The inscription states that he died at the early age of thirteen years,
77. five months, and twelve days. He carried off the honours for
composing Greek verse against fifty-two competitors. The poem is
engraved on the pilasters. The subject is—The arguments used by
Jove in reproving Phœbus for intrusting his chariot to Phaeton.
Africa's deserts and the negroes' black skins are ascribed to the
careless driving of Phaeton on that occasion. No. 5. Venus. 23.
Mercury. 11. A bust of Faustina the elder. 13. A youth anointing
himself. 14 and 16. Tritons. 15. A half statue of the Emperor
Commodus as Hercules, beautifully executed in fine marble, with the
lion's skin over his head and knotted upon his chest: in his right
hand is the club. A bracket of marble, ornamented at its end with a
celestial globe, rested on the pedestal, which formed a shield, a
band running round the centre with the signs of the zodiac. This
bracket is supported by two kneeling figures, holding cornucopias
containing fruit. One is in good preservation; the fragments of the
other were also found. 17. Plotina, wife of Trajan. 18. Apollo. 19.
Bacchus, with a satyr on a leopard at his side. 21. Sarcophagus of
the Calydonian boar hunt. Polyhymnia. 24. Terpsichore. 26. A
beautiful nude statue of a young girl or nymph leaving the bath, of
Parian marble, standing with sandalled feet by a pedestal, which
supports her robe, the left hand fastening up the hair. 28, 29. Two
magistrates about to start the racers by dropping a handkerchief.
They represent L. A. A. Symmachus, prefect of Rome, A.D. 365, and
his son; and are unique. The father was found in one hundred and
eighty pieces, and the son in ninety pieces, which have been
carefully put together. 31. Colossal statue. 33. Fortune. Apollo with
the Lyre. Relief, forging the Shield of Minerva. 38, 42. Athletes
starting for the Race. 40a. A Cow. 44. Manlia Scantilla. Marsyas
bound to the tree; the finest statue in the collection, found in 1879.
48. Didia Clara. 49a. A Roman General; a striking statue. 8. The
Earth; a sitting statuette in a niche found in the Roman Cemetery. 9.
A Baccante.
In the inner circle.—A magnificent marble vase, found upon the
Esquiline, called by the Greeks a Rhyton: it is the work of Pontios, an
Athenian sculptor. A vase with figures in relief. The infant Hercules
78. found at the Cemetery of S. Lorenzo. Another vase. The Muse of
Astronomy. Exit. 74, 75. Hercules taming the Horses: part of a group
found in many fragments, and very skilfully put together. Seated
statue of a girl. 133. Minerva. 130. A statue of Silenus, which was
formerly a fountain. A youth carrying a pig for sacrifice. Cupid
playing with a tortoise. 123. Boy with a puppy. 81. Statuette of
Venus. 81a. A Sleeping Cupid. 124. A large stone shield sculptured
with the acanthus leaf. 90. Mithras slaying the Bull. 117, 105, 106.
Reliefs relating to the worship of the Persian sun-god Mithras,
recently found on the Esquiline Hill.
Crossing the Hall of Busts, by Canova's Monument, we enter the
TERRA-COTTA ROOM,
composed of remains found chiefly in the excavations in building the
new quarter of Rome upon the Esquiline Hill. The principal objects
are:—A coffin containing skulls; a large jar containing a leaden case,
in which is enclosed a beautiful alabaster urn; a large and varied
collection of Roman lamps, glass, and terra-cotta; also glass in
various forms, and for windows, pieces of fresco, &c. A door on the
left leads into the
SECOND HALL OF BRONZES.
In the centre of the first room is the celebrated bronze wolf of the
Capitol (1), thus alluded to by Virgil ("Æn." viii. 630):—
"By the wolf were laid the martial twins,
Intrepid on her swelling dugs they hung:
The foster-dam lolled out her fawning tongue:
They sucked secure, while, bending back her head,
She licked their tender limbs, and formed them as they fed."
Cicero (in "Catiline" iii. 8), mentions this object as a small gilt figure
of Romulus sucking the teat of a wolf, which was struck by lightning,
79. Welcome to our website – the perfect destination for book lovers and
knowledge seekers. We believe that every book holds a new world,
offering opportunities for learning, discovery, and personal growth.
That’s why we are dedicated to bringing you a diverse collection of
books, ranging from classic literature and specialized publications to
self-development guides and children's books.
More than just a book-buying platform, we strive to be a bridge
connecting you with timeless cultural and intellectual values. With an
elegant, user-friendly interface and a smart search system, you can
quickly find the books that best suit your interests. Additionally,
our special promotions and home delivery services help you save time
and fully enjoy the joy of reading.
Join us on a journey of knowledge exploration, passion nurturing, and
personal growth every day!
ebookbell.com