Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
3e41f3ca
Commit
3e41f3ca
authored
Aug 07, 2019
by
Sergey Fedoseev
Committed by
Inada Naoki
Aug 07, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
bpo-34488: optimize BytesIO.writelines() (GH-8904)
Avoid the creation of unused int object for each line.
parent
3a5c433f
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
61 additions
and
36 deletions
+61
-36
Misc/NEWS.d/next/Library/2019-08-06-21-30-58.bpo-34488.OqxVo8.rst
...S.d/next/Library/2019-08-06-21-30-58.bpo-34488.OqxVo8.rst
+2
-0
Modules/_io/bytesio.c
Modules/_io/bytesio.c
+59
-36
No files found.
Misc/NEWS.d/next/Library/2019-08-06-21-30-58.bpo-34488.OqxVo8.rst
0 → 100644
View file @
3e41f3ca
:meth:`writelines` method of :class:`io.BytesIO` is now slightly faster
when many small lines are passed. Patch by Sergey Fedoseev.
Modules/_io/bytesio.c
View file @
3e41f3ca
...
...
@@ -31,17 +31,34 @@ typedef struct {
* exports > 0. Py_REFCNT(buf) == 1, any modifications are forbidden.
*/
static
int
check_closed
(
bytesio
*
self
)
{
if
(
self
->
buf
==
NULL
)
{
PyErr_SetString
(
PyExc_ValueError
,
"I/O operation on closed file."
);
return
1
;
}
return
0
;
}
static
int
check_exports
(
bytesio
*
self
)
{
if
(
self
->
exports
>
0
)
{
PyErr_SetString
(
PyExc_BufferError
,
"Existing exports of data: object cannot be re-sized"
);
return
1
;
}
return
0
;
}
#define CHECK_CLOSED(self) \
if ((self)->buf == NULL) { \
PyErr_SetString(PyExc_ValueError, \
"I/O operation on closed file."); \
if (check_closed(self)) { \
return NULL; \
}
#define CHECK_EXPORTS(self) \
if ((self)->exports > 0) { \
PyErr_SetString(PyExc_BufferError, \
"Existing exports of data: object cannot be re-sized"); \
if (check_exports(self)) { \
return NULL; \
}
...
...
@@ -156,23 +173,41 @@ resize_buffer(bytesio *self, size_t size)
}
/* Internal routine for writing a string of bytes to the buffer of a BytesIO
object. Returns the number of bytes written, or -1 on error. */
static
Py_ssize_t
write_bytes
(
bytesio
*
self
,
const
char
*
bytes
,
Py_ssize_t
len
)
object. Returns the number of bytes written, or -1 on error.
Inlining is disabled because it's significantly decreases performance
of writelines() in PGO build. */
_Py_NO_INLINE
static
Py_ssize_t
write_bytes
(
bytesio
*
self
,
PyObject
*
b
)
{
size_t
endpos
;
assert
(
self
->
buf
!=
NULL
);
assert
(
self
->
pos
>=
0
);
assert
(
len
>=
0
);
if
(
check_closed
(
self
))
{
return
-
1
;
}
if
(
check_exports
(
self
))
{
return
-
1
;
}
endpos
=
(
size_t
)
self
->
pos
+
len
;
Py_buffer
buf
;
if
(
PyObject_GetBuffer
(
b
,
&
buf
,
PyBUF_CONTIG_RO
)
<
0
)
{
return
-
1
;
}
Py_ssize_t
len
=
buf
.
len
;
if
(
len
==
0
)
{
goto
done
;
}
assert
(
self
->
pos
>=
0
);
size_t
endpos
=
(
size_t
)
self
->
pos
+
len
;
if
(
endpos
>
(
size_t
)
PyBytes_GET_SIZE
(
self
->
buf
))
{
if
(
resize_buffer
(
self
,
endpos
)
<
0
)
return
-
1
;
if
(
resize_buffer
(
self
,
endpos
)
<
0
)
{
len
=
-
1
;
goto
done
;
}
}
else
if
(
SHARED_BUF
(
self
))
{
if
(
unshare_buffer
(
self
,
Py_MAX
(
endpos
,
(
size_t
)
self
->
string_size
))
<
0
)
return
-
1
;
if
(
unshare_buffer
(
self
,
Py_MAX
(
endpos
,
(
size_t
)
self
->
string_size
))
<
0
)
{
len
=
-
1
;
goto
done
;
}
}
if
(
self
->
pos
>
self
->
string_size
)
{
...
...
@@ -190,7 +225,7 @@ write_bytes(bytesio *self, const char *bytes, Py_ssize_t len)
/* Copy the data to the internal buffer, overwriting some of the existing
data if self->pos < self->string_size. */
memcpy
(
PyBytes_AS_STRING
(
self
->
buf
)
+
self
->
pos
,
b
ytes
,
len
);
memcpy
(
PyBytes_AS_STRING
(
self
->
buf
)
+
self
->
pos
,
b
uf
.
buf
,
len
);
self
->
pos
=
endpos
;
/* Set the new length of the internal string if it has changed. */
...
...
@@ -198,6 +233,8 @@ write_bytes(bytesio *self, const char *bytes, Py_ssize_t len)
self
->
string_size
=
endpos
;
}
done:
PyBuffer_Release
(
&
buf
);
return
len
;
}
...
...
@@ -669,19 +706,7 @@ static PyObject *
_io_BytesIO_write
(
bytesio
*
self
,
PyObject
*
b
)
/*[clinic end generated code: output=53316d99800a0b95 input=f5ec7c8c64ed720a]*/
{
Py_ssize_t
n
=
0
;
Py_buffer
buf
;
CHECK_CLOSED
(
self
);
CHECK_EXPORTS
(
self
);
if
(
PyObject_GetBuffer
(
b
,
&
buf
,
PyBUF_CONTIG_RO
)
<
0
)
return
NULL
;
if
(
buf
.
len
!=
0
)
n
=
write_bytes
(
self
,
buf
.
buf
,
buf
.
len
);
PyBuffer_Release
(
&
buf
);
Py_ssize_t
n
=
write_bytes
(
self
,
b
);
return
n
>=
0
?
PyLong_FromSsize_t
(
n
)
:
NULL
;
}
...
...
@@ -702,7 +727,6 @@ _io_BytesIO_writelines(bytesio *self, PyObject *lines)
/*[clinic end generated code: output=7f33aa3271c91752 input=e972539176fc8fc1]*/
{
PyObject
*
it
,
*
item
;
PyObject
*
ret
;
CHECK_CLOSED
(
self
);
...
...
@@ -711,13 +735,12 @@ _io_BytesIO_writelines(bytesio *self, PyObject *lines)
return
NULL
;
while
((
item
=
PyIter_Next
(
it
))
!=
NULL
)
{
ret
=
_io_BytesIO_write
(
self
,
item
);
Py_ssize_t
ret
=
write_bytes
(
self
,
item
);
Py_DECREF
(
item
);
if
(
ret
==
NULL
)
{
if
(
ret
<
0
)
{
Py_DECREF
(
it
);
return
NULL
;
}
Py_DECREF
(
ret
);
}
Py_DECREF
(
it
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment