SlideShare une entreprise Scribd logo
1  sur  63
Télécharger pour lire hors ligne
Software Transactional Memory
Курс «Базы данных»
Цесько Вадим Александрович
http://incubos.org
@incubos
Computer Science Center

9 декабря 2013 г.

Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

1 / 63
Содержание
1

Введение

2

Примеры

3

Internals

4

Заключение

5

Домашнее задание

Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

2 / 63
Введение

Мотивация

Мотивация
Задача
Множество изменяемых объектов в памяти
Атомарность наборов операций с объектами
Решение
Software Transactional Memorya :
Память как транзакционное хранилище
Универсальная альтернатива ручным блокировкам
ACI
a

http:
//en.wikipedia.org/wiki/Software_transactional_memory
Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

3 / 63
Введение

Идея

Идея

(Очень) оптимистичные транзакции
Если прочитанные значения не менялись, то
commit
В противном случае — retry
Возможен abort в любой момент
Как следствие – max concurrency

Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

4 / 63
Введение

Идея

Ручные блокировки

Нужно думать о перекрывающихся операциях
Нужно «держать в голове» весь код
Deadlocks, livelocks, progress, etc.
Очень трудно воспроизвести и отладить
Priority inversion1

1

http://en.wikipedia.org/wiki/Priority_inversion

Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

5 / 63
Введение

Идея

Подход STM

Simple
Maintainable
Composable
Не нужно думать о deadlocks и livelocks
Priority inversion — abort низкоприоритетной
транзакции
Но (почти) недопустимы side effects (в т. ч. IO)

Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

6 / 63
Введение

Реализации

Реализации

Множество реализаций для всех языков
Встроено в Clojure
ScalaSTM2

2

http://nbronson.github.io/scala-stm/

Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

7 / 63
Введение

Реализации

Scala STM Expert Group

Akka
Stanford
Tel-Aviv University
EPFL
Cisco
etc.

Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

8 / 63
Введение

ScalaSTM

С высоты птичьего полёта
Живёт между atomic-блоком и Heap
Перехватывает чтения и записи
Чтения и записи из разных потоков
перемешались — rollback записей и retry
Иначе — commit
Видны только закоммиченые изменения
Принимаем во внимание только Refы
Реализация в виде библиотеки
TSet и TMap

Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

9 / 63
Введение

ScalaSTM

Достоинства
Say what you mean
(nested) atomic

Readers scale
CPU cache friendly

Exceptions automatically trigger cleanup
By default

Waiting for complex conditions is easy
retry, chaining

Simple
Just a library

Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

10 / 63
Введение

ScalaSTM

Недостатки
Two extra characters per read or write
x: Ref
Read: x()
Write: x() = y

Single-thread overheads
Но полезен rollback при исключениях

Rollback doesn’t mix well with I/O
Но есть хуки

Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

11 / 63
Примеры

API

Basic
1

import scala.concurrent.stm._

2
3
4
5

val x = Ref(0) // allocate a Ref[Int]
val y = Ref.make[String]() // type-specific default
val z = x.single // Ref.View[Int]

6
7
8
9
10
11
12
13
14
15
16

atomic { implicit txn =>
val i = x() // read
y() = "x was " + i // write
val eq = atomic { implicit txn => // nested atomic
// both Ref and Ref.View can be used inside atomic
x() == z()
}
assert(eq)
y.set(y.get + ", long-form access")
}
Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

12 / 63
Примеры

API

Advanced
1
2
3

// only Ref.View can be used outside atomic
println("y was ’" + y.single() + "’")
println("z was " + z())

4
5
6
7
8
9
10
11

atomic { implicit txn =>
y() = y() + ", first alternative"
if (x getWith { _ > 0 }) // read via a function
retry // try alternatives or block
} orAtomic { implicit txn =>
y() = y() + ", second alternative"
}

12
13
14
15
16
17

val prev = z.swap(10) // atomic swap
val success = z.compareAndSet(10, 11) // atomic compare-and-set
z.transform { _ max 20 } // atomic transformation
val pre = y.single.getAndTransform { _.toUpperCase }
val post = y.single.transformAndGet { _.filterNot { _ == ’ ’ } }
Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

13 / 63
Примеры

Doubly-linked list

Use Ref for shared variables
1

import scala.concurrent.stm._

2
3
4
5
6
7
8
9
10
11

