Найти - Пользователи
Полная версия: Ссылка/псевдоним объекта?
Начало » Python для экспертов » Ссылка/псевдоним объекта?
1 2 3
PyCraft
Тест показал, что классы работают быстрее списков.
Тест выполнялся несколько раз, позиции блоков кода каждый раз менялись местами!
Как оказалось последовательность выполнения влияет на результат
Сравнивались лучшие результаты для первого по исполнению блока кода и худшие для второго
Лушее время:
class=11.28 spisok=12.78
Худшее время:
class=19.39 spisok=22.71

import time

class SockBuff:
def __init__(self,buff=''):
self.buff=buff

if __name__=="__main__":
m = 100
s = 'lbahbvlahsvbasbvbvhvblsvb'

List2 = {}
t = time.time()
for i in range(0,m):
List2[`i`]=[s]
for j in range(0,i):
o = List2[`j`]
for k in range(0,m):
o[0] += s
dt = time.time()-t
print "spisok=",dt

del List2
time.sleep(20)

List1 = {}
t = time.time()
for i in range(0,m):
List1[`i`]=SockBuff(s)
for j in range(0,i):
o = List1[`j`]
for k in range(0,m):
o.buff += s
dt = time.time()-t
print "class=",dt
PyCraft
Daevaorn
Только это не спасет:
Для цели закачки из сокета в буфер, с проверкой начала и конца сообщения по протоколу, после каждого селекта/ресива, ни StringIO, ни свой список, ни классы не спасут. Всё равно на каждом цикле нужно проверять суммарный массив, а для этого его нужно объединить. Искомый контекст может находиться по частям в двух субстроках. Таким образом, никакой выгоды не будет.
Нужен именно способ работы через указатели - как в C или по крайней мере возможность изменять содержимое заранее выделенного байтового массива

….

Однако сStringIO (реализация на C) нас спасёт. По тесту работает ~ в 4 раза быстрее StringIO и ~ в 40 раз быстрее строк.
Хотя конечно и там не самый эффективный алгоритм. Он же не знает как лучше и сколько аллоцировать при каждом вызове write(s).

Самый эффективный нужно самому на С писать и добавлять в качестве модуля.
bialix
PyCraft
Не нашел в документации как делать сылки на объекты, чтобы сами объекты при этом не копировались в новую переменную.
В Питоне все имена являются ссылками на объекты и никакого копирования кроме явного никогда не производится.
bialix
для байтовых массивов существует модуль array. однако мысль о том, что нужный специфический тип данных нужно писать на Си, – правильная.
PyCraft
Daevaorn
buf = StringIO( “\0” * buf_size ) buf.seek(0)
Заливка нулями при создании или в процессе перезаписи тормозит процесс. Проверено в разных вариантах.

Выводы не утешительные…

Вот результаты нового теста
1) class o.buff = 0.0469999313354
2) spisok = 0.047000169754
3) StringIO питон = 0.219000101089
4)cStringIO без заливки = 0.108999967575
5)cStringIO с заливкой = 0.140000104904

Вот сам тест (имитация конечно)
import time, StringIO, cStringIO

class SockBuff:
def __init__(self,buff=''):
self.buff=buff

if __name__=="__main__":
n = 2 #Среднее количество подкачек пакетов
m = 5000 #Количество сокетов
s = 'x' * 1020 #пакет данных
o = 'Объект'
son = 10 #проспаться 10 секунд для очистки памяти
buf_size = 1024 #размер пакета
max_buf_size = buf_size * n #размер буфера для сборки пакетов

List5 = {}
t = time.time()
#создание объектов
for i in range(0,m):
o=cStringIO.StringIO()
o.write("\0" * max_buf_size)
o.seek(0)
List5[`i`]=o
#чтение данных
for j in range(0,n):
for k in range(0,m):
o = List5[`k`]
o.write(s)
v=o.getvalue()
if len(v)>=buf_size:
x=v[:buf_size]
o.seek(0)
o.write(v[buf_size:])
dt = time.time()-t
print "5)cStringIO=",dt
del List5
time.sleep(son)

List4 = {}
t = time.time()
for i in range(0,m):
List4[`i`]=cStringIO.StringIO()
for j in range(0,n):
for k in range(0,m):
o = List4[`k`]
o.write(s)
v=o.getvalue()
if len(v)>=buf_size:
x=v[:buf_size]
o.seek(0)
o.write(v[buf_size:])
dt = time.time()-t
print "4)cStringIO=",dt
del List4
time.sleep(son)

List3 = {}
t = time.time()
for i in range(0,m):
List3[`i`]=StringIO.StringIO()
for j in range(0,n):
for k in range(0,m):
o = List3[`k`]
o.write(s)
v=o.getvalue()
if len(v)>=buf_size:
x=v[:buf_size]
o.seek(0)
o.write(v[buf_size:])
dt = time.time()-t
print "3) StringIO=",dt
del List3
time.sleep(son)

List2 = {}
t = time.time()
for i in range(0,m):
List2[`i`]=['']
for j in range(0,n):
for k in range(0,m):
o = List2[`k`]
o[0]+=s
if len(o[0])>=buf_size:
x=o[0][:buf_size]
o[0]=o[0][buf_size:]
dt = time.time()-t
print "2) spisok =",dt
del List2
time.sleep(son)

List1 = {}
t = time.time()
for i in range(0,m):
List1[`i`]=SockBuff()
for j in range(0,n):
for k in range(0,m):
o = List1[`k`]
o.buff+=s
if len(o.buff)>=buf_size:
x=o.buff[:buf_size]
o.buff=o.buff[buf_size:]
dt = time.time()-t
print "1) class =",dt
del List1
time.sleep(son)
PyCraft
bialix
В Питоне все имена являются ссылками на объекты и никакого копирования кроме явного никогда не производится.
оператор присваивания = работает по разному для разных типов объектов
Немутабельные (строки, числа) объекты всегда копируются - “семантика компирования”
Мутабельные объекты (списки, словари, классы) присваиваются по ссылке - “семантика указателей”
Для кортежей работает “семантика указателей” но они немутабельны, т.е. их нельзя изменить.

Меня интересуют строки и байтовые массивы, а также способы ускорения работы с ними.
hellt
PyCraft
bialix
В Питоне все имена являются ссылками на объекты и никакого копирования кроме явного никогда не производится.
оператор присваивания = работает по разному для разных типов объектов
Немутабельные (строки, числа) объекты всегда копируются - “семантика компирования”
Мутабельные объекты (списки, словари, классы) присваиваются по ссылке - “семантика указателей”
Для кортежей работает “семантика указателей” но они немутабельны, т.е. их нельзя изменить.

Меня интересуют строки и байтовые массивы, а также способы ускорения работы с ними.
its called shared reference
a = 23 # not mutable в памяти создается объект 23 и а указывает на этот объект в памяти

b = a # теперь b ссылается на область памяти в которой лежит число 23

a = 0 # создается новый объект в памяти и а теперь ссылается на него. b по прежнему ссылается на объект 23



IDLE 1.2.2
>>> a = 23
>>> b = a
>>> print “0x%X” % id(a)
0xA65650
>>> print “0x%X” % id(b)
0xA65650
>>>
PyCraft
hellt
its called shared reference
a = 23 # not mutable в памяти создается объект 23 и а указывает на этот объект в памяти

b = a # теперь b ссылается на область памяти в которой лежит число 23

a = 0 # создается новый объект в памяти и а теперь ссылается на него. b по прежнему ссылается на объект 23

Код: :python:

IDLE 1.2.2
>>> a = 23
>>> b = a
>>> print “0x%X” % id(a)
0xA65650
>>> print “0x%X” % id(b)
0xA65650
>>>
Это, ровным счетом, ни о чем не говорит, точнее бесполезно. Мы же не можем с этой областью памяти напрямую работать.
А питон работает по своей логике.

a=1
b=a
b += 1
print a
1
print b
2

a=1
b=a
a += 1
print b
1
print a
2

и никакой пользы от ссылки b в обоих случаях мы не получаем.
PyCraft
bialix
для байтовых массивов существует модуль array.
А как с ним работать? там нет функции вставки без сдвига вправо, длина массива какая-то ненадежная.
Пример можешь показать?

1) создать массив элементов типа Т, начальный размер массива N, заполнен 0
2) довавить в массив строку (желательно при этом не переаллоцировать память)
3) определить длину массива (но не буфера в памяти, т.к. боюсь он может отличаться от реальной длины)
4) скопировать первые M элементов в переменную
5) часть массива начиная с позиции M до конца сдвинуть в начало (желательно опять же не переаллоцировать память)

в общем, аналогично приведенному тесту.
Александр Кошелев
PyCraft
1) class o.buff = 0.0469999313354
2) spisok = 0.047000169754
3) StringIO питон = 0.219000101089
4)cStringIO без заливки = 0.108999967575
5)cStringIO с заливкой = 0.140000104904
Ага медлено. Но видимо StringIO не для этой задачи
PyCraft
Это, ровным счетом, ни о чем не говорит, точнее бесполезно.
Это говорит о том что в питоне везде ссылки(через COW), и ваш прошлый тезис неправилен.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB