Skip to content

Commit f53ddc6

Browse files
committed
Merge branch 'py2n3'
Clode cleanup and performance regression fixes in py3
2 parents 1af4b42 + 948a927 commit f53ddc6

12 files changed

Lines changed: 136 additions & 122 deletions

File tree

.travis.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
language: python
22
python:
3+
# These versions are unsupported by travis, even though smmap claims to still support these outdated versions
4+
# - 2.4
5+
# - 2.5
36
- 2.6
47
- 2.7
58
- 3.3

README.md

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,27 +25,21 @@ For performance critical 64 bit applications, a simplified version of memory map
2525

2626
## Prerequisites
2727

28-
* Python 2.4, 2.5 or 2.6
28+
* Python 2.4, 2.5, 2.6, 2.7 or 3.3
2929
* OSX, Windows or Linux
3030

3131
The package was tested on all of the previously mentioned configurations.
3232

33-
34-
3533
## Limitations
3634

3735
* The memory access is read-only by design.
3836
* In python below 2.6, memory maps will be created in compatibility mode which works, but creates inefficient memory mappings as they always start at offset 0.
39-
* It wasn't tested on python 2.7 and 3.x.
40-
4137

4238
## Installing smmap
4339

44-
Its easiest to install smmap using the *easy_install* or *pip* program, which is part of the [setuptools](http://peak.telecommunity.com/DevCenter/setuptools) or [pip](http://www.pip-installer.org/en/latest) respectively:
40+
Its easiest to install smmap using the [pip](http://www.pip-installer.org/en/latest) program:
4541

4642
```bash
47-
$ easy_install smmap
48-
# or
4943
$ pip install smmap
5044
```
5145

@@ -80,7 +74,6 @@ Issues can be filed on github:
8074
* https://github.com/Byron/smmap/issues
8175

8276

83-
8477
## License Information
8578

8679
*smmap* is licensed under the New BSD License.

doc/source/changes.rst

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,16 @@
22
Changelog
33
#########
44

5+
**********
6+
v0.8.3
7+
**********
8+
- Cleaned up code and assured it works sufficiently well with python 3
9+
510
**********
611
v0.8.1
712
**********
813
- A single bugfix
914

10-
1115
**********
1216
v0.8.0
1317
**********

doc/source/intro.rst

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ For performance critical 64 bit applications, a simplified version of memory map
2222
#############
2323
Prerequisites
2424
#############
25-
* Python 2.4, 2.5 or 2.6
25+
* Python 2.4, 2.5, 2.6, 2.7 or 3.3
2626
* OSX, Windows or Linux
2727

2828
The package was tested on all of the previously mentioned configurations.
@@ -32,15 +32,12 @@ Limitations
3232
###########
3333
* The memory access is read-only by design.
3434
* In python below 2.6, memory maps will be created in compatibility mode which works, but creates inefficient memory mappings as they always start at offset 0.
35-
* It wasn't tested on python 2.7 and 3.x.
3635

3736
################
3837
Installing smmap
3938
################
40-
Its easiest to install smmap using the *easy_install* or *pip* program, which is part of the `setuptools`_ or `pip`_ respectively::
39+
Its easiest to install smmap using the *pip* program::
4140
42-
$ easy_install smmap
43-
# or
4441
$ pip install smmap
4542
4643
As the command will install smmap in your respective python distribution, you will most likely need root permissions to authorize the required changes.
@@ -75,5 +72,4 @@ License Information
7572
###################
7673
*smmap* is licensed under the New BSD License.
7774

78-
.. _setuptools: http://peak.telecommunity.com/DevCenter/setuptools
7975
.. _pip: http://www.pip-installer.org/en/latest/

setup.py

100644100755
Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@
1010

1111
import smmap
1212

13-
if os.path.exists("README.rst"):
14-
long_description = codecs.open('README.rst', "r", "utf-8").read()
13+
if os.path.exists("README.md"):
14+
long_description = codecs.open('README.md', "r", "utf-8").read()
1515
else:
16-
long_description = "See http://github.com/nvie/smmap/tree/master"
16+
long_description = "See http://github.com/Byron/smmap"
1717

1818
setup(
1919
name="smmap",
@@ -32,8 +32,8 @@
3232
#"Development Status :: 1 - Planning",
3333
#"Development Status :: 2 - Pre-Alpha",
3434
#"Development Status :: 3 - Alpha",
35-
"Development Status :: 4 - Beta",
36-
#"Development Status :: 5 - Production/Stable",
35+
# "Development Status :: 4 - Beta",
36+
"Development Status :: 5 - Production/Stable",
3737
#"Development Status :: 6 - Mature",
3838
#"Development Status :: 7 - Inactive",
3939
"Environment :: Console",
@@ -52,4 +52,6 @@
5252
"Programming Language :: Python :: 3.4",
5353
],
5454
long_description=long_description,
55+
tests_require=('nose', 'nosexcover'),
56+
test_suite='nose.collector'
5557
)

smmap/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
__author__ = "Sebastian Thiel"
44
__contact__ = "byronimo@gmail.com"
55
__homepage__ = "https://github.com/Byron/smmap"
6-
version_info = (0, 8, 2)
6+
version_info = (0, 8, 3)
77
__version__ = '.'.join(str(i) for i in version_info)
88

99
# make everything available in root package for convenience

smmap/buf.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
"""Module with a simple buffer implementation using the memory manager"""
2-
from .mman import WindowCursor
3-
42
import sys
53

64
__all__ = ["SlidingWindowMapBuffer"]
@@ -79,18 +77,18 @@ def __getslice__(self, i, j):
7977
else:
8078
l = j-i # total length
8179
ofs = i
82-
# Keeping tokens in a list could possible be faster, but the list
83-
# overhead outweighs the benefits (tested) !
84-
md = bytes()
80+
# It's fastest to keep tokens and join later, especially in py3, which was 7 times slower
81+
# in the previous iteration of this code
82+
md = list()
8583
while l:
8684
c.use_region(ofs, l)
8785
assert c.is_valid()
8886
d = c.buffer()[:l]
8987
ofs += len(d)
9088
l -= len(d)
91-
md += d
89+
md.append(d)
9290
#END while there are bytes to read
93-
return md
91+
return bytes().join(md)
9492
# END fast or slow path
9593
#{ Interface
9694

smmap/mman.py

Lines changed: 20 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
"""Module containing a memory memory manager which provides a sliding window on a number of memory mapped files"""
22
from .util import (
3-
MapWindow,
4-
MapRegion,
5-
MapRegionList,
6-
is_64_bit,
7-
align_to_mmap,
8-
string_types,
9-
buffer,
10-
)
3+
MapWindow,
4+
MapRegion,
5+
MapRegionList,
6+
is_64_bit,
7+
string_types,
8+
buffer,
9+
)
1110

1211
from weakref import ref
1312
import sys
@@ -102,7 +101,7 @@ def use_region(self, offset = 0, size = 0, flags = 0):
102101
:param flags: additional flags to be given to os.open in case a file handle is initially opened
103102
for mapping. Has no effect if a region can actually be reused.
104103
:return: this instance - it should be queried for whether it points to a valid memory region.
105-
This is not the case if the mapping failed becaues we reached the end of the file
104+
This is not the case if the mapping failed because we reached the end of the file
106105
107106
**Note:**: The size actually mapped may be smaller than the given size. If that is the case,
108107
either the file has reached its end, or the map was created between two existing regions"""
@@ -138,7 +137,7 @@ def unuse_region(self):
138137
"""Unuse the ucrrent region. Does nothing if we have no current region
139138
140139
**Note:** the cursor unuses the region automatically upon destruction. It is recommended
141-
to unuse the region once you are done reading from it in persistent cursors as it
140+
to un-use the region once you are done reading from it in persistent cursors as it
142141
helps to free up resource more quickly"""
143142
self._region = None
144143
# note: should reset ofs and size, but we spare that for performance. Its not
@@ -204,7 +203,7 @@ def file_size(self):
204203
return self._rlist.file_size()
205204

206205
def path_or_fd(self):
207-
""":return: path or file decriptor of the underlying mapped file"""
206+
""":return: path or file descriptor of the underlying mapped file"""
208207
return self._rlist.path_or_fd()
209208

210209
def path(self):
@@ -238,12 +237,12 @@ class StaticWindowMapManager(object):
238237
These clients would have to use a SlidingWindowMapBuffer to hide this fact.
239238
240239
This type will always use a maximum window size, and optimize certain methods to
241-
acomodate this fact"""
240+
accommodate this fact"""
242241

243242
__slots__ = [
244243
'_fdict', # mapping of path -> StorageHelper (of some kind
245244
'_window_size', # maximum size of a window
246-
'_max_memory_size', # maximum amount ofmemory we may allocate
245+
'_max_memory_size', # maximum amount of memory we may allocate
247246
'_max_handle_count', # maximum amount of handles to keep open
248247
'_memory_size', # currently allocated memory size
249248
'_handle_count', # amount of currently allocated file handles
@@ -261,14 +260,14 @@ class StaticWindowMapManager(object):
261260
def __init__(self, window_size = 0, max_memory_size = 0, max_open_handles = sys.maxsize):
262261
"""initialize the manager with the given parameters.
263262
:param window_size: if -1, a default window size will be chosen depending on
264-
the operating system's architechture. It will internally be quantified to a multiple of the page size
263+
the operating system's architecture. It will internally be quantified to a multiple of the page size
265264
If 0, the window may have any size, which basically results in mapping the whole file at one
266265
:param max_memory_size: maximum amount of memory we may map at once before releasing mapped regions.
267-
If 0, a viable default iwll be set dependning on the system's architecture.
268-
It is a soft limit that is tried to be kept, but nothing bad happens if we have to overallocate
269-
:param max_open_handles: if not maxin, limit the amount of open file handles to the given number.
270-
Otherwise the amount is only limited by the system iteself. If a system or soft limit is hit,
271-
the manager will free as many handles as posisble"""
266+
If 0, a viable default will be set depending on the system's architecture.
267+
It is a soft limit that is tried to be kept, but nothing bad happens if we have to over-allocate
268+
:param max_open_handles: if not maxint, limit the amount of open file handles to the given number.
269+
Otherwise the amount is only limited by the system itself. If a system or soft limit is hit,
270+
the manager will free as many handles as possible"""
272271
self._fdict = dict()
273272
self._window_size = window_size
274273
self._max_memory_size = max_memory_size
@@ -277,15 +276,15 @@ def __init__(self, window_size = 0, max_memory_size = 0, max_open_handles = sys.
277276
self._handle_count = 0
278277

279278
if window_size < 0:
280-
coeff = 32
279+
coeff = 64
281280
if is_64_bit():
282281
coeff = 1024
283282
#END handle arch
284283
self._window_size = coeff * self._MB_in_bytes
285284
# END handle max window size
286285

287286
if max_memory_size == 0:
288-
coeff = 512
287+
coeff = 1024
289288
if is_64_bit():
290289
coeff = 8192
291290
#END handle arch
@@ -351,8 +350,6 @@ def _obtain_region(self, a, offset, size, flags, is_recursive):
351350
# As many more operations are likely to fail in that condition (
352351
# like reading a file from disk, etc) we free up as much as possible
353352
# As this invalidates our insert position, we have to recurse here
354-
# NOTE: The c++ version uses a linked list to curcumvent this, but
355-
# using that in python is probably too slow anyway
356353
if is_recursive:
357354
# we already tried this, and still have no success in obtaining
358355
# a mapping. This is an exception, so we propagate it
@@ -563,8 +560,6 @@ def _obtain_region(self, a, offset, size, flags, is_recursive):
563560
# As many more operations are likely to fail in that condition (
564561
# like reading a file from disk, etc) we free up as much as possible
565562
# As this invalidates our insert position, we have to recurse here
566-
# NOTE: The c++ version uses a linked list to curcumvent this, but
567-
# using that in python is probably too slow anyway
568563
if is_recursive:
569564
# we already tried this, and still have no success in obtaining
570565
# a mapping. This is an exception, so we propagate it

0 commit comments

Comments
 (0)