Что сообщения - Вы добирающийся путем выполнения после команды:
dmesg | tail
после того замораживания?
Также удостоверьтесь, что Ваш xorg.conf делает существует, в противном случае создайте один (например. sudo Xorg -configure
) или настройте его путем проигрывания со следующими опциями (в разделе Device):
Option "UseEDID" "False"
Option "IgnoreEDID" "1"
Modes "1152X864" "1024X768" "800x600"
Если это не помогает, попытайтесь отредактировать Ваш: файл/etc/default/grub и изменение (или добавляют), следующая строка:
GRUB_CMDLINE_LINUX_DEFAULT="nomodeset"
Если выше решения не помогает, то попытайтесь обновить свой дистрибутив до последней версии:
sudo apt-get update && sudo apt-get upgrade && sudo apt-get dist-upgrade
перезапустите свою машину и проверку, если она решена.
См. некоторые следующие статьи для некоторого руководства:
http://www.thinkwiki.org/wiki/Intel_Graphics_Media_Accelerator_X3100
Вероятно, полезным средством тестирования производительности оболочки является многократное выполнение множества очень маленьких простых оценок. Я думаю, что важно не просто зацикливать, но и перебирать ввод , потому что оболочка должна читать <& 0
.
Я думал, что это дополнит тесты @cuonglm, уже опубликованные , потому что они демонстрируют производительность одного процесса оболочки после вызова, в отличие от его, который демонстрирует, насколько быстро загружается процесс оболочки при вызове. Таким образом, мы закрываем обе стороны медали.
Вот функция для упрощения демонстрации:
sh_bench() ( #dont copy+paste comments
o=-c sh=$(command -v "$1") ; shift #get shell $PATH; toss $1
[ -z "${sh##*busybox}" ] && o='ash -c' #cause its weird
set -- "$sh" $o "'$(cat <&3)'" -- "$@" #$@ = invoke $shell
time env - "$sh" $o "while echo; do echo; done|$*" #time (env - sh|sh) AC/DC
) 3<<-\SCRIPT
#Everything from here down is run by the different shells
i="${2:-1}" l="${1:-100}" d="${3:-
}"; set -- "\$((n=\$n\${n:++\$i}))\$d" #prep loop; prep eval
set -- $1$1$1$1$1$1$1$1$1$1 #yup
while read m #iterate on input
do [ $(($i*50+${n:=-$i})) -gt "$(($l-$i))" ] || #eval ok?
eval echo -n \""$1$1$1$1$1"\" #yay!
[ $((n=$i+$n)) -gt "$(($l-$i))" ] && #end game?
echo "$n" && exit #and EXIT
echo -n "$n$d" #damn - maybe next time
done #done
#END
SCRIPT #end heredoc
Она либо увеличивает значение переменной один раз при чтении новой строки, либо, в качестве небольшой оптимизации, если это возможно, увеличивает значение 50 раз при чтении новой строки. Каждый раз, когда переменная увеличивается, она выводится на stdout
. Он во многом похож на своего рода seq
cross nl
.
И чтобы прояснить, что он делает - вот некоторые усеченные set -x;
выходные данные после его вставки непосредственно перед временем
в приведенной выше функции:
time env - /usr/bin/busybox ash -c '
while echo; do echo; done |
/usr/bin/busybox ash -c '"'$(
cat <&3
)'"' -- 20 5 busybox'
Итак, каждый сначала вызывается оболочка, например:
env - $shell -c "while echo; do echo; done |..."
... для генерации входных данных, которые ей нужно будет перебрать, когда она читает в 3 << \ SCRIPT
- или когда делает cat
, так или иначе. А с другой стороны этого | канала
он снова вызывает себя, например:
"...| $shell -c '$(cat <<\SCRIPT)' -- $args"
Итак, помимо первоначального вызова env
(потому что cat
фактически вызывается в предыдущей строке) ; никакие другие процессы не вызываются с момента его вызова до его завершения. По крайней мере, я надеюсь, что это правда.
Я должен сделать несколько замечаний по переносимости.
posh
не любит $ ((n = n + 1))
и настаивает на $ ((n = $ n + 1))
mksh
в большинстве случаев не имеет встроенной функции printf
. В более ранних тестах он сильно отставал - он вызывал / usr / bin / printf
при каждом запуске. Следовательно, echo -n
выше.
может быть, больше, насколько я помню ...
for sh in dash busybox posh ksh mksh zsh bash
do sh_bench $sh 20 5 $sh 2>/dev/null
sh_bench $sh 500000 | wc -l
echo ; done
Вот и все сразу ...
0dash5dash10dash15dash20
real 0m0.909s
user 0m0.897s
sys 0m0.070s
500001
0busybox5busybox10busybox15busybox20
real 0m1.809s
user 0m1.787s
sys 0m0.107s
500001
0posh5posh10posh15posh20
real 0m2.010s
user 0m2.060s
sys 0m0.067s
500001
0ksh5ksh10ksh15ksh20
real 0m2.019s
user 0m1.970s
sys 0m0.047s
500001
0mksh5mksh10mksh15mksh20
real 0m2.287s
user 0m2.340s
sys 0m0.073s
500001
0zsh5zsh10zsh15zsh20
real 0m2.648s
user 0m2.223s
sys 0m0.423s
500001
0bash5bash10bash15bash20
real 0m3.966s
user 0m3.907s
sys 0m0.213s
500001
Тем не менее, это довольно произвольный тест, но он проверяет ввод на чтение, арифметическую оценку и расширение переменных. Может быть, не исчерпывающе, но, возможно, близко к этому.
РЕДАКТИРОВАТЬ Тереза и Джуниор : @mikeserv и я провели много других тестов (подробности см. В в нашем чате ), и мы обнаружили, что результаты можно резюмировать следующим образом:
grep
, sed
, sort
и т. Д., У которых не так много функций, как у обычно используемых утилит GNU, но они могут выполнять столько же работы. Давайте сделаем тест.
С помощью bash
:
$ strace -cf bash -c 'for i in $(seq 1 1000); do bash -c ":"; done'
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
99.12 0.376044 188 2004 1002 wait4
0.74 0.002805 3 1002 clone
0.03 0.000130 0 4037 read
0.03 0.000119 0 15026 rt_sigprocmask
0.03 0.000096 0 15040 6017 stat
0.01 0.000055 0 8011 open
0.01 0.000024 0 5013 getegid
0.01 0.000021 0 16027 rt_sigaction
0.00 0.000017 0 9020 5008 access
0.00 0.000014 0 1001 1001 getpeername
0.00 0.000013 0 1001 getpgrp
0.00 0.000012 0 5013 geteuid
0.00 0.000011 0 15025 mmap
0.00 0.000011 0 1002 rt_sigreturn
0.00 0.000000 0 1 write
0.00 0.000000 0 8017 close
0.00 0.000000 0 7011 fstat
0.00 0.000000 0 8012 mprotect
0.00 0.000000 0 2004 munmap
0.00 0.000000 0 18049 brk
0.00 0.000000 0 1 pipe
0.00 0.000000 0 1 dup2
0.00 0.000000 0 1001 getpid
0.00 0.000000 0 1002 execve
0.00 0.000000 0 1001 uname
0.00 0.000000 0 1001 getrlimit
0.00 0.000000 0 5013 getuid
0.00 0.000000 0 5013 getgid
0.00 0.000000 0 1001 getppid
0.00 0.000000 0 1002 arch_prctl
0.00 0.000000 0 1001 time
------ ----------- ----------- --------- --------- ----------------
100.00 0.379372 158353 13028 total
С помощью dash
:
$ strace -cf bash -c 'for i in $(seq 1 1000); do dash -c ":"; done'
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
73.88 0.008543 4 2004 1002 wait4
25.35 0.002932 3 1002 clone
0.62 0.000072 0 9026 rt_sigprocmask
0.10 0.000011 0 1002 rt_sigreturn
0.05 0.000006 0 15027 rt_sigaction
0.00 0.000000 0 1037 read
0.00 0.000000 0 1 write
0.00 0.000000 0 2011 open
0.00 0.000000 0 2017 close
0.00 0.000000 0 2040 17 stat
0.00 0.000000 0 2011 fstat
0.00 0.000000 0 8025 mmap
0.00 0.000000 0 3012 mprotect
0.00 0.000000 0 1004 munmap
0.00 0.000000 0 3049 brk
0.00 0.000000 0 3020 3008 access
0.00 0.000000 0 1 pipe
0.00 0.000000 0 1 dup2
0.00 0.000000 0 1001 getpid
0.00 0.000000 0 1 1 getpeername
0.00 0.000000 0 1002 execve
0.00 0.000000 0 1 uname
0.00 0.000000 0 1 getrlimit
0.00 0.000000 0 13 getuid
0.00 0.000000 0 13 getgid
0.00 0.000000 0 1013 geteuid
0.00 0.000000 0 13 getegid
0.00 0.000000 0 1001 getppid
0.00 0.000000 0 1 getpgrp
0.00 0.000000 0 1002 arch_prctl
0.00 0.000000 0 1 time
------ ----------- ----------- --------- --------- ----------------
100.00 0.011564 60353 4028 total
Каждая итерация только запускает оболочку и ничего не делает с оператором no-op - colon, затем выходит.
Как видно из результатов, тире
при старте происходит чрезвычайно быстро, чем bash
. тире
меньше и зависит от меньшей общей библиотеки, чем bash
:
$ du -s /bin/bash
956 /bin/bash
$ du -s /bin/dash
108 /bin/dash
$ ldd /bin/bash
linux-vdso.so.1 => (0x00007fffc7947000)
libtinfo.so.5 => /lib/x86_64-linux-gnu/libtinfo.so.5 (0x00007f5a8110d000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f5a80f09000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f5a80b7d000)
/lib64/ld-linux-x86-64.so.2 (0x00007f5a81352000)
$ ldd /bin/dash
linux-vdso.so.1 => (0x00007fff56e5a000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fb24844c000)
/lib64/ld-linux-x86-64.so.2 (0x00007fb2487f3000)
Речь идет о времени запуска, как насчет работы. Давайте сделаем другой тест:
$ time dash -c 'for i in $(seq 1 1000000);do [ 1 = 1 ];done'
real 0m2.684s
user 0m2.728s
sys 0m0.100s
$ time bash -c 'for i in $(seq 1 1000000);do [ 1 = 1 ];done'
real 0m6.996s
user 0m6.820s
sys 0m0.376s
С помощью простого теста 1 = 1
, тире
всё ещё намного быстрее, чем bash
.
Системы Unix делают разделение между томами максимально прозрачным. Очень немногие программы заботятся о том, какой том (под какой точкой монтирования) находится файл. Это просто не имеет значения.
Существует множество средств для «запоминания» нескольких каталогов. Ищите объекты, связанные с каталогами, или со последовательностями в целом, а не объекты, связанные с несколькими томами: эти объекты не волнуют, на каких томах находятся каталоги.
Очень общий объект «запоминания» - это установка переменной. Эта переменная может содержать путь к каталогу или любой последовательности, которую вы хотите туда поместить. На оболочке в стиле Борна (zsh, bash, ksh и т. д.):
f=/media/usb1/dir1/dir2
d=~/dir3/dir4
cp $f/* $d/*
Если значения содержат места или \[ *?
, остерегайтесь, чем на оболочках в стиле Bourne, отличных от zsh, нужны двойные кавычки вокруг переменных замен:
cp "$f"/* "$d"/*
Вы всегда должны использовать двойные кавычки в сценариях, но в командной строке, поскольку вы обычно знаете, что в переменной, вы можете опустить их, если вы не знаете, что переменная содержит места.
Для быстрого перехода между несколькими каталогами можно использовать стек каталогов . Пример:
cd /media/usr1/dir1/dir2
ls
pushd ~/dir3 # Remember /media/usr1/dir1/dir2 and go to ~/dir3
ls
cd dir4 # Go to ~/dir3/dir4, /media/usr1/dir1/dir2 is still remembered
dirs # Show the directory stack
cp ~1/* . # Copy files from /media/usr1/dir1/dir2
popd +1 # Forget /media/usr1/dir1/dir2
-121--66142- Хотя может показаться, что у вас более чем достаточно оперативной памяти, Linux буферизирует файловые данные в памяти. Для ускорения доступа в память часто помещаются файловые системы типа /tmp
. Если замена не включена, в памяти может оказаться много вещей, которые могут помешать кэшированию часто используемых файлов. Ваш выбор на самом деле: пейджинговать неиспользуемую память на диск; или многократно считывать файлы с диска. У вас нет параметров, которые не потребуют ввода-вывода после заполнения памяти (включая буферы).
В эти дни обычно перестраивают память, чтобы поменять местами то, к которому недавно не обращались, вместо того, чтобы поменять местами целые программы. Вещи, которые могут быть разбиены на страницы:
PIC и другие немодифицированные данные, считанные с диска, могут использовать файл, из которого они считываются, в качестве резервного хранилища, а не с помощью подкачки.
Можно использовать такую программу, как sar
, для контроля пейджинга, замены и дискового ввода-вывода. Я ожидаю, что вы увидите меньше использования диска, когда у вас включена замена.
Если требуется приостановить работу на диске, обычно требуется достаточно большое пространство подкачки, в которое можно скопировать память при приостановке.
-121--229544-Ниже приведены некоторые моменты времени запуска различных оболочек в сертифицированной UNIX (Mac OS X 10.10.3). Я переписал тест, чтобы использовать tcsh для управления контурами, чтобы тестируемая оболочка не была той, которая управляет контурами. Для каждой оболочки цикл выполняется пять раз до синхронизации, чтобы гарантировать, что исполняемый файл оболочки и сценарии находятся в кэше.
Как вы видите, нет явного победителя, но есть один окончательный проигравший. В любом случае, баш 4 заметно медленнее, чем баш 3. Dash работает хорошо, но учитывая, что сейчас ksh93 с открытым исходным кодом, нет реальных причин не использовать его для всего (извинений, если я неправильно понимаю какие-либо лицензионные симпатии): ksh93 быстрый, солидный, и де-факто стандарт в UNIX-land (если не в GNU/Linux-land); он обеспечивает супернабор функциональности оболочки POSIX (насколько я понимаю, оболочка POSIX была основана на ksh88); он равен bash в качестве интерактивной оболочки, хотя и отстает по сравнению с tcsh. И проигравший, конечно, zsh.
/bin/bash is v3.2.57(1)
/usr/local/bin/bash is v4.3.33(1)
dash is v0.5.8
ksh is v93u+
mksh is vR50f
pdksh is v5.2.14
/opt/heirloom/5bin/sh is from SysV
yash is v2.37
zsh is v5.0.5
% cat driver.csh
#!/bin/tcsh
foreach s ( $* )
echo
echo "$s"
foreach i ( `seq 1 5` )
./simple_loop.csh "$s"
end
/usr/bin/time -p ./simple_loop.csh "$s"
end
% cat simple_loop.csh
#!/bin/tcsh
set shell = `which ${1}`
foreach i ( `seq 1 1000` )
${shell} -c ":"
end
% ./driver.csh /bin/bash /usr/local/bin/bash dash ksh mksh pdksh /opt/heirloom/5bin/sh yash zsh
/bin/bash
real 4.21
user 1.44
sys 1.94
/usr/local/bin/bash
real 5.45
user 1.44
sys 1.98
dash
real 3.28
user 0.85
sys 1.11
ksh
real 3.48
user 1.35
sys 1.68
mksh
real 3.38
user 0.94
sys 1.14
pdksh
real 3.56
user 0.96
sys 1.17
/opt/heirloom/5bin/sh
real 3.46
user 0.92
sys 1.11
yash
real 3.97
user 1.08
sys 1.44
zsh
real 10.88
user 3.02
sys 5.80
Во многих ответах слишком много несправедливых тестов. Если протестировать две оболочки, используйте правильный синтаксис для каждой из них. А в bash двойные скобки намного быстрее и надежнее, чем одинарные, так что разница в скорости вообще гораздо меньше. Также используйте оптимизированные башизмы, и тогда эти различия в скорости тоже будут меньше.В моей системе bash работает как ад, с интенсивным использованием башизмов. И эквиваленты posix в тире здесь медленнее. Это неверно, что dash всегда в несколько раз быстрее, чем bash. На самом деле довольно несправедливо сравнивать командные строки posix в обоих, кто тире всегда может быть самым быстрым. На мой взгляд, posix сильно устарел. И с точки зрения совместимости, сейчас очень сложно найти подходящие системы, они не использовали оболочку bash.
Хорошим сравнением является :использование наилучшей возможной командной строки в каждой оболочке для завершения конкретной работы. Мало того, что точно такая же командная строка, когда тут действительно преимущество имеет только одна оболочка. Подобные сравнения ненадежны и не отражают реальную производительность конкурентов. Я вижу на своей повседневной работе, какая оболочка быстрее во многих случаях использования.
Например, чтобы заменить все символы a
в строке на символы b
, в bash вы можете написать "${varname//a/b}"
, а в тире вам нужно вызвать внешний инструмент, подобный этому:"$(echo "$varname" | sed 's/a/b/g')"
. Если вам нужно повторить это несколько сотен раз -, использование башизма может дать вам 2-кратное ускорение.
Не все проблемы производительности являются проблемами эффективности, только большинство из них, в отличие от достаточно эффективных наивных проблем, которые требуют алгоритмических решений. Если бы мы исправляли одно или другое в целом, в большинстве случаев самое эффективное решение имело бы лучшую производительность.
Никто не может указать вам правильный путь решения проблемы, но есть одна конкретная проблема с эффективностью, которую может решить оболочка POSIX, по которой все сценарии запуска были перенесены с Bash на Dash.
Если вы испытываете проблемы с производительностью из-за одновременного запуска большого количества -сценариев, но все они достаточно эффективны каждый по отдельности, тогда перенос их всех на оболочку POSIX является предпочтительным решением.
Тем не менее, я бы, вероятно, сначала перепроверил, чтобы убедиться, что вы действительно должны порождать так много процессов одновременно, и что конкретная часть скрипта не может быть -переписана по-другому. Вы не упоминаете, что 200 порожденных дочерних процессов являются другими сценариями, возможно, их можно будет просто портировать вместо более крупного родительского сценария.
Бенчмарк подоболочки для sh/dash:
time./sh.sh --> real 0m12.382s
time./dash.sh --> real 0m12.459s
time./bash.sh --> real 0m48.913s (Cannot allocate memory)
K=$( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( $( exit ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) )