- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
// =================================================================================================
//
// Starling Framework
// Copyright 2011 Gamua OG. All Rights Reserved.
//
// This program is free software. You can redistribute and/or modify it
// in accordance with the terms of the accompanying license agreement.
//
// =================================================================================================
package starling.utils
{
/** Returns the next power of two that is equal to or bigger than the specified number. */
public function getNextPowerOfTwo(number:int):int
{
if (number > 0 && (number & (number - 1)) == 0) // see: http://goo.gl/D9kPj
return number;
else
{
var result:int = 1;
while (result < number) result <<= 1;
return result;
}
}
}
Для кого-то и логарифм - высшая математика... :(
wvxvw 01.11.2012 17:30 # +2
ширина / высота - целые числа. :)
3.14159265 01.11.2012 21:56 # +3
Он бы сдвиг сделал. Инфа 100%.
TarasB 01.11.2012 18:12 # +8
Кстати, зря в языках нету bsr
wvxvw 01.11.2012 18:35 # 0
Тем более, функция используется в атласе текстур, где все измерения целочисленные и неотрицательные.
roman-kashitsyn 01.11.2012 19:14 # +2
wvxvw 01.11.2012 19:23 # +1
Если для этого логарифм не использовать, то для чего же тогда? Тут прямо и само название говорит об этом.
roman-kashitsyn 01.11.2012 19:24 # +4
WGH 02.11.2012 00:20 # +1
TarasB 02.11.2012 09:23 # +1
tirinox 02.11.2012 11:40 # +3
3.14159265 01.11.2012 19:53 # +6
Код автора - лучше. Сдвиговая арифметика.
А дорогое деление и логарифм, а также перессылка в st0 и обратно съедят скорость.
Есть более быстрые способы, но они юзают битовую магию и неочевидны для читателей.
>где все измерения целочисленные и неотрицательные.
Тем более.
Минус.
wvxvw 01.11.2012 20:14 # 0
Вроде как нет, хотя и близко. Ну и пришлось немного подправить исходный вариант, т.как не работал.
Да и вообще в этом месте скорость была вообще не принципиальна. Атлас текстур собирается и разбирается не так часто, ну и вычислить именно это значение в контексте сборки атласа - вообще ни на что не повлияет по сравнению со временем нужным на то, чтобы скопировать текстуру в нужное место и загрузить атлас в память.
bormand 01.11.2012 20:21 # +3
Ну и чем тогда железобетонный и наглядный код со сдвигами хуже логарифма?
P.S. Вот всяко на нормальном компилируемом языке он еще и быстрее.
wvxvw 01.11.2012 20:25 # 0
TarasB 01.11.2012 20:43 # +1
wvxvw 01.11.2012 23:11 # +1
Кстати, если уж речь о байтолюбстве, то есть еще такие варианты:
Как оказалось, бинарный поиск - в пролете, а обычный if-else всех победил.
bormand 02.11.2012 08:33 # 0
wvxvw 02.11.2012 10:05 # 0
Да, получится чуть быстрее.
Но, тут еще такой момент: самый первый тест я сделал в более старой версии плеера, где логарифм вообще выигал, а в более новой - он безнадежно проигрывает. Т.е. видимо где-то в JIT компиляции научились лучше понимать байткод.
Кроме того, бинарный поиск можно оптимизировать, но для этого нужно будет переписать это на HaXe, или использовать какой-нибудь "оптимизатор", который бы переделал чтение / запись из флешевого вектора в обычный Си-шный массив. Скорее всего время тратится именно там в бинарном поиске.
TarasB 02.11.2012 09:25 # +1
wvxvw 02.11.2012 09:43 # 0
TarasB 02.11.2012 10:01 # 0
TarasB 01.11.2012 20:30 # 0
Есть одна асмокоманда. Но она не поддерживается ни в одном известном мне ЯВУ.
bormand 01.11.2012 20:43 # 0
http://ideone.com/vODZhq
На соответствующих процах компилится именно в bsr. На тех где нету - видимо в цикл.
TarasB 01.11.2012 20:46 # 0
Ещё байтоёбский вопрос: запилят ли в стандарт mul_int_int_to_double_int и div_double_int_on_int?
bormand 01.11.2012 20:56 # +2
> запилят ли в стандарт
146%, что нет.
> А в LLVM запилят?
__builtin_ia32_bsrdi. Х.з. если честно как с ним не на интелях.
> mul_int_int_to_double_int и div_double_int_on_int
Если я правильно понял, что double int это тупо два инта - то тут gcc и так отлично справляется. Где-то я уже кидал пример который превращается в одинокий imul.
TarasB 01.11.2012 21:08 # +3
3.14159265 01.11.2012 21:15 # +1
Чудеса конечно. Но asmовставка очевидней будет.
3.14159265 01.11.2012 21:13 # 0
int __builtin_popcount (unsigned int x)
3.14159265 01.11.2012 20:49 # +1
Ну то давно известно. На многие случаи жизни, особенно когда дело касается работы с битами есть "одна асмокомманда".
Например еще есть popcnt и lzcnt. Последняя суть аналог bsr, но вроде побыстрее.
Я же о реализации без них.
Вот реально жаль что в языках нету команды которая делит число и одновременно находит его остаток. Всё какие-то проценты сраные.
Кстати мне раньше нравилась старая winApi функция mulDiv, которую дельфятники даже в язык встроили. Но это немного не то.
TarasB 01.11.2012 20:51 # +4
3.14159265 01.11.2012 20:53 # +3
А они всякое не особо нужное говно добавляют.
bormand 01.11.2012 21:03 # +1
Умножение по модулю? Ну да, для той же криптографии полезно.
3.14159265 01.11.2012 21:05 # +5
div когда делит, то результат деления в eax, а остаток в edx.
Обожаю эту фичу.
Потому что обычно когда делишь, то нужен и остаток. А везде надо 2 деления делать. Это говно.
>Умножение по модулю?
Это mulDiv. Или не то выделил когда цитировал?
TarasB 01.11.2012 21:08 # +1
wvxvw 01.11.2012 21:11 # +4
3.14159265 01.11.2012 21:21 # 0
Делает список из 2-х значений?
Где первый элемент - частное, а второе остаток?
wvxvw 01.11.2012 21:24 # 0
3.14159265 01.11.2012 21:36 # 0
Это моя очепятка :)
>чуда-макрос
чудо-макрос
bormand 01.11.2012 21:34 # +1
3.14159265 01.11.2012 21:48 # 0
А то как я только не пробовал
(format t "a: ~d, b: ~d~&" (a, b) ))
(format t "a: ~d, b: ~d~&" a, b ))
А там оказывается хуйня с делением.
bormand 01.11.2012 21:41 # +1
P.S. За название multiple-value-bind мне хочется взять-и-уебать того кто ее так назвал. Довольно удобная и полезная фича, которую тем не менее противно юзать из-за длинного имени.
wvxvw 01.11.2012 22:19 # +1
bormand 01.11.2012 22:32 # 0
wvxvw 01.11.2012 21:18 # 0
fixed :)
bormand 01.11.2012 21:35 # +1
wvxvw 01.11.2012 21:38 # +1
bormand 01.11.2012 21:23 # +1
> Это mulDiv. Или не то выделил когда цитировал?
Да, на mulDiv отвечал.
3.14159265 01.11.2012 21:39 # +3
Но, блядь, почему в лоу-левельной сишке и прочих языках такого нет?
Ладно - они не могут в кортежи, списки и возвращать несколько значений.
Но ведь есть же передача по ссылке.
LispGovno 01.11.2012 22:12 # 0
ну а ссылок в сишке нет, указатели только
3.14159265 01.11.2012 20:00 # +4
Да. Асм безусловно рулит в таких вопросах. Быстро и красиво.
Кстати тут очень давно это обсуждали.
3.14159265 01.11.2012 20:11 # +3
"суть наверное в том чел написал одну годную оптимизацию
> (number & (number - 1))
Но не написал другую
Но когда я дошел до Math.floor(Math.log(x) / Math.log(2)) понял что код абсолютно адекватен.
Вот буквально только что смотрел. Из сырцов жабы (довольно свежих):
ConcurrentHashMap.class - очень годная, скоростная мапа, если что.
LispGovno 01.11.2012 20:13 # −4
За что эта константа отвечает?
TarasB 01.11.2012 20:32 # +5
LispGovno 01.11.2012 22:14 # −5
а вот жабу не знаешь, раз ответить не смог
bormand 01.11.2012 22:20 # +7
- Неа.
- Нет? А на си-решетке сидел?
- Нет.
- Че, крестоблядь что-ли?
Одно дело знать жабу, другое знать все кишки реализации ее хешмапов.
wvxvw 01.11.2012 20:39 # 0
Битовая магия, не?
bormand 01.11.2012 20:47 # 0
Можно номер строки в которой она находится?
wvxvw 01.11.2012 20:49 # 0
3.14159265 01.11.2012 20:51 # 0
Дело в том что нам надо "округлять вверх" до ближайшего сдвига. То есть задача следующая
min(x,y where y=2^n and y>x)
wvxvw 01.11.2012 20:56 # 0
bormand 01.11.2012 20:59 # +2
Работа кода вполне соответствует комменту:
/** Returns the next power of two that is equal to or bigger than the specified number. */
P.S. Ну правда next можно было и убрать.
wvxvw 01.11.2012 21:05 # +1
bormand 01.11.2012 21:38 # 0
Да, согласен.
3.14159265 01.11.2012 21:00 # +2
Заодно отвечая гумну. Чтобы мапа хорошо асспараллелилась, то её бьют на сегменты, на каждый сегмент своя лочка.
От хеша отрезают часть адреса и отводят на сегмент, остальное на адрес внутри - классика.
Так вот нам надо найти минимальную степень двойки, которая покроет нужный concurrencyLevel
Потому берем либо точно, либо немного с избытком. BUT NOT ANYMORE BABY!!!
Это ж должно быть очевидно - почему так.
Edit. Вон и bormand чуть выше толкует об том же.
LispGovno 01.11.2012 22:22 # −1
Блять. И вот после они говорят, что в кресты добавили поддержку многопоточности в новом стандарте С++11. Даже в бородавках жабы есть потокобезопасные контейнеры
3.14159265 01.11.2012 22:30 # +4
Другое дело быстрый, потокобезопастный контейнер, который умеет раssпаралеливаться - то есть можно одновременно добавлять значения, с другого треда читать, а с третьего удалять. Разработка такой штуки - дело непростое.
Потому кстати это одно из немногих мест где шарп отстал от жабы - в до-диезе только с 4-ой версии добавили ConcurrentDictionary. А до этого у них был только тормозной Hashtable.Synchronised, который работал в однопоточном режиме. Нахуй так жить?
LispGovno 01.11.2012 23:37 # 0
defecate-plusplus 02.11.2012 00:21 # +2
а парни из интела даже пропозицию делали в стандарт по поводу concurrent_* контейнеров
LispGovno 02.11.2012 01:08 # 0
proposal?
LispGovno 02.11.2012 01:14 # +1
LispGovno 02.11.2012 01:18 # 0
Концепты
«Концепты» (concepts) – это механизм, описывающий требования для типов, комбинаций типов или комбинаций типов и целых чисел. Эта возможность особенно полезна для ранней проверки использования шаблонов. И наоборот, она также помогает находить ошибки в теле шаблона на ранней стадии. Давайте рассмотрим алгоритм fill из стандартной библиотеки:
// типы типов
template<ForwardIterator Iter, class V>
// взаимоотношения между аргументами типов
requires Assignable<Iter::value_type,V>
// лишь объявление, а не определение
void fill(Iter first, Iter last, const V& v);
// Iter имеет тип int; ошибка: int не является ForwardIterator-ом
// int не содержит *
fill(0, 9, 9.9);
// Iter имеет тип int; ok: int* является ForwardIterator-ом
fill(&v[0], &v[9], 9.9);
LispGovno 02.11.2012 01:19 # 0
· Аргументы first и last должны быть типом ForwardIterator (и они должны быть одного типа).
· Третий аргумент v должен быть типом, который можно присвоить типу value_type типа ForwardIterator.
Конечно, мы все это знаем, ведь мы читали стандарт. Однако, компиляторы не умеют читать документы с требованиями, поэтому мы должны сказать ему в коде, в виде концептов ForwardIterator и Assignable. В результате ошибки использования метода fill() могут быть пойманы в месте использования, и текст ошибок может быть значительно яснее. Теперь у компилятора есть информация о намерениях программиста, что позволяет обеспечить хороший уровень проверок и диагностических сообщений.
LispGovno 02.11.2012 01:19 # 0
Эта ошибка будет отловлена сразу же, устраняя необходимость трудоемкого тестирования (хотя и не избавляет от тестирования полностью).
С возможностью классифицировать и различать разные типы типов, мы можем перегружать методы, основываясь на виде передаваемых типов. Например:
Вы можете определить свои собственные концепты, но для начала, в стандартной библиотеке определен большой набор полезных концептов, таких как ForwardIterator, Collable, LessThanComparable и Regular.
Обратите внимание, стандартные библиотеки С++11 предусматривают использование концептов.
См. также:
the C++ draft 14.10 Concepts
[N2617=08-0127] Douglas Gregor, Bjarne Stroustrup, James Widman, and Jeremy Siek: Proposed Wording for Concepts (Revision 5) (Final proposal).
Douglas Gregor, Jaakko Jarvi, Jeremy Siek, Bjarne Stroustrup, Gabriel Dos Reis, and Andrew Lumsdaine: Concepts: Linguistic Support for Generic Programming in C++. OOPSLA'06, October 2006.
LispGovno 02.11.2012 01:20 # 0
int* является ForwardIterator; мы сказали об этом при обсуждении концептов, и в стандартной библиотеке это всегда было именно так; даже в первой версии STL указатели использовались в качестве итераторов. Однако, мы также говорили о члене value_type типа ForwardIterator. Но int* не содержит члена с именем value_type; на самом деле, он вообще не содержит никаких членов. Так как int* может быть ForwardIterator? Поскольку мы сами это указали. С помощью concept_map мы можем сказать, что при использовании T*, где требуется ForwardIterator, мы будем рассматривать T в качестве value_type:
concept_map позволяет указать способ представления нашего типа, предотвращая от модификации существующий тип или от создания нового типа в качестве обертки. «Отображения концептов» (concept maps) являются гибким и обобщенным механизмом для адаптации независимо разработанных программ для совместного использования.
LispGovno 02.11.2012 01:21 # 0
the C++ draft 14.10.2 Concept maps
[N2617=08-0127] Douglas Gregor, Bjarne Stroustrup, James Widman, and Jeremy Siek: Proposed Wording for Concepts (Revision 5) (Final proposal).
Douglas Gregor, Jaakko Jarvi, Jeremy Siek, Bjarne Stroustrup, Gabriel Dos Reis, Andrew Lumsdaine: Concepts: Linguistic Support for Generic Programming in C++. OOPSLA'06, October 2006.
LispGovno 02.11.2012 01:21 # 0
Аксиома (axiom) – это набор предикатов, определяющих семантику концепта. Главным сценарием использование аксиом являются внешние инструменты (например, действия, нетипичные для компилятора), такие как, инструменты для предметно-ориентированных оптимизаций (domain-specific optimizations) (языки для описания программных изменений стали важным поводом появления аксиом). Аксиомы также могут быть полезны для некоторых оптимизаций (выполняемых компилятором и обычными оптимизаторами), но компиляторы не должны обращать внимания на пользовательские аксиомы; их работа основана на семантиках, определенных в стандарте.
Аксиомы перечисляют пару вычислений, которые могут трактоваться как эквивалентные. Например:
concept
<=> - это оператор эквивалентности, используемый только в аксиомах. Обратите внимание, что вы не можете (в общем случае) доказать аксиому; мы используем аксиомы для указания того, что мы не можем доказать, но что программист может назвать приемлемым допущением. Обратите внимание, что обе стороны оператора эквивалентности могут быть некорректными для некоторых значений, например использование NaN (not a number) для типов с плавающей запятой: если обе стороны эквивалентности используют NaN, то обе стороны (явно) некорректны и эквивалентны (независимо от того, что говорится в аксиоме), но если NaN используется только с одной стороны, то существует возможность получить выгоды от использования аксиомы.
LispGovno 02.11.2012 01:21 # 0
// в концепте TotalOrder:
axiom Transitivity(Op op, T x, T y, T z)
{
// условная эквивалентность
if (op(x, y) && op(y, z)) op(x, z) <=> true;
}
См. также:
the C++ draft 14.9.1.4 Axioms
???.
LispGovno 02.11.2012 01:32 # +2
Зато они приняли std::atomic, который в нормальных локфри алгоритмах и не поиспользуешь нормально.
defecate-plusplus 02.11.2012 09:14 # +3
в частности, последние proposalы по интересующей тебя теме датируются сентябрем 2012 (кстати, в авторах числится А. Малахов - может поэтому не принимают?) http://bit.ly/SgjoTp
а вообще в целом интересная страничка:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/
3.14159265 02.11.2012 15:36 # +2
А не AssParallel() #pragma omp parallel for для быдла которое возомнило что может в многопоточность.
LispGovno 03.11.2012 18:13 # +1
bormand 03.11.2012 18:31 # +1
3.14159265 03.11.2012 18:43 # +3
Я серъезно.
LispGovno 03.11.2012 18:56 # 0
3.14159265 03.11.2012 18:58 # +2
Ладно. Я сегодня добрый.
Примерно такая же как между мутабельной ссылкой на массив констант, и константым массивом мутабельных переменных.
LispGovno 04.11.2012 01:00 # 0
bormand 04.11.2012 13:46 # +1
http://stackoverflow.com/questions/692677/atomicintegerarray-vs-atomicinteger
AtomicInteger[] is an array of thread safe integers.
AtomicIntegerArray is a thread-safe array of integers.
LispGovno 04.11.2012 20:17 # 0
AtomicIntegerArray is a thread-safe array of integers.
Похоже на записки из бортового журнала капитана-очевидность.
LispGovno 04.11.2012 20:19 # 0
bormand 04.11.2012 21:09 # +1
Yes.
Поэтому AtomicIntegerArray быстрее, жрет меньше памяти, и его проще инициализировать.
LispGovno 03.11.2012 19:00 # 0
roman-kashitsyn 01.11.2012 23:52 # +2
roman-kashitsyn 02.11.2012 00:02 # +2
У эрланга, правда, есть большое преимущество: посколько процессы не шарят память, можно осуществлять сборку мусора в софт-реалтайм режиме: собирать мусор в тех процессах, которые в данный момент не выполняются, позволяя активным процессам продолжать работу.
wvxvw 02.11.2012 00:21 # +2
Можно все делать в одном модуле, в одном потоке, чтобы никуда ничего не передавать :) но это как-бы делает потоки и все что с ними связано бесполезным.
И это приводит к неимоверно кривым решениям:
- запись в файл и передача имени файла (так и то быстрее получается).
- запись в базу данных, и передавать доступ к соединению с базой в разные потоки (ппц глючно).
- держать открытый сокет с самопальным сервером, предназначенным для хранения информации (типа Memcached, например). Тоже решение так себе, т.как обычно уже лучше написать и обработку там же заодно.
Есть другой, меньший недостаток. Все объекты представлены, как в жабоскрипте: список, а внутри еще список, а внутри еще список... и т.д. Когда объекты простенькие - все замечательно, а когда начинаются усложнения - records превращаются в страницы текста до боли похожие одна на другую. И тут паттерн-матчинг начинает работать против нас, т.как случайно ненужные объекты попадают не в те функции. Решение - люди начинают изобретать свои системы типизации, которые, как правило сводятся к тому, что первым елементом в списке идет какой-нибудь символ, по которому дальше уже выбирается, что нужно. Естесственно, проблемы с уникальностью таких символов, ну и куча бойлерплейта, который никак не скрыть.
LispGovno 02.11.2012 01:36 # 0
Зачем передавать измененный список полностью, если можно передать комманду на изменение копии списка, находящегося в чужом экторе?
LispGovno 02.11.2012 01:41 # 0
Эм. А рекордов там нет?
Просто храни список экторов (они у нас будут заменять рекорды) и через сообщения выпытывай у них значения тех или иных полей.
Конечно, если программировать на эрланге, как на стандартных парадигмах - оно не будет работать.
wvxvw 02.11.2012 01:52 # +2
Можно конечно не посылать им весь спискок, а послать "что поменялось", и пусть сами разбираются как обновить список. Таким образом экономим память, но тратим время на то, что каждая функция выполнит ту же процедуру по изменению списка.
Т.е. получается, что проигрываем либо по памяти, либо по скорости.
> Стандартных парадигмах
Каких стандартов? :)
Работать, как уже было заявлено, будет в песочнице, по-настоящему - не будет.
> Рекорды
Ну вот они аналогичны жабоскриптовскому Object, в рантайме они неотличимы один от другого. Т.е. чтобы понять, что перед нами объект какого-то определенного типа нам нужно проверить, что все требования к типу соблюдены, при чем сделать это вручную. Т.е. если это пользователь чата, то нужно проверить, что у него есть имя, возраст, адресс и т.д. Даже всякие самодельные, не встроенные в язык системы типа той же eieio берут на себя этот тяжкий труд и предоставляют красивый способ решить эту проблему. В Эрланге, это все нужно делать самому, но в виду вышеописаных обстоятельств делать и не хочется особо, т.как никакой выгоды в перспективе не намечается.
wvxvw 02.11.2012 10:36 # +2
roman-kashitsyn 02.11.2012 16:25 # +2
Заводим процесс на каждого клиента, процесс на каждый диалог (который привязан к процессам клиентов). При смене состояния клиента (поменялся статус/отвалился) процесс диалога получает оповещение, и рассылает всем остальным участникам диалога соответствующее сообщение.
Если нужно делать постоянные вычисления и выборки по условиям, можно не мучиться с ручным удалением из списков и хранить данные в in-memory таблицах mnesia.
Проектировать распределённые системы сложно: нужно тщательно продумывать, кто за что отвечает и какие сообщения кому посылает, но в этом есть особенный кайф.
От разделяемого состояния на самом деле профита немного. При любом раскладе всем клиентам (ICQ-клиентам, comet-страничкам, etc.) нужно рассылать нотификации об изменении статусов, и наличие глобального состояния на сервере тут ничем не поможет. Оно также помешает распределению сервера по нескольким машинам.
wvxvw 02.11.2012 19:00 # +2
Вывод: картинку нужно хранить где-то отдельно, и каким-то образом косвенно разрешать другим функциям с ней работать, так чтобы они эту картинку никогда по-настоящему не получали. Эта стратегия так быстро перерастает в неимоверное мозгоебство, с которым ну так не хочется бороться, особенно, когда рядом лежит нормальный инструмент, которы может это сделать вообще без затрачивания каких-либо усилий.
Возможно, если очень упорно стараться сделать то же самое на Эрланге, можно каким-то образом построить систему, которая не будет передавать ресурсы, а только записывать в них чего-то. Но зачем? Нет ничего, что бы Эрланг делал лучше чем аналоги. Издеваться над собой ради чего?
Сопоставление с образцом? Так оно и не нужно в 90% случаев, и еще в 9% случаев работает не так, как нужно.
Ключевые слова для создания процессов + ппц неудобная конструкция их обработки? - Офигенный бонус. Я прям зальюсь слезами и все брошу когда вместо receive мне нужно будет написать reactor.callLater(...)
LispGovno 02.11.2012 19:05 # −3
>Erlang
No way.
LispGovno 02.11.2012 19:10 # −1
Стандартная стратегия при работе с эктерами. Чего плохого то? Какие проблемы вызывает? Я бы так и на другом языке делал. Просто с этим эктером обменивался сообщениями.
wvxvw 02.11.2012 19:18 # +1
Или, просто, напишите фильтр "размывка", который усредняет значения цвета в пикселах без чтения из картинки.
LispGovno 03.11.2012 13:18 # −1
А вот та идея, что обсуждается ниже (хранение кучи копий рисунков) - вообще не работоспособна. Это вместо единой работы, мы загружаем процессор кучой копий работы. А ведь это не единственная проблема. Результат некоторых алгоритмов рисования зависит от порядка рисования элементов. То есть если один человек закончил контур, а второй заливал этот контур (могло быть наоборот и команды пришли в обратном порядке), то залилось лишнее или один рисовал линию, а второй размытие (опять же в зависимости от порядка прихода команд), то линия получится размытой или нет. Порядок прихода сообщений в эрланге одному эктору от разных экторов не определен. Это значит что в каждой копии окажется свой рисунок, отличаюийся от других рисунков, если тебе не повезло. Делать так, чтобы один видел одно, а другой другое - глупо. Один говорит - ты все правильно сделал, а другой чатится с криками - ты упорот штоле? Лучше пусть они имеют единое мнение о упоротости или кутости параллельно рисующих. И отменят неудавшиеся операции.
LispGovno 03.11.2012 13:26 # 0
LispGovno 03.11.2012 13:28 # 0
roman-kashitsyn 03.11.2012 13:30 # +1
LispGovno 03.11.2012 13:37 # 0
roman-kashitsyn 03.11.2012 14:00 # +2
LispGovno 03.11.2012 15:19 # 0
Первый этап делаем по технологии map-reduce, а второй на основе перового уже как финальная обработка. Конечно этапов можно завести и больше, если нужно.
roman-kashitsyn 02.11.2012 20:49 # −1
Сервер, разумеется, ничего отрисовывать не должен, лишь заниматься маршрутизацией команд. Аналогично решается зача коллективного редактирования текста: между клиенскими машинами и сервером должны бегать только небольшие (но частые) патчи.
scriptin 02.11.2012 20:56 # 0
wvxvw 02.11.2012 21:07 # 0
wvxvw 02.11.2012 21:13 # 0
roman-kashitsyn 02.11.2012 22:06 # 0
wvxvw 02.11.2012 22:14 # 0
chatroulette.com
В сервере написаном на Эрланге юзабилити будет не просто убогий, он вообще работать не будет :) даже проверять бессмысленно.
roman-kashitsyn 02.11.2012 22:28 # −1
пф, что это
Это совсем другая задача - не коллективное редактирование документов, а передача потока, и этим занимаются высокооптимизированные медиа-сервера, написанные на плюсах или на том же эрланге (http://erlyvideo.org/). Предварительной обработки там не требуется: получил поток, направь его в нужную соску. Сервер там ничего не рендерит, и никаких фильтров не применяет.
И тут на клиенте как раз стоит жирный Flash Player.
wvxvw 02.11.2012 22:55 # +1
Вот именно потому, что не применяет никаких фильтров, да и вообще ничего толком с видео сделать не может - и не нужен он по большому счету. Я же почему чатрултеку вспомнил. Там очень даже нужно с видео что-то делать.
Например, там даже есть ИИ который пытается (но не очень успешно ;) угадать показывает ли абонент свои гениталии в камеру или это у него лицо такое. Но там еще много чего в том же духе.
PascalGovno 03.11.2012 11:20 # 0
roman-kashitsyn 03.11.2012 09:27 # 0
А вот это интересно. Можно поподробнее?
Если рендерить всё на сервере, передавать изображения между разными процессами тоже практически не нужно.
На каждого клиента будет процесс, который принимает от него команды на редактирование; на каждое "коллективное" изображение будет процесс, который отвечает за последовательное применение команд, и практически не делит ни с кем изображение, разве что с процессом, отправляющим изображение обратно пользователям.
Кстати, бинарные данные в сообщениях не копируются в рамках одного нода: можно спокойно передавать блоб с изображением от процесса к процессу, копироваться будет только кортеж, в который завернули бинарник.
А проблема всплывает в обработке изображения на erlang: для каждой команды нужно будет порождать новую копию изображения, что не эффективно для большого числа мелких команд, да и эрланг слишком тормозной для обработки изображений. Кстати, эрланговцы сами честно не советуют применять его для этого:
The most common class of 'less suitable' problems is characterised by performance being a prime requirement and constant-factors having a large effect on performance. Typical examples are image processing, signal processing, sorting large volumes of data and low-level protocol termination.
http://www.erlang.org/faq/introduction.html
wvxvw 03.11.2012 11:38 # +1
Когда сопоставление с образцом вредно:
- у нас есть кортеж, который представляет пользователя, мы написали функции которые на нем сепциализируется узнавая первый элемент коретжа как символ 'user'. Приложение монетизируют следующим образом: пользователи с "премиум" возможностями могут совершать какие-то операции, другие пользователи не могут (за эти возможности они чего-то заплатили).
Проблема: кортежи, которые представляют платных пользователей нужно как-то отличать от обычных пользователей.
Если мы переименуем первый тег в 'premium_user' - все функции, которые раньше специализировались на 'user' нужно либо переписать, либо они не будут рабоать. Иногда нам нужно / не важно будут ли они работать с новым типом пользователей, а может быть и важно. Другой вариант, оставляем и тех и других с тегом 'user' и добавляем еще один элемент в кортеж, в котором указываем тип пользователя - но проблему это не решает, т.как переписывать все равно нужно много. Можно еще использовать эрланговское наследование, при условии, что все функции работающие с пользователями были в одном модуле (а как же...) это будет немного лучше.
Вобщем, работа с похожими, но не одинаковыми объектами становится головной болью номер один, и выглядит как либо огромное количество if-ов, а учитывая не-ленивые if-ы, это цирк тот еще... Или в кучу служебных функций, которые пытаются как-то отфильтровать нужные типы объектов, или сигнатуры функций начинают выглядеть как доказательство последней теоремы Ферма.
roman-kashitsyn 03.11.2012 12:36 # +2
Я бы в таком случае, наверное, попытался применить список привилегий пользователя.