class ConcurrentIntList {
private class Node(
val elem: Int,
prev0: Node,
next0: Node) {
val isHeader = prev0 == null
val prev = Ref(if (isHeader) this else prev0)
val next = Ref(if (isHeader) this else next0)
}

12
13

private val header = new Node(-1, null, null)

Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

14 / 63
Примеры

Doubly-linked list

Wrap your code in atomic

1
2
3
4
5
6
7
8

def addLast(elem: Int) {
atomic { implicit txn =>
val p = header.prev()
val newNode = new Node(elem, p, header)
p.next() = newNode
header.prev() = newNode
}
}

Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

15 / 63
Примеры

Doubly-linked list

Compose atomic operations

1
2
3
4
5
6
7

def addLast(e1: Int, e2: Int, elems: Int*) {
atomic { implicit txn =>
addLast(e1)
addLast(e2)
elems foreach { addLast(_) }
}
}

Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

16 / 63
Примеры

Doubly-linked list

Optimize single-operation transactions
Ref.View:
Получение через Ref.single
Можно использовать вне atomic
Поддерживает транзакции из одной операции
swap, compareAndSet, transform, etc.
Пример:
1
2
3
4
5

/*
def isEmpty = atomic { implicit t =>
header.next() == header
}
*/

6
7

def isEmpty = header.next.single() == header
Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

17 / 63
Примеры

Doubly-linked list

Wait for conditions to change

1
2
3
4
5
6
7
8
9
10

def removeFirst(): Int =
atomic { implicit txn =>
val n = header.next()
if (n == header)
retry
val nn = n.next()
header.next() = nn
nn.prev() = header
n.elem
}

Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

18 / 63
Примеры

Doubly-linked list

Wait for multiple events

1
2
3
4
5
6
7

def maybeRemoveFirst(): Option[Int] = {
atomic { implicit txn =>
Some(removeFirst())
} orAtomic { implicit txn =>
None
}
}

Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

19 / 63
Примеры

Doubly-linked list

Composition: select
1
2
3
4
5
6
7
8
9
10
11
12

object ConcurrentIntList {
def select(stacks: ConcurrentIntList*):
(ConcurrentIntList, Int) =
atomic { implicit txn =>
for (s <− stacks) {
s.maybeRemoveFirst() match {
case Some(e) => return (s -> e)
case None => _
}
}
retry
}

Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

20 / 63
Примеры

Doubly-linked list

Be careful about rollback (1)
1
2
3
4
5
6
7
8
9
10
11
12

def badToString: String = {
val buf = new StringBuilder("ConcurrentIntList(")
atomic { implicit txn =>
var n = header.next()
while (n != header) {
buf ++= n.elem.toString
n = n.next()
if (n != header) buf ++= ","
}
}
buf ++= ")" toString
}

Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

21 / 63
Примеры

Doubly-linked list

Be careful about rollback (2)
1
2
3
4
5
6
7
8
9
10
11
12

override def toString: String = {
atomic { implicit txn =>
val buf = new StringBuilder("ConcurrentIntList(")
var n = header.next()
while (n != header) {
buf ++= n.elem.toString
n = n.next()
if (n != header) buf ++= ","
}
buf ++= ")" toString
}
}

Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

22 / 63
Примеры

Indexed Map

Цель

In-memory DB
User-defined indices

Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

23 / 63
Примеры

Indexed Map

API
1
2
3
4
5
6
7
8
9
10
11
12

13
14

scala> case class User(id: Int, name: String, likes: Set[String])
scala> val m = new IndexedMap[Int, User]
scala> m.put(10, User(10, "alice", Set("scala", "climbing")))
res0: Option[User] = None
scala> val byName = m.addIndex { (id,u) => Some(u.name) }
byName: (String) => Map[Int,User] = <function1>
scala> val byLike = m.addIndex { (id,u) => u.likes }
byLike: (String) => Map[Int,User] = <function1>
scala> m.put(11, User(11, "bob", Set("scala", "skiing")))
res1: Option[User] = None
scala> byName("alice")
res2: Map[Int,User] = Map((10,User(10,alice,Set(scala,
climbing))))
scala> byLike("scala").values map { _.name }
res3: Iterable[String] = List(alice, bob)

Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

24 / 63
Примеры

Indexed Map

A high-level sketch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

import scala.concurrent.stm._
class IndexedMap[A, B] {
private val contents = TMap.empty[A, B]
// TODO def addIndex(view: ?): ?
def get(key: A): Option[B] = contents.single.get(key)
def put(key: A, value: B): Option[B] =
atomic { implicit txn =>
val prev = contents.put(key, value)
// TODO: update indices
prev
}
def remove(key: A): Option[B] =
atomic { implicit txn =>
val prev = contents.remove(key)
// TODO: update indices
prev
}
}
Цесько В. А. (CompSciCenter)
STM
9 декабря 2013 г.

25 / 63
Примеры

Indexed Map

Types for the view function and index

Помедитируем:
1
2

def addIndex(view: ((A, B) => Iterable[C])):
(C => Map[A, B]) = ...

Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

26 / 63
Примеры

Indexed Map

Tracking and updating indices (1)
1
2
3
4
5

private class Index[C](view: (A, B) => Iterable[C])
extends (C => Map[A, B]) {
def += (kv: (A, B)) // TODO
def -= (kv: (A, B)) // TODO
}

6
7

private val indices = Ref(List.empty[Index[_]])

8
9
10
11
12
13
14
15
16

def addIndex[C](view: (A, B) => Iterable[C]):
(C => Map[A, B]) =
atomic { implicit txn =>
val index = new Index(view)
indices() = index :: indices()
contents foreach { index += _ }
index
}
Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

27 / 63
Примеры

Indexed Map

Tracking and updating indices (2)
1
2
3
4
5
6
7

def put(key: A, value: B): Option[B] =
atomic { implicit txn =>
val prev = contents.put(key, value)
for (p <− prev; i <− indices()) i -= (key -> p)
for (i <− indices()) i += (key -> value)
prev
}

8
9
10
11
12
13
14

def remove(key: A): Option[B] =
atomic { implicit txn =>
val prev = contents.remove(key)
for (p <− prev; i <− indices()) i -= (key -> p)
prev
}

Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

28 / 63
Примеры

Indexed Map

Index internals
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

private class Index[C](view: (A, B) => Iterable[C])
extends (C => Map[A, B]) {
val mapping = TMap.empty[C, Map[A, B]]
def apply(derived: C) =
mapping.single.getOrElse(derived, Map.empty[A, B])
def += (kv: (A, B))(implicit txn: InTxn) {
for (c <− view(kv._1, kv._2))
mapping(c) = apply(c) + kv
}
def -= (kv: (A, B))(implicit txn: InTxn) {
for (c <− view(kv._1, kv._2)) {
val after = mapping(c) - kv._1
if (after.isEmpty)
mapping -= c
else
mapping(c) = after
}
}
Цесько В. А. (CompSciCenter)
STM
9 декабря 2013 г.

29 / 63
Примеры

Dining Philosophers

Проблема

Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

30 / 63
Примеры

Dining Philosophers

STM solution
1

class Fork { val inUse = Ref(false) }

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

def meal(left: Fork, right: Fork) {
// thinking
atomic { implicit txn =>
if (left.inUse() || right.inUse())
retry // forks are not both ready, wait
left.inUse() = true
right.inUse() = true
}
// eating
atomic { implicit txn =>
left.inUse() = false
right.inUse() = false
}
}
Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

31 / 63
Internals

Waiting

Waiting
retry в atomic ≈ wait() в synchronized, но retry:
Безопаснее
STM определяет модификации Ref, ведущие к
пробуждению (вместо notifyAll)
Невозможны «потерянные» пробуждения

Эффективнее
Нет «лишних» пробуждений
Можно ожидать на любых условиях, а не только на
предопределённых

Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

32 / 63
Internals

Waiting

Search with backtracking (1)
Optimistic concurrency control as a search with
backtracking:
1

val (x, y) = (Ref(10), Ref(0))

2
3
4
5
6
7

def sum = atomic { implicit txn =>
val a = x()
val b = y()
a + b
}

8
9
10
11
12
13
14

def transfer(n: Int) {
atomic { implicit txn =>
x -= n
y += n
}
}
Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

33 / 63
Internals

Waiting

Search with backtracking (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

// sum
atomic
| begin txn
| | read x
| |
:
| |
| |
:
| |
| | read y
| roll back
| begin txn
| | read x
| | read y
| commit
+-> 10

attempt
-> 10

-> x read is invalid

// transfer(2)
atomic
| begin txn attempt
| | read x -> 10
| | write x <− 8
| | read y -> 0
| | write y <− 2
| commit
+-> ()

attempt
-> 8
-> 2

Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

34 / 63
Internals

Waiting

Retry. Семантика
Вызов retry — сигнал о dead end, даже если все
чтения и записи консистентны
STM откатится и попробует снова
Если некоторые из прочитанных Refов
изменились, то atomic блок может пойти по
другому пути и избежать retry
Условие ожидания retry
Неявно задано потоком управления в atomic-блоке

Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

35 / 63
Internals

Waiting

Retry. Эффективность
Примеры:
if (x() <= 10) retry
if (x() == 0 && y() == 0 && z() == 0)
retry
Реализация:
STM отслеживает, к каким Refам обращались
Под капотом — блокирующиеся конструкции
retry: Nothing

Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

36 / 63
Internals

Waiting

Alternatives

orAtomic/atomic.oneOf:
Несколько путей поиска
Первый заканчивается retry — откат и идём по
второму и т. д.
Учитывается только явный retry (а не
неконсистентные чтения)

Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

37 / 63
Internals

Waiting

Alternatives. Пример
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

val msg = atomic { implicit txn =>
if (x() == 0)
retry
x -= 1
"took one from x"
} orAtomic { implicit txn =>
if (y() == 0)
retry
y -= 1
"took one from y"
} orAtomic { implicit txn =>
if (z() == 0)
retry
z -= 1
"took one from z"
}
Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

38 / 63
Internals

Waiting

Timeouts
Зачем timeout при retry:
Error logging/handling
No work — waiting thread shutdown
Timeouts in spec of higher-level interface
Способы ограничения retry:
Модифицированный TxnExecutor
(InterruptedException)
retryFor()

Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

39 / 63
Internals

Waiting

Timeouts. TxnExecutor
1
2

3

atomic.withRetryTimeout(1000) { implicit txn =>
// any retries in this atomic block will wait for at most
1000 milliseconds
}

4
5
6
7
8
9

val myAtomic = atomic.withRetryTimeout(1, TimeUnit.SECONDS)
myAtomic { implicit txn =>
// this atomic block has a timeout of 1 seconds
}
myAtomic { ... }

10
11
12
13
14

TxnExecutor.transformDefault( _.withRetryTimeout(1000) )
atomic { implicit txn =>
// all atomic blocks now default to a 1 second timeout
}

Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

40 / 63
Internals

Waiting

Timeouts. retryFor(timeout)
1
2
3
4
5
6
7

val instance = atomic { implicit txn =>
if (!pool.hasAvailable) {
retryFor(100)
pool.grow()
}
pool.take()
}

Сигнатура
1

retryFor(...): Unit

1

retry: Nothing

Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

41 / 63
Internals

Waiting

Timeouts. Views

Можно блокироваться на Ref.View:
Ref.View.await(pred): Unit
Ref.View.tryAwait(duration)(pred): Boolean

Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

42 / 63
Internals

Maps + Sets

Maps + Sets

Консистентные итераторы у TMap.View и
TSet.View
Быстрые слепки за O(1)

Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

43 / 63
Internals

Maps + Sets

Consistent iteration

TMap.View extends mutable.MapLike
get()/put() outside atomic should be atomic
TMap.View.iterator/TSet.View.iterator для
атомарного слепка

Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

44 / 63
Internals

Maps + Sets

Inconsistent iteration

1

val m = TMap("one" -> 1).single

2
3
4
5
6
7
8

(new Thread { override def run {
atomic { implicit txn =>
m -= "one"
m += ("ONE" -> 1)
}
} }).start

9
10

for ((k, v) <− m; if v == 1) println(k)

Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

45 / 63
Internals

Maps + Sets

Manual snapshots

<TMap|TSet>[.View].snapshot() возвращает
immutable.Map/immutable.Set
<TMap|TSet>.clone()

Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

46 / 63
Internals

Maps + Sets

How does it work?
Mutable hash tries from Refs with generation
numbers that control copy-on-write
N. G. Bronson, J. Casper, H. Chafi and K. Olukotun. A
Practical Concurrent Binary Search Tree. 2010.
N. G. Bronson, J. Casper, H. Chafi and K. Olukotun.
Transactional Predication: High-Performance
Concurrent Sets and Maps for STM. In PODC’10:
Proceedings of the 29th Annual ACM Conference on
Principles of Distributed Computing, 2010.
N. G. Bronson. Composable Operations on
High-Performance Concurrent Collections. Ph.D.
Dissertation, Stanford University, 2011.
Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

47 / 63
Internals

Exceptions

Exceptions

Exception ⇒ rollback + rethrow
scala.util.control.ControlThrowable ⇒
commit + rethrow

Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

48 / 63
Internals

Exceptions

Exceptions and nesting
1
2
3
4
5
6
7
8
9
10
11
12

val last = Ref("none")
atomic { implicit txn =>
last() = "outer"
try {
atomic { implicit txn =>
last() = "inner"
throw new RuntimeException
}
} catch {
case _: RuntimeException =>
}
}

Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

49 / 63
Заключение

Benchmarking

Benchmarking

TL;DR
Немного медленнее в однопоточном режиме по
сравнению с хитрыми блокировками
Лучше масштабируется по ядрам/нитям

Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

50 / 63
Заключение

Benchmarking

STMBench7
R. Guerraoui, M. Kapalka and J. Vitek. STMBench7:
A Benchmark for Software Transactional Memory.
2007.
A. Dragojevic, R. Guerraoui and M. Kapalka. Dividing
Transactional Memories by Zero. 2008.
Comparison to coarse- and medium-grained locking
See the details4

4

http://nbronson.github.io/scala-stm/benchmark.html

Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

51 / 63
Заключение

Benchmarking

Read Dominated

Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

52 / 63
Заключение

Benchmarking

Write Dominated

Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

53 / 63
Заключение

Benchmarking

Read + Write Mix

Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

54 / 63
Заключение

Benchmarking

Read + Write Mix GC Rate

Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

55 / 63
Заключение

Benchmarking

Read + Write Mix GC Load

Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

56 / 63
Заключение

Bibliography

Bibliography
F. T. Schneider, V. Menon, T. Shpeisman, and
A.-R. Adl-Tabatabai. Dynamic Optimization for
Efficient Strong Atomicity. 2008.
N. G. Bronson, C. Kozyrakis and K. Olukotun.
Feedback-Directed Barrier Optimization in a Strongly
Isolated STM. 2009
V. Menon, S. Balensieger, T. Shpeisman,
A.-R. Adl-Tabatabai, R. L. Hudson, B. Saha and
A. Welc. Practical Weak-Atomicity Semantics for
Java STM. 2008.
K. F. Moore and D. Grossman. High-Level Small-Step
Operational Semantics for transactions. 2008.
Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

57 / 63
Заключение

Bibliography continued

Bibliography continued
T. Harris, S. Marlow, S. Peyton-Jones and M. Herlihy.
Composable Memory Transactions. 2005.
R. Hickey. The Clojure Programming Language. 2008
D. Dice, O. Shalev and N. Shavit. Transactional
Locking II. 2006.
T. Riegel, P. Felber and C. Fetzer. A Lazy Snapshot
Algorithm with Eager Validation. 2006.
R. Guerraoui and M. Kapalka. On the Correctness of
Transactional Memory. 2008.
A. Dragojevic, R. Guerraoui and M. Kapalka.
Stretching Transactional Memory. 2009.
Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

58 / 63
Заключение

Куда двигаться дальше

Куда двигаться дальше
Herb Sutter. The Free Lunch Is Over. 2009.
Jonas Bon´r. State: You’re Doing It Wrong —
e
Alternative Concurrency Paradigms For The JVM5 .
JavaOne 2009.
ScalaDays 2013. Concurrency — The good, the bad,
the ugly6
Chris Okasaki. Purely Functional Data Structures.
1999
JCIP 2nd edition + JMM
5

http://www.slideshare.net/jboner/
state-youre-doing-it-wrong-javaone-2009
6
http://www.parleys.com/play/51c0bc58e4b0ed877035680a/
Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

59 / 63
Домашнее задание

Получили зачёт

Получили зачёт

Ершов В.
Суворов Е.
Фёдоров К.

Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

60 / 63
Домашнее задание

Могут получить зачёт

Могут получить зачёт

Бакрадзе Л.
Грязнов С.
Егоров Д.
Королев Д.
Хомутов В.
Шашкова Е.

Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

61 / 63
Домашнее задание

Last Feature Requests

Last Feature Requests

2013-11-18
2013-11-25
2013-12-02
Batches
2013-12-09
Processing

7

FR8: Redis Hashes7
FR9: Compression
FR10: Multithreaded Node + Atomic
FR11: Server Side Filtering and

http://redis.io/commands#hash

Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

62 / 63
Вопросы?

Вопросы?

http://incubos.org/contacts/
Общие вопросы — в Twitter: @incubos
Вопросы по лекциям — в комментариях:
http://incubos.org/blog/
Частные вопросы — в почту
vadim.tsesko@gmail.com

Цесько В. А. (CompSciCenter)

STM

9 декабря 2013 г.

63 / 63

Contenu connexe

Tendances

Technopolis.NoSQL 03 Cassandra
Technopolis.NoSQL 03 CassandraTechnopolis.NoSQL 03 Cassandra
Technopolis.NoSQL 03 CassandraVadim Tsesko
 
Современная операционная система: что надо знать разработчику / Александр Кри...
Современная операционная система: что надо знать разработчику / Александр Кри...Современная операционная система: что надо знать разработчику / Александр Кри...
Современная операционная система: что надо знать разработчику / Александр Кри...Ontico
 
Мониторинг ожиданий в PostgreSQL / Курбангалиев Ильдус (Postgres Professional)
Мониторинг ожиданий в PostgreSQL / Курбангалиев Ильдус (Postgres Professional)Мониторинг ожиданий в PostgreSQL / Курбангалиев Ильдус (Postgres Professional)
Мониторинг ожиданий в PostgreSQL / Курбангалиев Ильдус (Postgres Professional)Ontico
 
DNS в условиях хостинг-провайдера / Константин Новаковский (Selectel)
DNS в условиях хостинг-провайдера / Константин Новаковский (Selectel)DNS в условиях хостинг-провайдера / Константин Новаковский (Selectel)
DNS в условиях хостинг-провайдера / Константин Новаковский (Selectel)Ontico
 
Реактивный раздатчик ok.ru/music
Реактивный раздатчик ok.ru/musicРеактивный раздатчик ok.ru/music
Реактивный раздатчик ok.ru/musicVadim Tsesko
 
Строим сервисы на базе Nginx и Tarantool / Василий Сошников, Андрей Дроздов (...
Строим сервисы на базе Nginx и Tarantool / Василий Сошников, Андрей Дроздов (...Строим сервисы на базе Nginx и Tarantool / Василий Сошников, Андрей Дроздов (...
Строим сервисы на базе Nginx и Tarantool / Василий Сошников, Андрей Дроздов (...Ontico
 
Отказоустойчивая обработка 10M OAuth токенов на Tarantool / Владимир Перепели...
Отказоустойчивая обработка 10M OAuth токенов на Tarantool / Владимир Перепели...Отказоустойчивая обработка 10M OAuth токенов на Tarantool / Владимир Перепели...
Отказоустойчивая обработка 10M OAuth токенов на Tarantool / Владимир Перепели...Ontico
 
Константин Осипов (Mail.Ru)
Константин Осипов (Mail.Ru)Константин Осипов (Mail.Ru)
Константин Осипов (Mail.Ru)Ontico
 
Чем заняться вечером, если я знаю сколько будет ++i + ++i / Андрей Бородин (Y...
Чем заняться вечером, если я знаю сколько будет ++i + ++i / Андрей Бородин (Y...Чем заняться вечером, если я знаю сколько будет ++i + ++i / Андрей Бородин (Y...
Чем заняться вечером, если я знаю сколько будет ++i + ++i / Андрей Бородин (Y...Ontico
 
Flashcache в mamba.ru / Яковлев Александр Юрьевич (ЗАО Мамба)
Flashcache в mamba.ru / Яковлев Александр Юрьевич (ЗАО Мамба)Flashcache в mamba.ru / Яковлев Александр Юрьевич (ЗАО Мамба)
Flashcache в mamba.ru / Яковлев Александр Юрьевич (ЗАО Мамба)Ontico
 
Что особенного в СУБД для данных в оперативной памяти / Константин Осипов (Ta...
Что особенного в СУБД для данных в оперативной памяти / Константин Осипов (Ta...Что особенного в СУБД для данных в оперативной памяти / Константин Осипов (Ta...
Что особенного в СУБД для данных в оперативной памяти / Константин Осипов (Ta...Ontico
 
Реализация восстановления после аварий / Сергей Бурладян (Avito)
Реализация восстановления после аварий / Сергей Бурладян (Avito)Реализация восстановления после аварий / Сергей Бурладян (Avito)
Реализация восстановления после аварий / Сергей Бурладян (Avito)Ontico
 
nginx.CHANGES.2015 / Игорь Сысоев, Валентин Бартенев (Nginx)
nginx.CHANGES.2015 / Игорь Сысоев, Валентин Бартенев (Nginx)nginx.CHANGES.2015 / Игорь Сысоев, Валентин Бартенев (Nginx)
nginx.CHANGES.2015 / Игорь Сысоев, Валентин Бартенев (Nginx)Ontico
 
Модульность и управляемая многопоточность встраиваемых С++ приложений - трудн...
Модульность и управляемая многопоточность встраиваемых С++ приложений - трудн...Модульность и управляемая многопоточность встраиваемых С++ приложений - трудн...
Модульность и управляемая многопоточность встраиваемых С++ приложений - трудн...corehard_by
 
Отладка и устранение проблем в PostgreSQL Streaming Replication.
Отладка и устранение проблем в PostgreSQL Streaming Replication.Отладка и устранение проблем в PostgreSQL Streaming Replication.
Отладка и устранение проблем в PostgreSQL Streaming Replication.Alexey Lesovsky
 
Защита данных и датацентров от катастроф. Подход Nutanix / Максим Шапошников ...
Защита данных и датацентров от катастроф. Подход Nutanix / Максим Шапошников ...Защита данных и датацентров от катастроф. Подход Nutanix / Максим Шапошников ...
Защита данных и датацентров от катастроф. Подход Nutanix / Максим Шапошников ...Ontico
 
PostgreSQL: практические примеры оптимизации SQL-запросов / Иван Фролков (Po...
PostgreSQL: практические примеры оптимизации SQL-запросов /  Иван Фролков (Po...PostgreSQL: практические примеры оптимизации SQL-запросов /  Иван Фролков (Po...
PostgreSQL: практические примеры оптимизации SQL-запросов / Иван Фролков (Po...Ontico
 
SOA: строим свой service mesh / Иван Круглов (Booking.com)
SOA: строим свой service mesh / Иван Круглов (Booking.com)SOA: строим свой service mesh / Иван Круглов (Booking.com)
SOA: строим свой service mesh / Иван Круглов (Booking.com)Ontico
 

Tendances (20)

Haystack
HaystackHaystack
Haystack
 
Technopolis.NoSQL 03 Cassandra
Technopolis.NoSQL 03 CassandraTechnopolis.NoSQL 03 Cassandra
Technopolis.NoSQL 03 Cassandra
 
Современная операционная система: что надо знать разработчику / Александр Кри...
Современная операционная система: что надо знать разработчику / Александр Кри...Современная операционная система: что надо знать разработчику / Александр Кри...
Современная операционная система: что надо знать разработчику / Александр Кри...
 
Мониторинг ожиданий в PostgreSQL / Курбангалиев Ильдус (Postgres Professional)
Мониторинг ожиданий в PostgreSQL / Курбангалиев Ильдус (Postgres Professional)Мониторинг ожиданий в PostgreSQL / Курбангалиев Ильдус (Postgres Professional)
Мониторинг ожиданий в PostgreSQL / Курбангалиев Ильдус (Postgres Professional)
 
DNS в условиях хостинг-провайдера / Константин Новаковский (Selectel)
DNS в условиях хостинг-провайдера / Константин Новаковский (Selectel)DNS в условиях хостинг-провайдера / Константин Новаковский (Selectel)
DNS в условиях хостинг-провайдера / Константин Новаковский (Selectel)
 
Реактивный раздатчик ok.ru/music
Реактивный раздатчик ok.ru/musicРеактивный раздатчик ok.ru/music
Реактивный раздатчик ok.ru/music
 
Строим сервисы на базе Nginx и Tarantool / Василий Сошников, Андрей Дроздов (...
Строим сервисы на базе Nginx и Tarantool / Василий Сошников, Андрей Дроздов (...Строим сервисы на базе Nginx и Tarantool / Василий Сошников, Андрей Дроздов (...
Строим сервисы на базе Nginx и Tarantool / Василий Сошников, Андрей Дроздов (...
 
Отказоустойчивая обработка 10M OAuth токенов на Tarantool / Владимир Перепели...
Отказоустойчивая обработка 10M OAuth токенов на Tarantool / Владимир Перепели...Отказоустойчивая обработка 10M OAuth токенов на Tarantool / Владимир Перепели...
Отказоустойчивая обработка 10M OAuth токенов на Tarantool / Владимир Перепели...
 
Mysql vs postgresql
Mysql vs postgresqlMysql vs postgresql
Mysql vs postgresql
 
Константин Осипов (Mail.Ru)
Константин Осипов (Mail.Ru)Константин Осипов (Mail.Ru)
Константин Осипов (Mail.Ru)
 
Чем заняться вечером, если я знаю сколько будет ++i + ++i / Андрей Бородин (Y...
Чем заняться вечером, если я знаю сколько будет ++i + ++i / Андрей Бородин (Y...Чем заняться вечером, если я знаю сколько будет ++i + ++i / Андрей Бородин (Y...
Чем заняться вечером, если я знаю сколько будет ++i + ++i / Андрей Бородин (Y...
 
Flashcache в mamba.ru / Яковлев Александр Юрьевич (ЗАО Мамба)
Flashcache в mamba.ru / Яковлев Александр Юрьевич (ЗАО Мамба)Flashcache в mamba.ru / Яковлев Александр Юрьевич (ЗАО Мамба)
Flashcache в mamba.ru / Яковлев Александр Юрьевич (ЗАО Мамба)
 
Что особенного в СУБД для данных в оперативной памяти / Константин Осипов (Ta...
Что особенного в СУБД для данных в оперативной памяти / Константин Осипов (Ta...Что особенного в СУБД для данных в оперативной памяти / Константин Осипов (Ta...
Что особенного в СУБД для данных в оперативной памяти / Константин Осипов (Ta...
 
Реализация восстановления после аварий / Сергей Бурладян (Avito)
Реализация восстановления после аварий / Сергей Бурладян (Avito)Реализация восстановления после аварий / Сергей Бурладян (Avito)
Реализация восстановления после аварий / Сергей Бурладян (Avito)
 
nginx.CHANGES.2015 / Игорь Сысоев, Валентин Бартенев (Nginx)
nginx.CHANGES.2015 / Игорь Сысоев, Валентин Бартенев (Nginx)nginx.CHANGES.2015 / Игорь Сысоев, Валентин Бартенев (Nginx)
nginx.CHANGES.2015 / Игорь Сысоев, Валентин Бартенев (Nginx)
 
Модульность и управляемая многопоточность встраиваемых С++ приложений - трудн...
Модульность и управляемая многопоточность встраиваемых С++ приложений - трудн...Модульность и управляемая многопоточность встраиваемых С++ приложений - трудн...
Модульность и управляемая многопоточность встраиваемых С++ приложений - трудн...
 
Отладка и устранение проблем в PostgreSQL Streaming Replication.
Отладка и устранение проблем в PostgreSQL Streaming Replication.Отладка и устранение проблем в PostgreSQL Streaming Replication.
Отладка и устранение проблем в PostgreSQL Streaming Replication.
 
Защита данных и датацентров от катастроф. Подход Nutanix / Максим Шапошников ...
Защита данных и датацентров от катастроф. Подход Nutanix / Максим Шапошников ...Защита данных и датацентров от катастроф. Подход Nutanix / Максим Шапошников ...
Защита данных и датацентров от катастроф. Подход Nutanix / Максим Шапошников ...
 
PostgreSQL: практические примеры оптимизации SQL-запросов / Иван Фролков (Po...
PostgreSQL: практические примеры оптимизации SQL-запросов /  Иван Фролков (Po...PostgreSQL: практические примеры оптимизации SQL-запросов /  Иван Фролков (Po...
PostgreSQL: практические примеры оптимизации SQL-запросов / Иван Фролков (Po...
 
SOA: строим свой service mesh / Иван Круглов (Booking.com)
SOA: строим свой service mesh / Иван Круглов (Booking.com)SOA: строим свой service mesh / Иван Круглов (Booking.com)
SOA: строим свой service mesh / Иван Круглов (Booking.com)
 

En vedette

Базы данных. HBase
Базы данных. HBaseБазы данных. HBase
Базы данных. HBaseVadim Tsesko
 
Multidimensional indexing
Multidimensional indexingMultidimensional indexing
Multidimensional indexingVadim Tsesko
 
Базы данных. ZooKeeper
Базы данных. ZooKeeperБазы данных. ZooKeeper
Базы данных. ZooKeeperVadim Tsesko
 
Базы данных. Cassandra
Базы данных. CassandraБазы данных. Cassandra
Базы данных. CassandraVadim Tsesko
 
Базы данных. HDFS
Базы данных. HDFSБазы данных. HDFS
Базы данных. HDFSVadim Tsesko
 
Базы данных. Distributed Commit
Базы данных. Distributed CommitБазы данных. Distributed Commit
Базы данных. Distributed CommitVadim Tsesko
 
Фреймворк Akka и его использование в Яндексе
Фреймворк Akka и его использование в ЯндексеФреймворк Akka и его использование в Яндексе
Фреймворк Akka и его использование в ЯндексеVadim Tsesko
 
Базы данных. CAP
Базы данных. CAPБазы данных. CAP
Базы данных. CAPVadim Tsesko
 
Actor model. Futures & Promises. Reactive Streams.
Actor model. Futures & Promises. Reactive Streams.Actor model. Futures & Promises. Reactive Streams.
Actor model. Futures & Promises. Reactive Streams.Vadim Tsesko
 
Потоковая фильтрация событий
Потоковая фильтрация событийПотоковая фильтрация событий
Потоковая фильтрация событийCEE-SEC(R)
 
YoctoDB в Яндекс.Вертикалях
YoctoDB в Яндекс.ВертикаляхYoctoDB в Яндекс.Вертикалях
YoctoDB в Яндекс.ВертикаляхCEE-SEC(R)
 

En vedette (13)

Базы данных. HBase
Базы данных. HBaseБазы данных. HBase
Базы данных. HBase
 
Actor model
Actor modelActor model
Actor model
 
Multidimensional indexing
Multidimensional indexingMultidimensional indexing
Multidimensional indexing
 
Базы данных. ZooKeeper
Базы данных. ZooKeeperБазы данных. ZooKeeper
Базы данных. ZooKeeper
 
Базы данных. Cassandra
Базы данных. CassandraБазы данных. Cassandra
Базы данных. Cassandra
 
Actor model
Actor modelActor model
Actor model
 
Базы данных. HDFS
Базы данных. HDFSБазы данных. HDFS
Базы данных. HDFS
 
Базы данных. Distributed Commit
Базы данных. Distributed CommitБазы данных. Distributed Commit
Базы данных. Distributed Commit
 
Фреймворк Akka и его использование в Яндексе
Фреймворк Akka и его использование в ЯндексеФреймворк Akka и его использование в Яндексе
Фреймворк Akka и его использование в Яндексе
 
Базы данных. CAP
Базы данных. CAPБазы данных. CAP
Базы данных. CAP
 
Actor model. Futures & Promises. Reactive Streams.
Actor model. Futures & Promises. Reactive Streams.Actor model. Futures & Promises. Reactive Streams.
Actor model. Futures & Promises. Reactive Streams.
 
Потоковая фильтрация событий
Потоковая фильтрация событийПотоковая фильтрация событий
Потоковая фильтрация событий
 
YoctoDB в Яндекс.Вертикалях
YoctoDB в Яндекс.ВертикаляхYoctoDB в Яндекс.Вертикалях
YoctoDB в Яндекс.Вертикалях
 

Similaire à Software Transactional Memory

20130429 dynamic c_c++_program_analysis-alexey_samsonov
20130429 dynamic c_c++_program_analysis-alexey_samsonov20130429 dynamic c_c++_program_analysis-alexey_samsonov
20130429 dynamic c_c++_program_analysis-alexey_samsonovComputer Science Club
 
Объектно-Ориентированное Программирование на C++, Лекции 3 и 4
Объектно-Ориентированное Программирование на C++, Лекции  3 и 4 Объектно-Ориентированное Программирование на C++, Лекции  3 и 4
Объектно-Ориентированное Программирование на C++, Лекции 3 и 4 Dima Dzuba
 
Встреча №9. Алгоритмы и коллекции стандартных библиотек C++, C#, Java, Object...
Встреча №9. Алгоритмы и коллекции стандартных библиотек C++, C#, Java, Object...Встреча №9. Алгоритмы и коллекции стандартных библиотек C++, C#, Java, Object...
Встреча №9. Алгоритмы и коллекции стандартных библиотек C++, C#, Java, Object...CocoaHeads
 
Семинар 5. Многопоточное программирование на OpenMP (часть 5)
Семинар 5. Многопоточное программирование на OpenMP (часть 5)Семинар 5. Многопоточное программирование на OpenMP (часть 5)
Семинар 5. Многопоточное программирование на OpenMP (часть 5)Mikhail Kurnosov
 
Статический анализ: вокруг Java за 60 минут
Статический анализ: вокруг Java за 60 минутСтатический анализ: вокруг Java за 60 минут
Статический анализ: вокруг Java за 60 минутAndrey Karpov
 
Лекция 8. Intel Threading Building Blocks
Лекция 8. Intel Threading Building BlocksЛекция 8. Intel Threading Building Blocks
Лекция 8. Intel Threading Building BlocksMikhail Kurnosov
 
Характерные черты функциональных языков программирования
Характерные черты функциональных языков программированияХарактерные черты функциональных языков программирования
Характерные черты функциональных языков программированияAlex.Kolonitsky
 
Spark: нетипичные примеры использования
Spark:  нетипичные примеры использованияSpark:  нетипичные примеры использования
Spark: нетипичные примеры использованияfaithlessfriend
 
Статический анализ кода: Что? Как? Зачем?
Статический анализ кода: Что? Как? Зачем?Статический анализ кода: Что? Как? Зачем?
Статический анализ кода: Что? Как? Зачем?Andrey Karpov
 
Лекция 12 (часть 2): Языки программирования семейства PGAS: IBM X10
Лекция 12 (часть 2): Языки программирования семейства PGAS: IBM X10Лекция 12 (часть 2): Языки программирования семейства PGAS: IBM X10
Лекция 12 (часть 2): Языки программирования семейства PGAS: IBM X10Mikhail Kurnosov
 
Лекция №5 "Обработка текстов, Naive Bayes"
Лекция №5 "Обработка текстов, Naive Bayes" Лекция №5 "Обработка текстов, Naive Bayes"
Лекция №5 "Обработка текстов, Naive Bayes" Technosphere1
 
Hacking PostgreSQL. Локальная память процессов. Контексты памяти.
Hacking PostgreSQL. Локальная память процессов. Контексты памяти.Hacking PostgreSQL. Локальная память процессов. Контексты памяти.
Hacking PostgreSQL. Локальная память процессов. Контексты памяти.Anastasia Lubennikova
 
ПВТ - весна 2015 - Лекция 5. Многопоточное программирование в С++. Синхрониза...
ПВТ - весна 2015 - Лекция 5. Многопоточное программирование в С++. Синхрониза...ПВТ - весна 2015 - Лекция 5. Многопоточное программирование в С++. Синхрониза...
ПВТ - весна 2015 - Лекция 5. Многопоточное программирование в С++. Синхрониза...Alexey Paznikov
 
Clojure: Lisp for the modern world (русская версия)
Clojure: Lisp for the modern world (русская версия)Clojure: Lisp for the modern world (русская версия)
Clojure: Lisp for the modern world (русская версия)Alex Ott
 
AlgoCollections (RUS)
AlgoCollections (RUS)AlgoCollections (RUS)
AlgoCollections (RUS)Anton Bukov
 
Алгоритмы и структуры данных осень 2013 лекция 2
Алгоритмы и структуры данных осень 2013 лекция 2Алгоритмы и структуры данных осень 2013 лекция 2
Алгоритмы и структуры данных осень 2013 лекция 2Technopark
 

Similaire à Software Transactional Memory (20)

20130429 dynamic c_c++_program_analysis-alexey_samsonov
20130429 dynamic c_c++_program_analysis-alexey_samsonov20130429 dynamic c_c++_program_analysis-alexey_samsonov
20130429 dynamic c_c++_program_analysis-alexey_samsonov
 
Объектно-Ориентированное Программирование на C++, Лекции 3 и 4
Объектно-Ориентированное Программирование на C++, Лекции  3 и 4 Объектно-Ориентированное Программирование на C++, Лекции  3 и 4
Объектно-Ориентированное Программирование на C++, Лекции 3 и 4
 
Встреча №9. Алгоритмы и коллекции стандартных библиотек C++, C#, Java, Object...
Встреча №9. Алгоритмы и коллекции стандартных библиотек C++, C#, Java, Object...Встреча №9. Алгоритмы и коллекции стандартных библиотек C++, C#, Java, Object...
Встреча №9. Алгоритмы и коллекции стандартных библиотек C++, C#, Java, Object...
 
Семинар 5. Многопоточное программирование на OpenMP (часть 5)
Семинар 5. Многопоточное программирование на OpenMP (часть 5)Семинар 5. Многопоточное программирование на OpenMP (часть 5)
Семинар 5. Многопоточное программирование на OpenMP (часть 5)
 
Scala for android
Scala for androidScala for android
Scala for android
 
Статический анализ: вокруг Java за 60 минут
Статический анализ: вокруг Java за 60 минутСтатический анализ: вокруг Java за 60 минут
Статический анализ: вокруг Java за 60 минут
 
Лекция 8. Intel Threading Building Blocks
Лекция 8. Intel Threading Building BlocksЛекция 8. Intel Threading Building Blocks
Лекция 8. Intel Threading Building Blocks
 
Характерные черты функциональных языков программирования
Характерные черты функциональных языков программированияХарактерные черты функциональных языков программирования
Характерные черты функциональных языков программирования
 
Spark: нетипичные примеры использования
Spark:  нетипичные примеры использованияSpark:  нетипичные примеры использования
Spark: нетипичные примеры использования
 
Intro to Swift techitout
Intro to Swift techitoutIntro to Swift techitout
Intro to Swift techitout
 
msumobi2. Лекция 1
msumobi2. Лекция 1msumobi2. Лекция 1
msumobi2. Лекция 1
 
Статический анализ кода: Что? Как? Зачем?
Статический анализ кода: Что? Как? Зачем?Статический анализ кода: Что? Как? Зачем?
Статический анализ кода: Что? Как? Зачем?
 
Лекция 12 (часть 2): Языки программирования семейства PGAS: IBM X10
Лекция 12 (часть 2): Языки программирования семейства PGAS: IBM X10Лекция 12 (часть 2): Языки программирования семейства PGAS: IBM X10
Лекция 12 (часть 2): Языки программирования семейства PGAS: IBM X10
 
Лекция №5 "Обработка текстов, Naive Bayes"
Лекция №5 "Обработка текстов, Naive Bayes" Лекция №5 "Обработка текстов, Naive Bayes"
Лекция №5 "Обработка текстов, Naive Bayes"
 
Hacking PostgreSQL. Локальная память процессов. Контексты памяти.
Hacking PostgreSQL. Локальная память процессов. Контексты памяти.Hacking PostgreSQL. Локальная память процессов. Контексты памяти.
Hacking PostgreSQL. Локальная память процессов. Контексты памяти.
 
ПВТ - весна 2015 - Лекция 5. Многопоточное программирование в С++. Синхрониза...
ПВТ - весна 2015 - Лекция 5. Многопоточное программирование в С++. Синхрониза...ПВТ - весна 2015 - Лекция 5. Многопоточное программирование в С++. Синхрониза...
ПВТ - весна 2015 - Лекция 5. Многопоточное программирование в С++. Синхрониза...
 
Clojure #2 (2014)
Clojure #2 (2014)Clojure #2 (2014)
Clojure #2 (2014)
 
Clojure: Lisp for the modern world (русская версия)
Clojure: Lisp for the modern world (русская версия)Clojure: Lisp for the modern world (русская версия)
Clojure: Lisp for the modern world (русская версия)
 
AlgoCollections (RUS)
AlgoCollections (RUS)AlgoCollections (RUS)
AlgoCollections (RUS)
 
Алгоритмы и структуры данных осень 2013 лекция 2
Алгоритмы и структуры данных осень 2013 лекция 2Алгоритмы и структуры данных осень 2013 лекция 2
Алгоритмы и структуры данных осень 2013 лекция 2
 

Software Transactional Memory

  • 1. Software Transactional Memory Курс «Базы данных» Цесько Вадим Александрович http://incubos.org @incubos Computer Science Center 9 декабря 2013 г. Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 1 / 63
  • 3. Введение Мотивация Мотивация Задача Множество изменяемых объектов в памяти Атомарность наборов операций с объектами Решение Software Transactional Memorya : Память как транзакционное хранилище Универсальная альтернатива ручным блокировкам ACI a http: //en.wikipedia.org/wiki/Software_transactional_memory Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 3 / 63
  • 4. Введение Идея Идея (Очень) оптимистичные транзакции Если прочитанные значения не менялись, то commit В противном случае — retry Возможен abort в любой момент Как следствие – max concurrency Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 4 / 63
  • 5. Введение Идея Ручные блокировки Нужно думать о перекрывающихся операциях Нужно «держать в голове» весь код Deadlocks, livelocks, progress, etc. Очень трудно воспроизвести и отладить Priority inversion1 1 http://en.wikipedia.org/wiki/Priority_inversion Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 5 / 63
  • 6. Введение Идея Подход STM Simple Maintainable Composable Не нужно думать о deadlocks и livelocks Priority inversion — abort низкоприоритетной транзакции Но (почти) недопустимы side effects (в т. ч. IO) Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 6 / 63
  • 7. Введение Реализации Реализации Множество реализаций для всех языков Встроено в Clojure ScalaSTM2 2 http://nbronson.github.io/scala-stm/ Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 7 / 63
  • 8. Введение Реализации Scala STM Expert Group Akka Stanford Tel-Aviv University EPFL Cisco etc. Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 8 / 63
  • 9. Введение ScalaSTM С высоты птичьего полёта Живёт между atomic-блоком и Heap Перехватывает чтения и записи Чтения и записи из разных потоков перемешались — rollback записей и retry Иначе — commit Видны только закоммиченые изменения Принимаем во внимание только Refы Реализация в виде библиотеки TSet и TMap Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 9 / 63
  • 10. Введение ScalaSTM Достоинства Say what you mean (nested) atomic Readers scale CPU cache friendly Exceptions automatically trigger cleanup By default Waiting for complex conditions is easy retry, chaining Simple Just a library Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 10 / 63
  • 11. Введение ScalaSTM Недостатки Two extra characters per read or write x: Ref Read: x() Write: x() = y Single-thread overheads Но полезен rollback при исключениях Rollback doesn’t mix well with I/O Но есть хуки Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 11 / 63
  • 12. Примеры API Basic 1 import scala.concurrent.stm._ 2 3 4 5 val x = Ref(0) // allocate a Ref[Int] val y = Ref.make[String]() // type-specific default val z = x.single // Ref.View[Int] 6 7 8 9 10 11 12 13 14 15 16 atomic { implicit txn => val i = x() // read y() = "x was " + i // write val eq = atomic { implicit txn => // nested atomic // both Ref and Ref.View can be used inside atomic x() == z() } assert(eq) y.set(y.get + ", long-form access") } Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 12 / 63
  • 13. Примеры API Advanced 1 2 3 // only Ref.View can be used outside atomic println("y was ’" + y.single() + "’") println("z was " + z()) 4 5 6 7 8 9 10 11 atomic { implicit txn => y() = y() + ", first alternative" if (x getWith { _ > 0 }) // read via a function retry // try alternatives or block } orAtomic { implicit txn => y() = y() + ", second alternative" } 12 13 14 15 16 17 val prev = z.swap(10) // atomic swap val success = z.compareAndSet(10, 11) // atomic compare-and-set z.transform { _ max 20 } // atomic transformation val pre = y.single.getAndTransform { _.toUpperCase } val post = y.single.transformAndGet { _.filterNot { _ == ’ ’ } } Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 13 / 63
  • 14. Примеры Doubly-linked list Use Ref for shared variables 1 import scala.concurrent.stm._ 2 3 4 5 6 7 8 9 10 11 class ConcurrentIntList { private class Node( val elem: Int, prev0: Node, next0: Node) { val isHeader = prev0 == null val prev = Ref(if (isHeader) this else prev0) val next = Ref(if (isHeader) this else next0) } 12 13 private val header = new Node(-1, null, null) Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 14 / 63
  • 15. Примеры Doubly-linked list Wrap your code in atomic 1 2 3 4 5 6 7 8 def addLast(elem: Int) { atomic { implicit txn => val p = header.prev() val newNode = new Node(elem, p, header) p.next() = newNode header.prev() = newNode } } Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 15 / 63
  • 16. Примеры Doubly-linked list Compose atomic operations 1 2 3 4 5 6 7 def addLast(e1: Int, e2: Int, elems: Int*) { atomic { implicit txn => addLast(e1) addLast(e2) elems foreach { addLast(_) } } } Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 16 / 63
  • 17. Примеры Doubly-linked list Optimize single-operation transactions Ref.View: Получение через Ref.single Можно использовать вне atomic Поддерживает транзакции из одной операции swap, compareAndSet, transform, etc. Пример: 1 2 3 4 5 /* def isEmpty = atomic { implicit t => header.next() == header } */ 6 7 def isEmpty = header.next.single() == header Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 17 / 63
  • 18. Примеры Doubly-linked list Wait for conditions to change 1 2 3 4 5 6 7 8 9 10 def removeFirst(): Int = atomic { implicit txn => val n = header.next() if (n == header) retry val nn = n.next() header.next() = nn nn.prev() = header n.elem } Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 18 / 63
  • 19. Примеры Doubly-linked list Wait for multiple events 1 2 3 4 5 6 7 def maybeRemoveFirst(): Option[Int] = { atomic { implicit txn => Some(removeFirst()) } orAtomic { implicit txn => None } } Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 19 / 63
  • 20. Примеры Doubly-linked list Composition: select 1 2 3 4 5 6 7 8 9 10 11 12 object ConcurrentIntList { def select(stacks: ConcurrentIntList*): (ConcurrentIntList, Int) = atomic { implicit txn => for (s <− stacks) { s.maybeRemoveFirst() match { case Some(e) => return (s -> e) case None => _ } } retry } Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 20 / 63
  • 21. Примеры Doubly-linked list Be careful about rollback (1) 1 2 3 4 5 6 7 8 9 10 11 12 def badToString: String = { val buf = new StringBuilder("ConcurrentIntList(") atomic { implicit txn => var n = header.next() while (n != header) { buf ++= n.elem.toString n = n.next() if (n != header) buf ++= "," } } buf ++= ")" toString } Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 21 / 63
  • 22. Примеры Doubly-linked list Be careful about rollback (2) 1 2 3 4 5 6 7 8 9 10 11 12 override def toString: String = { atomic { implicit txn => val buf = new StringBuilder("ConcurrentIntList(") var n = header.next() while (n != header) { buf ++= n.elem.toString n = n.next() if (n != header) buf ++= "," } buf ++= ")" toString } } Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 22 / 63
  • 23. Примеры Indexed Map Цель In-memory DB User-defined indices Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 23 / 63
  • 24. Примеры Indexed Map API 1 2 3 4 5 6 7 8 9 10 11 12 13 14 scala> case class User(id: Int, name: String, likes: Set[String]) scala> val m = new IndexedMap[Int, User] scala> m.put(10, User(10, "alice", Set("scala", "climbing"))) res0: Option[User] = None scala> val byName = m.addIndex { (id,u) => Some(u.name) } byName: (String) => Map[Int,User] = <function1> scala> val byLike = m.addIndex { (id,u) => u.likes } byLike: (String) => Map[Int,User] = <function1> scala> m.put(11, User(11, "bob", Set("scala", "skiing"))) res1: Option[User] = None scala> byName("alice") res2: Map[Int,User] = Map((10,User(10,alice,Set(scala, climbing)))) scala> byLike("scala").values map { _.name } res3: Iterable[String] = List(alice, bob) Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 24 / 63
  • 25. Примеры Indexed Map A high-level sketch 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import scala.concurrent.stm._ class IndexedMap[A, B] { private val contents = TMap.empty[A, B] // TODO def addIndex(view: ?): ? def get(key: A): Option[B] = contents.single.get(key) def put(key: A, value: B): Option[B] = atomic { implicit txn => val prev = contents.put(key, value) // TODO: update indices prev } def remove(key: A): Option[B] = atomic { implicit txn => val prev = contents.remove(key) // TODO: update indices prev } } Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 25 / 63
  • 26. Примеры Indexed Map Types for the view function and index Помедитируем: 1 2 def addIndex(view: ((A, B) => Iterable[C])): (C => Map[A, B]) = ... Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 26 / 63
  • 27. Примеры Indexed Map Tracking and updating indices (1) 1 2 3 4 5 private class Index[C](view: (A, B) => Iterable[C]) extends (C => Map[A, B]) { def += (kv: (A, B)) // TODO def -= (kv: (A, B)) // TODO } 6 7 private val indices = Ref(List.empty[Index[_]]) 8 9 10 11 12 13 14 15 16 def addIndex[C](view: (A, B) => Iterable[C]): (C => Map[A, B]) = atomic { implicit txn => val index = new Index(view) indices() = index :: indices() contents foreach { index += _ } index } Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 27 / 63
  • 28. Примеры Indexed Map Tracking and updating indices (2) 1 2 3 4 5 6 7 def put(key: A, value: B): Option[B] = atomic { implicit txn => val prev = contents.put(key, value) for (p <− prev; i <− indices()) i -= (key -> p) for (i <− indices()) i += (key -> value) prev } 8 9 10 11 12 13 14 def remove(key: A): Option[B] = atomic { implicit txn => val prev = contents.remove(key) for (p <− prev; i <− indices()) i -= (key -> p) prev } Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 28 / 63
  • 29. Примеры Indexed Map Index internals 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 private class Index[C](view: (A, B) => Iterable[C]) extends (C => Map[A, B]) { val mapping = TMap.empty[C, Map[A, B]] def apply(derived: C) = mapping.single.getOrElse(derived, Map.empty[A, B]) def += (kv: (A, B))(implicit txn: InTxn) { for (c <− view(kv._1, kv._2)) mapping(c) = apply(c) + kv } def -= (kv: (A, B))(implicit txn: InTxn) { for (c <− view(kv._1, kv._2)) { val after = mapping(c) - kv._1 if (after.isEmpty) mapping -= c else mapping(c) = after } } Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 29 / 63
  • 30. Примеры Dining Philosophers Проблема Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 30 / 63
  • 31. Примеры Dining Philosophers STM solution 1 class Fork { val inUse = Ref(false) } 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 def meal(left: Fork, right: Fork) { // thinking atomic { implicit txn => if (left.inUse() || right.inUse()) retry // forks are not both ready, wait left.inUse() = true right.inUse() = true } // eating atomic { implicit txn => left.inUse() = false right.inUse() = false } } Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 31 / 63
  • 32. Internals Waiting Waiting retry в atomic ≈ wait() в synchronized, но retry: Безопаснее STM определяет модификации Ref, ведущие к пробуждению (вместо notifyAll) Невозможны «потерянные» пробуждения Эффективнее Нет «лишних» пробуждений Можно ожидать на любых условиях, а не только на предопределённых Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 32 / 63
  • 33. Internals Waiting Search with backtracking (1) Optimistic concurrency control as a search with backtracking: 1 val (x, y) = (Ref(10), Ref(0)) 2 3 4 5 6 7 def sum = atomic { implicit txn => val a = x() val b = y() a + b } 8 9 10 11 12 13 14 def transfer(n: Int) { atomic { implicit txn => x -= n y += n } } Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 33 / 63
  • 34. Internals Waiting Search with backtracking (2) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 // sum atomic | begin txn | | read x | | : | | | | : | | | | read y | roll back | begin txn | | read x | | read y | commit +-> 10 attempt -> 10 -> x read is invalid // transfer(2) atomic | begin txn attempt | | read x -> 10 | | write x <− 8 | | read y -> 0 | | write y <− 2 | commit +-> () attempt -> 8 -> 2 Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 34 / 63
  • 35. Internals Waiting Retry. Семантика Вызов retry — сигнал о dead end, даже если все чтения и записи консистентны STM откатится и попробует снова Если некоторые из прочитанных Refов изменились, то atomic блок может пойти по другому пути и избежать retry Условие ожидания retry Неявно задано потоком управления в atomic-блоке Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 35 / 63
  • 36. Internals Waiting Retry. Эффективность Примеры: if (x() <= 10) retry if (x() == 0 && y() == 0 && z() == 0) retry Реализация: STM отслеживает, к каким Refам обращались Под капотом — блокирующиеся конструкции retry: Nothing Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 36 / 63
  • 37. Internals Waiting Alternatives orAtomic/atomic.oneOf: Несколько путей поиска Первый заканчивается retry — откат и идём по второму и т. д. Учитывается только явный retry (а не неконсистентные чтения) Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 37 / 63
  • 38. Internals Waiting Alternatives. Пример 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 val msg = atomic { implicit txn => if (x() == 0) retry x -= 1 "took one from x" } orAtomic { implicit txn => if (y() == 0) retry y -= 1 "took one from y" } orAtomic { implicit txn => if (z() == 0) retry z -= 1 "took one from z" } Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 38 / 63
  • 39. Internals Waiting Timeouts Зачем timeout при retry: Error logging/handling No work — waiting thread shutdown Timeouts in spec of higher-level interface Способы ограничения retry: Модифицированный TxnExecutor (InterruptedException) retryFor() Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 39 / 63
  • 40. Internals Waiting Timeouts. TxnExecutor 1 2 3 atomic.withRetryTimeout(1000) { implicit txn => // any retries in this atomic block will wait for at most 1000 milliseconds } 4 5 6 7 8 9 val myAtomic = atomic.withRetryTimeout(1, TimeUnit.SECONDS) myAtomic { implicit txn => // this atomic block has a timeout of 1 seconds } myAtomic { ... } 10 11 12 13 14 TxnExecutor.transformDefault( _.withRetryTimeout(1000) ) atomic { implicit txn => // all atomic blocks now default to a 1 second timeout } Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 40 / 63
  • 41. Internals Waiting Timeouts. retryFor(timeout) 1 2 3 4 5 6 7 val instance = atomic { implicit txn => if (!pool.hasAvailable) { retryFor(100) pool.grow() } pool.take() } Сигнатура 1 retryFor(...): Unit 1 retry: Nothing Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 41 / 63
  • 42. Internals Waiting Timeouts. Views Можно блокироваться на Ref.View: Ref.View.await(pred): Unit Ref.View.tryAwait(duration)(pred): Boolean Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 42 / 63
  • 43. Internals Maps + Sets Maps + Sets Консистентные итераторы у TMap.View и TSet.View Быстрые слепки за O(1) Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 43 / 63
  • 44. Internals Maps + Sets Consistent iteration TMap.View extends mutable.MapLike get()/put() outside atomic should be atomic TMap.View.iterator/TSet.View.iterator для атомарного слепка Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 44 / 63
  • 45. Internals Maps + Sets Inconsistent iteration 1 val m = TMap("one" -> 1).single 2 3 4 5 6 7 8 (new Thread { override def run { atomic { implicit txn => m -= "one" m += ("ONE" -> 1) } } }).start 9 10 for ((k, v) <− m; if v == 1) println(k) Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 45 / 63
  • 46. Internals Maps + Sets Manual snapshots <TMap|TSet>[.View].snapshot() возвращает immutable.Map/immutable.Set <TMap|TSet>.clone() Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 46 / 63
  • 47. Internals Maps + Sets How does it work? Mutable hash tries from Refs with generation numbers that control copy-on-write N. G. Bronson, J. Casper, H. Chafi and K. Olukotun. A Practical Concurrent Binary Search Tree. 2010. N. G. Bronson, J. Casper, H. Chafi and K. Olukotun. Transactional Predication: High-Performance Concurrent Sets and Maps for STM. In PODC’10: Proceedings of the 29th Annual ACM Conference on Principles of Distributed Computing, 2010. N. G. Bronson. Composable Operations on High-Performance Concurrent Collections. Ph.D. Dissertation, Stanford University, 2011. Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 47 / 63
  • 48. Internals Exceptions Exceptions Exception ⇒ rollback + rethrow scala.util.control.ControlThrowable ⇒ commit + rethrow Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 48 / 63
  • 49. Internals Exceptions Exceptions and nesting 1 2 3 4 5 6 7 8 9 10 11 12 val last = Ref("none") atomic { implicit txn => last() = "outer" try { atomic { implicit txn => last() = "inner" throw new RuntimeException } } catch { case _: RuntimeException => } } Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 49 / 63
  • 50. Заключение Benchmarking Benchmarking TL;DR Немного медленнее в однопоточном режиме по сравнению с хитрыми блокировками Лучше масштабируется по ядрам/нитям Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 50 / 63
  • 51. Заключение Benchmarking STMBench7 R. Guerraoui, M. Kapalka and J. Vitek. STMBench7: A Benchmark for Software Transactional Memory. 2007. A. Dragojevic, R. Guerraoui and M. Kapalka. Dividing Transactional Memories by Zero. 2008. Comparison to coarse- and medium-grained locking See the details4 4 http://nbronson.github.io/scala-stm/benchmark.html Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 51 / 63
  • 52. Заключение Benchmarking Read Dominated Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 52 / 63
  • 53. Заключение Benchmarking Write Dominated Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 53 / 63
  • 54. Заключение Benchmarking Read + Write Mix Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 54 / 63
  • 55. Заключение Benchmarking Read + Write Mix GC Rate Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 55 / 63
  • 56. Заключение Benchmarking Read + Write Mix GC Load Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 56 / 63
  • 57. Заключение Bibliography Bibliography F. T. Schneider, V. Menon, T. Shpeisman, and A.-R. Adl-Tabatabai. Dynamic Optimization for Efficient Strong Atomicity. 2008. N. G. Bronson, C. Kozyrakis and K. Olukotun. Feedback-Directed Barrier Optimization in a Strongly Isolated STM. 2009 V. Menon, S. Balensieger, T. Shpeisman, A.-R. Adl-Tabatabai, R. L. Hudson, B. Saha and A. Welc. Practical Weak-Atomicity Semantics for Java STM. 2008. K. F. Moore and D. Grossman. High-Level Small-Step Operational Semantics for transactions. 2008. Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 57 / 63
  • 58. Заключение Bibliography continued Bibliography continued T. Harris, S. Marlow, S. Peyton-Jones and M. Herlihy. Composable Memory Transactions. 2005. R. Hickey. The Clojure Programming Language. 2008 D. Dice, O. Shalev and N. Shavit. Transactional Locking II. 2006. T. Riegel, P. Felber and C. Fetzer. A Lazy Snapshot Algorithm with Eager Validation. 2006. R. Guerraoui and M. Kapalka. On the Correctness of Transactional Memory. 2008. A. Dragojevic, R. Guerraoui and M. Kapalka. Stretching Transactional Memory. 2009. Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 58 / 63
  • 59. Заключение Куда двигаться дальше Куда двигаться дальше Herb Sutter. The Free Lunch Is Over. 2009. Jonas Bon´r. State: You’re Doing It Wrong — e Alternative Concurrency Paradigms For The JVM5 . JavaOne 2009. ScalaDays 2013. Concurrency — The good, the bad, the ugly6 Chris Okasaki. Purely Functional Data Structures. 1999 JCIP 2nd edition + JMM 5 http://www.slideshare.net/jboner/ state-youre-doing-it-wrong-javaone-2009 6 http://www.parleys.com/play/51c0bc58e4b0ed877035680a/ Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 59 / 63
  • 60. Домашнее задание Получили зачёт Получили зачёт Ершов В. Суворов Е. Фёдоров К. Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 60 / 63
  • 61. Домашнее задание Могут получить зачёт Могут получить зачёт Бакрадзе Л. Грязнов С. Егоров Д. Королев Д. Хомутов В. Шашкова Е. Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 61 / 63
  • 62. Домашнее задание Last Feature Requests Last Feature Requests 2013-11-18 2013-11-25 2013-12-02 Batches 2013-12-09 Processing 7 FR8: Redis Hashes7 FR9: Compression FR10: Multithreaded Node + Atomic FR11: Server Side Filtering and http://redis.io/commands#hash Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 62 / 63
  • 63. Вопросы? Вопросы? http://incubos.org/contacts/ Общие вопросы — в Twitter: @incubos Вопросы по лекциям — в комментариях: http://incubos.org/blog/ Частные вопросы — в почту vadim.tsesko@gmail.com Цесько В. А. (CompSciCenter) STM 9 декабря 2013 г. 63 / 63