ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
* [ruby-core:101956] [Ruby master Feature#12607] Ruby needs an atomic integer
       [not found] <redmine.issue-12607.20160721050407.10@ruby-lang.org>
@ 2021-01-06 12:06 ` eregontp
  2021-01-06 15:17 ` [ruby-core:101962] " dsisnero
                   ` (16 subsequent siblings)
  17 siblings, 0 replies; 18+ messages in thread
From: eregontp @ 2021-01-06 12:06 UTC (permalink / raw)
  To: ruby-core

Issue #12607 has been updated by Eregon (Benoit Daloze).


FWIW, I think an atomic integer makes sense in core, because it's easier to optimize it that way.
But, since it seems a lot nicer to support fixnums and bignums (not just fixnums), and notably the Integer class is now used for both, I think the better thing to expose is an AtomicReference.
As an added benefit, that has other usages and notably adds a general compare-and-swap operation.

TruffleRuby for instance has such a class, which is currently by concurrent-ruby:
https://github.com/oracle/truffleruby/blob/07d62320c0d83efd6f7f99a805d6f61d1e03d60d/doc/user/truffleruby-additions.md#atomic-references
https://github.com/oracle/truffleruby/blob/07d62320c0d83efd6f7f99a805d6f61d1e03d60d/src/main/ruby/truffleruby/core/truffle/truffleruby.rb#L23-L51

----------------------------------------
Feature #12607: Ruby needs an atomic integer
https://bugs.ruby-lang.org/issues/12607#change-89809

* Author: shyouhei (Shyouhei Urabe)
* Status: Feedback
* Priority: Normal
* Assignee: ko1 (Koichi Sasada)
----------------------------------------
(This one was derived from bug #12463)

Although I don't think += would become atomic, at the same time I understand Rodrigo's needs of _easier_ counter variable that resists inter-thread tampering.  I don't think ruby's Integer class can be used for that purpose for reasons (mainly because it is not designed with threads in mind).  Rather we should introduce a integer class which is carefully designed.

Why not import Concurrent::AtomicFixnum into core?



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [ruby-core:101962] [Ruby master Feature#12607] Ruby needs an atomic integer
       [not found] <redmine.issue-12607.20160721050407.10@ruby-lang.org>
  2021-01-06 12:06 ` [ruby-core:101956] [Ruby master Feature#12607] Ruby needs an atomic integer eregontp
@ 2021-01-06 15:17 ` dsisnero
  2021-01-12  7:54 ` [ruby-core:102026] " ko1
                   ` (15 subsequent siblings)
  17 siblings, 0 replies; 18+ messages in thread
From: dsisnero @ 2021-01-06 15:17 UTC (permalink / raw)
  To: ruby-core

Issue #12607 has been updated by dsisnero (Dominic Sisneros).


I agree this should be added to core because of ractor  and #17433.  

----------------------------------------
Feature #12607: Ruby needs an atomic integer
https://bugs.ruby-lang.org/issues/12607#change-89815

* Author: shyouhei (Shyouhei Urabe)
* Status: Feedback
* Priority: Normal
* Assignee: ko1 (Koichi Sasada)
----------------------------------------
(This one was derived from bug #12463)

Although I don't think += would become atomic, at the same time I understand Rodrigo's needs of _easier_ counter variable that resists inter-thread tampering.  I don't think ruby's Integer class can be used for that purpose for reasons (mainly because it is not designed with threads in mind).  Rather we should introduce a integer class which is carefully designed.

Why not import Concurrent::AtomicFixnum into core?



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [ruby-core:102026] [Ruby master Feature#12607] Ruby needs an atomic integer
       [not found] <redmine.issue-12607.20160721050407.10@ruby-lang.org>
  2021-01-06 12:06 ` [ruby-core:101956] [Ruby master Feature#12607] Ruby needs an atomic integer eregontp
  2021-01-06 15:17 ` [ruby-core:101962] " dsisnero
@ 2021-01-12  7:54 ` ko1
  2021-01-12 11:13 ` [ruby-core:102031] " eregontp
                   ` (14 subsequent siblings)
  17 siblings, 0 replies; 18+ messages in thread
From: ko1 @ 2021-01-12  7:54 UTC (permalink / raw)
  To: ruby-core

Issue #12607 has been updated by ko1 (Koichi Sasada).


I believe introducing STM https://bugs.ruby-lang.org/issues/17261 is more general for this purpose.

----------------------------------------
Feature #12607: Ruby needs an atomic integer
https://bugs.ruby-lang.org/issues/12607#change-89878

* Author: shyouhei (Shyouhei Urabe)
* Status: Feedback
* Priority: Normal
* Assignee: ko1 (Koichi Sasada)
----------------------------------------
(This one was derived from bug #12463)

Although I don't think += would become atomic, at the same time I understand Rodrigo's needs of _easier_ counter variable that resists inter-thread tampering.  I don't think ruby's Integer class can be used for that purpose for reasons (mainly because it is not designed with threads in mind).  Rather we should introduce a integer class which is carefully designed.

Why not import Concurrent::AtomicFixnum into core?



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [ruby-core:102031] [Ruby master Feature#12607] Ruby needs an atomic integer
       [not found] <redmine.issue-12607.20160721050407.10@ruby-lang.org>
                   ` (2 preceding siblings ...)
  2021-01-12  7:54 ` [ruby-core:102026] " ko1
@ 2021-01-12 11:13 ` eregontp
  2021-01-13  7:32 ` [ruby-core:102056] " ko1
                   ` (13 subsequent siblings)
  17 siblings, 0 replies; 18+ messages in thread
From: eregontp @ 2021-01-12 11:13 UTC (permalink / raw)
  To: ruby-core

Issue #12607 has been updated by Eregon (Benoit Daloze).


ko1 (Koichi Sasada) wrote in #note-24:
> I believe introducing STM https://bugs.ruby-lang.org/issues/17261 is more general for this purpose.

True, but an atomic integer remains useful even if there is an STM.
An STM is overkill and much slower if all someone wants is atomic counters.

----------------------------------------
Feature #12607: Ruby needs an atomic integer
https://bugs.ruby-lang.org/issues/12607#change-89885

* Author: shyouhei (Shyouhei Urabe)
* Status: Feedback
* Priority: Normal
* Assignee: ko1 (Koichi Sasada)
----------------------------------------
(This one was derived from bug #12463)

Although I don't think += would become atomic, at the same time I understand Rodrigo's needs of _easier_ counter variable that resists inter-thread tampering.  I don't think ruby's Integer class can be used for that purpose for reasons (mainly because it is not designed with threads in mind).  Rather we should introduce a integer class which is carefully designed.

Why not import Concurrent::AtomicFixnum into core?



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [ruby-core:102056] [Ruby master Feature#12607] Ruby needs an atomic integer
       [not found] <redmine.issue-12607.20160721050407.10@ruby-lang.org>
                   ` (3 preceding siblings ...)
  2021-01-12 11:13 ` [ruby-core:102031] " eregontp
@ 2021-01-13  7:32 ` ko1
  2021-01-13 18:05 ` [ruby-core:102070] " daniel
                   ` (12 subsequent siblings)
  17 siblings, 0 replies; 18+ messages in thread
From: ko1 @ 2021-01-13  7:32 UTC (permalink / raw)
  To: ruby-core

Issue #12607 has been updated by ko1 (Koichi Sasada).


Eregon (Benoit Daloze) wrote in #note-25:
> True, but an atomic integer remains useful even if there is an STM.
> An STM is overkill and much slower if all someone wants is atomic counters.

TVar proposed in https://bugs.ruby-lang.org/issues/17261 has `#increment` method and it is enough fast.

----------------------------------------
Feature #12607: Ruby needs an atomic integer
https://bugs.ruby-lang.org/issues/12607#change-89912

* Author: shyouhei (Shyouhei Urabe)
* Status: Feedback
* Priority: Normal
* Assignee: ko1 (Koichi Sasada)
----------------------------------------
(This one was derived from bug #12463)

Although I don't think += would become atomic, at the same time I understand Rodrigo's needs of _easier_ counter variable that resists inter-thread tampering.  I don't think ruby's Integer class can be used for that purpose for reasons (mainly because it is not designed with threads in mind).  Rather we should introduce a integer class which is carefully designed.

Why not import Concurrent::AtomicFixnum into core?



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [ruby-core:102070] [Ruby master Feature#12607] Ruby needs an atomic integer
       [not found] <redmine.issue-12607.20160721050407.10@ruby-lang.org>
                   ` (4 preceding siblings ...)
  2021-01-13  7:32 ` [ruby-core:102056] " ko1
@ 2021-01-13 18:05 ` daniel
  2021-01-13 21:45 ` [ruby-core:102074] " chris
                   ` (11 subsequent siblings)
  17 siblings, 0 replies; 18+ messages in thread
From: daniel @ 2021-01-13 18:05 UTC (permalink / raw)
  To: ruby-core

Issue #12607 has been updated by Dan0042 (Daniel DeLorme).


What is the use case for this atomic integer? I sometimes have a use for an atomic monotonically increasing counter, but that could be satisfied with a very simple API like `n = MyCounter.next`
On the other hand I've never felt the need for decrement or reset or in fact any integer atomic operations other than `+= 1`
2¢

----------------------------------------
Feature #12607: Ruby needs an atomic integer
https://bugs.ruby-lang.org/issues/12607#change-89931

* Author: shyouhei (Shyouhei Urabe)
* Status: Feedback
* Priority: Normal
* Assignee: ko1 (Koichi Sasada)
----------------------------------------
(This one was derived from bug #12463)

Although I don't think += would become atomic, at the same time I understand Rodrigo's needs of _easier_ counter variable that resists inter-thread tampering.  I don't think ruby's Integer class can be used for that purpose for reasons (mainly because it is not designed with threads in mind).  Rather we should introduce a integer class which is carefully designed.

Why not import Concurrent::AtomicFixnum into core?



-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [ruby-core:102074] [Ruby master Feature#12607] Ruby needs an atomic integer
       [not found] <redmine.issue-12607.20160721050407.10@ruby-lang.org>
                   ` (5 preceding siblings ...)
  2021-01-13 18:05 ` [ruby-core:102070] " daniel
@ 2021-01-13 21:45 ` chris
  2021-01-13 22:40 ` [ruby-core:102075] " marcandre-ruby-core
                   ` (10 subsequent siblings)
  17 siblings, 0 replies; 18+ messages in thread
From: chris @ 2021-01-13 21:45 UTC (permalink / raw)
  To: ruby-core

Issue #12607 has been updated by chrisseaton (Chris Seaton).


> What is the use case for this atomic integer?

For example for issuing unique IDs across multiple Ractors.

> or in fact any integer atomic operations other than += 1

For example a CAS to update a bank balance is a common requirement.

----------------------------------------
Feature #12607: Ruby needs an atomic integer
https://bugs.ruby-lang.org/issues/12607#change-89934

* Author: shyouhei (Shyouhei Urabe)
* Status: Feedback
* Priority: Normal
* Assignee: ko1 (Koichi Sasada)
----------------------------------------
(This one was derived from bug #12463)

Although I don't think += would become atomic, at the same time I understand Rodrigo's needs of _easier_ counter variable that resists inter-thread tampering.  I don't think ruby's Integer class can be used for that purpose for reasons (mainly because it is not designed with threads in mind).  Rather we should introduce a integer class which is carefully designed.

Why not import Concurrent::AtomicFixnum into core?



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [ruby-core:102075] [Ruby master Feature#12607] Ruby needs an atomic integer
       [not found] <redmine.issue-12607.20160721050407.10@ruby-lang.org>
                   ` (6 preceding siblings ...)
  2021-01-13 21:45 ` [ruby-core:102074] " chris
@ 2021-01-13 22:40 ` marcandre-ruby-core
  2021-01-13 23:45 ` [ruby-core:102076] " chris
                   ` (9 subsequent siblings)
  17 siblings, 0 replies; 18+ messages in thread
From: marcandre-ruby-core @ 2021-01-13 22:40 UTC (permalink / raw)
  To: ruby-core

Issue #12607 has been updated by marcandre (Marc-Andre Lafortune).


chrisseaton (Chris Seaton) wrote in #note-28:
> > What is the use case for this atomic integer?
> 
> For example for issuing unique IDs across multiple Ractors.

You can achieve something similar with `Object.new.object_id`

> > or in fact any integer atomic operations other than += 1
> 
> For example a CAS to update a bank balance is a common requirement.

Why atomic though... This can all be achieved with a Ractor.

----------------------------------------
Feature #12607: Ruby needs an atomic integer
https://bugs.ruby-lang.org/issues/12607#change-89935

* Author: shyouhei (Shyouhei Urabe)
* Status: Feedback
* Priority: Normal
* Assignee: ko1 (Koichi Sasada)
----------------------------------------
(This one was derived from bug #12463)

Although I don't think += would become atomic, at the same time I understand Rodrigo's needs of _easier_ counter variable that resists inter-thread tampering.  I don't think ruby's Integer class can be used for that purpose for reasons (mainly because it is not designed with threads in mind).  Rather we should introduce a integer class which is carefully designed.

Why not import Concurrent::AtomicFixnum into core?



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [ruby-core:102076] [Ruby master Feature#12607] Ruby needs an atomic integer
       [not found] <redmine.issue-12607.20160721050407.10@ruby-lang.org>
                   ` (7 preceding siblings ...)
  2021-01-13 22:40 ` [ruby-core:102075] " marcandre-ruby-core
@ 2021-01-13 23:45 ` chris
  2021-01-14  2:25 ` [ruby-core:102079] " daniel
                   ` (8 subsequent siblings)
  17 siblings, 0 replies; 18+ messages in thread
From: chris @ 2021-01-13 23:45 UTC (permalink / raw)
  To: ruby-core

Issue #12607 has been updated by chrisseaton (Chris Seaton).


> You can achieve something similar with Object.new.object_id

You may want them to be consecutive.

> Why atomic though... This can all be achieved with a Ractor.

A Ractor send has relatively high synchronisation overhead - an atomic integer is conventionally implemented at the cache-coherence level and is lock-free.

I can only offer that I use atomic integers for many things fairly frequently in my working life.

----------------------------------------
Feature #12607: Ruby needs an atomic integer
https://bugs.ruby-lang.org/issues/12607#change-89936

* Author: shyouhei (Shyouhei Urabe)
* Status: Feedback
* Priority: Normal
* Assignee: ko1 (Koichi Sasada)
----------------------------------------
(This one was derived from bug #12463)

Although I don't think += would become atomic, at the same time I understand Rodrigo's needs of _easier_ counter variable that resists inter-thread tampering.  I don't think ruby's Integer class can be used for that purpose for reasons (mainly because it is not designed with threads in mind).  Rather we should introduce a integer class which is carefully designed.

Why not import Concurrent::AtomicFixnum into core?



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [ruby-core:102079] [Ruby master Feature#12607] Ruby needs an atomic integer
       [not found] <redmine.issue-12607.20160721050407.10@ruby-lang.org>
                   ` (8 preceding siblings ...)
  2021-01-13 23:45 ` [ruby-core:102076] " chris
@ 2021-01-14  2:25 ` daniel
  2021-01-14  2:34 ` [ruby-core:102080] " chris
                   ` (7 subsequent siblings)
  17 siblings, 0 replies; 18+ messages in thread
From: daniel @ 2021-01-14  2:25 UTC (permalink / raw)
  To: ruby-core

Issue #12607 has been updated by Dan0042 (Daniel DeLorme).


chrisseaton (Chris Seaton) wrote in #note-28:
> For example for issuing unique IDs across multiple Ractors.

That's the "monotonically increasing counter" case I was talking about, and for that I really think a generator (like the above `MyCounter.next`) is a more appropriate tool than an atomic integer.

> For example a CAS to update a bank balance is a common requirement.

Can you elaborate? In my experience financial transactions will be handled at the DB level. Not to mention you usually need more intricate synchronization such as atomic update of the balances of _two_ accounts. I don't quite see how an atomic integer is a realistic tool for money stuff.

> I can only offer that I use atomic integers for many things fairly frequently in my working life.

That's great, so you should easily be able to give a concrete example _other_ than generating unique sequential IDs. I'm quite curious, so looking forward to a nice realistic use case.

----------------------------------------
Feature #12607: Ruby needs an atomic integer
https://bugs.ruby-lang.org/issues/12607#change-89938

* Author: shyouhei (Shyouhei Urabe)
* Status: Feedback
* Priority: Normal
* Assignee: ko1 (Koichi Sasada)
----------------------------------------
(This one was derived from bug #12463)

Although I don't think += would become atomic, at the same time I understand Rodrigo's needs of _easier_ counter variable that resists inter-thread tampering.  I don't think ruby's Integer class can be used for that purpose for reasons (mainly because it is not designed with threads in mind).  Rather we should introduce a integer class which is carefully designed.

Why not import Concurrent::AtomicFixnum into core?



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [ruby-core:102080] [Ruby master Feature#12607] Ruby needs an atomic integer
       [not found] <redmine.issue-12607.20160721050407.10@ruby-lang.org>
                   ` (9 preceding siblings ...)
  2021-01-14  2:25 ` [ruby-core:102079] " daniel
@ 2021-01-14  2:34 ` chris
  2021-01-14  3:41 ` [ruby-core:102082] " daniel
                   ` (6 subsequent siblings)
  17 siblings, 0 replies; 18+ messages in thread
From: chris @ 2021-01-14  2:34 UTC (permalink / raw)
  To: ruby-core

Issue #12607 has been updated by chrisseaton (Chris Seaton).


> In my experience financial transactions will be handled at the DB level.

So imagine you're implementing the DB then.

> Can you elaborate?

If you want to perform an arbitrary operation on a counter you can do that atomically, without a lock, by doing a CAS between the value as it currently is and the value you want to set it to, even if it takes you a long time to compute that. Atomics let you do this in a lock-free way.

> so you should easily be able to give a concrete example other than generating unique sequential IDs

An use-case I was working on earlier today was profiling operations like coverage and sampling tools. These need to be reset as well if they're in danger of over-flowing a range that the machine can natively implement with low-overhead.

----------------------------------------
Feature #12607: Ruby needs an atomic integer
https://bugs.ruby-lang.org/issues/12607#change-89939

* Author: shyouhei (Shyouhei Urabe)
* Status: Feedback
* Priority: Normal
* Assignee: ko1 (Koichi Sasada)
----------------------------------------
(This one was derived from bug #12463)

Although I don't think += would become atomic, at the same time I understand Rodrigo's needs of _easier_ counter variable that resists inter-thread tampering.  I don't think ruby's Integer class can be used for that purpose for reasons (mainly because it is not designed with threads in mind).  Rather we should introduce a integer class which is carefully designed.

Why not import Concurrent::AtomicFixnum into core?



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [ruby-core:102082] [Ruby master Feature#12607] Ruby needs an atomic integer
       [not found] <redmine.issue-12607.20160721050407.10@ruby-lang.org>
                   ` (10 preceding siblings ...)
  2021-01-14  2:34 ` [ruby-core:102080] " chris
@ 2021-01-14  3:41 ` daniel
  2021-01-14 13:06 ` [ruby-core:102091] " eregontp
                   ` (5 subsequent siblings)
  17 siblings, 0 replies; 18+ messages in thread
From: daniel @ 2021-01-14  3:41 UTC (permalink / raw)
  To: ruby-core

Issue #12607 has been updated by Dan0042 (Daniel DeLorme).


chrisseaton (Chris Seaton) wrote in #note-32:
> An use-case I was working on earlier today was profiling operations like coverage and sampling tools.

Ah yes, beautiful example! Accumulating metrics require both atomicity and performance.

----------------------------------------
Feature #12607: Ruby needs an atomic integer
https://bugs.ruby-lang.org/issues/12607#change-89941

* Author: shyouhei (Shyouhei Urabe)
* Status: Feedback
* Priority: Normal
* Assignee: ko1 (Koichi Sasada)
----------------------------------------
(This one was derived from bug #12463)

Although I don't think += would become atomic, at the same time I understand Rodrigo's needs of _easier_ counter variable that resists inter-thread tampering.  I don't think ruby's Integer class can be used for that purpose for reasons (mainly because it is not designed with threads in mind).  Rather we should introduce a integer class which is carefully designed.

Why not import Concurrent::AtomicFixnum into core?



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [ruby-core:102091] [Ruby master Feature#12607] Ruby needs an atomic integer
       [not found] <redmine.issue-12607.20160721050407.10@ruby-lang.org>
                   ` (11 preceding siblings ...)
  2021-01-14  3:41 ` [ruby-core:102082] " daniel
@ 2021-01-14 13:06 ` eregontp
  2021-01-14 14:43 ` [ruby-core:102095] " daniel
                   ` (4 subsequent siblings)
  17 siblings, 0 replies; 18+ messages in thread
From: eregontp @ 2021-01-14 13:06 UTC (permalink / raw)
  To: ruby-core

Issue #12607 has been updated by Eregon (Benoit Daloze).


There is also the well-known example of metrics in Sidekiq, and all these:
https://github.com/search?l=Ruby&q=AtomicFixnum&type=Code

> I really think a generator (like the above MyCounter.next) is a more appropriate tool than an atomic integer.

And how do you implement that efficiently, and in a way that's thread-safe?
To be clear, Enumerator.new {} is not efficient, so a generator is not good enough, and Fibers can't be resumed across threads.

ko1 (Koichi Sasada) wrote in #note-26:
> TVar proposed in https://bugs.ruby-lang.org/issues/17261 has `#increment` method and it is enough fast.

I think that cannot be as efficient as an atomic integer.
Reasoning: TVar#increment needs to also be atomic with other changes, including `Thread.atomically { tv.value = tv.value * 2 }`, for decent STM semantics.
That implies extra tracking for TVar#increment besides just a single fetch-and-add, isn't it?
For instance, it would be incorrect to execute that `atomically` block in parallel with the fetch-and-add (might result in the increment being lost). So TVar#increment needs to sync somehow with `Thread.atomically` and that's the overhead.

----------------------------------------
Feature #12607: Ruby needs an atomic integer
https://bugs.ruby-lang.org/issues/12607#change-89948

* Author: shyouhei (Shyouhei Urabe)
* Status: Feedback
* Priority: Normal
* Assignee: ko1 (Koichi Sasada)
----------------------------------------
(This one was derived from bug #12463)

Although I don't think += would become atomic, at the same time I understand Rodrigo's needs of _easier_ counter variable that resists inter-thread tampering.  I don't think ruby's Integer class can be used for that purpose for reasons (mainly because it is not designed with threads in mind).  Rather we should introduce a integer class which is carefully designed.

Why not import Concurrent::AtomicFixnum into core?



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [ruby-core:102095] [Ruby master Feature#12607] Ruby needs an atomic integer
       [not found] <redmine.issue-12607.20160721050407.10@ruby-lang.org>
                   ` (12 preceding siblings ...)
  2021-01-14 13:06 ` [ruby-core:102091] " eregontp
@ 2021-01-14 14:43 ` daniel
  2021-01-29  8:59 ` [ruby-core:102291] " ko1
                   ` (3 subsequent siblings)
  17 siblings, 0 replies; 18+ messages in thread
From: daniel @ 2021-01-14 14:43 UTC (permalink / raw)
  To: ruby-core

Issue #12607 has been updated by Dan0042 (Daniel DeLorme).


Eregon (Benoit Daloze) wrote in #note-34:
> And how do you implement that efficiently, and in a way that's thread-safe?
> To be clear, Enumerator.new {} is not efficient, so a generator is not good enough, and Fibers can't be resumed across threads.

By "a generator" I did not mean the `Enumerator::Generator` class. I meant a new generator-type class (say, `AtomicSequence`) that is implemented with atomic CAS operations. No one here is disputing the usefulness of atomic integers _in general_, just their relevance as a concurrency primitive in _ruby core_.

A naive implementation of a monotonic sequence using an atomic integer class might look like this:
```ruby
SEQUENCE.increment
guid = SEQUENCE.to_i
```
oops, wrong! When running concurrently this will produce duplicate guids. The correct usage would be `guid = SEQUENCE.increment` but you have to depend on the developer to understand the gotcha with `SEQUENCE.to_i`. In comparison, `guid = SEQUENCE.next` is always correct; you don't even need to be _aware_ of concurrency issues.

What about a naive implementation of metrics/statistics using an atomic integer class...
```ruby
t0 = Time.now
yield
t = ((Time.now - t0) * 1000000).round #microsecond
TIME.increment(t)
NB.increment(1)
avg = TIME.to_i / NB.to_i
```
oops, wrong again! When running concurrently the `avg` might be incorrect.

Maybe a more useful abstraction might be an `AtomicVector`? If such a thing is possible...
```ruby
TIME_NB = AtomicVector.new(0, 0)
TIME_NB.increment(t, 1)
avg = TIME_NB.to_a.inject(:/)
```

Basically all I'm trying to say is there's a clear benefit to choosing abstractions that produce the correct result _even when used naively_. Like Ractor. So I understand why ko1 is reluctant about this.

----------------------------------------
Feature #12607: Ruby needs an atomic integer
https://bugs.ruby-lang.org/issues/12607#change-89952

* Author: shyouhei (Shyouhei Urabe)
* Status: Feedback
* Priority: Normal
* Assignee: ko1 (Koichi Sasada)
----------------------------------------
(This one was derived from bug #12463)

Although I don't think += would become atomic, at the same time I understand Rodrigo's needs of _easier_ counter variable that resists inter-thread tampering.  I don't think ruby's Integer class can be used for that purpose for reasons (mainly because it is not designed with threads in mind).  Rather we should introduce a integer class which is carefully designed.

Why not import Concurrent::AtomicFixnum into core?



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [ruby-core:102291] [Ruby master Feature#12607] Ruby needs an atomic integer
       [not found] <redmine.issue-12607.20160721050407.10@ruby-lang.org>
                   ` (13 preceding siblings ...)
  2021-01-14 14:43 ` [ruby-core:102095] " daniel
@ 2021-01-29  8:59 ` ko1
  2021-01-29 12:28 ` [ruby-core:102299] " eregontp
                   ` (2 subsequent siblings)
  17 siblings, 0 replies; 18+ messages in thread
From: ko1 @ 2021-01-29  8:59 UTC (permalink / raw)
  To: ruby-core

Issue #12607 has been updated by ko1 (Koichi Sasada).


> ko1 (Koichi Sasada) wrote in #note-26:
> > TVar proposed in https://bugs.ruby-lang.org/issues/17261 has `#increment` method and it is enough fast.
> 
> I think that cannot be as efficient as an atomic integer.

Yes. It is slower than single purpose atomic integers with hardware instruction with JIT.
But (I didn't measured yet) increment method call on VM needs method invocation overhead and it is relatively higher than `TVar#increment` overhead. Again, I didn't measure and it can be wrong.


----------------------------------------
Feature #12607: Ruby needs an atomic integer
https://bugs.ruby-lang.org/issues/12607#change-90146

* Author: shyouhei (Shyouhei Urabe)
* Status: Feedback
* Priority: Normal
* Assignee: ko1 (Koichi Sasada)
----------------------------------------
(This one was derived from bug #12463)

Although I don't think += would become atomic, at the same time I understand Rodrigo's needs of _easier_ counter variable that resists inter-thread tampering.  I don't think ruby's Integer class can be used for that purpose for reasons (mainly because it is not designed with threads in mind).  Rather we should introduce a integer class which is carefully designed.

Why not import Concurrent::AtomicFixnum into core?



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [ruby-core:102299] [Ruby master Feature#12607] Ruby needs an atomic integer
       [not found] <redmine.issue-12607.20160721050407.10@ruby-lang.org>
                   ` (14 preceding siblings ...)
  2021-01-29  8:59 ` [ruby-core:102291] " ko1
@ 2021-01-29 12:28 ` eregontp
  2022-07-25 13:14 ` [ruby-core:109315] " Eregon (Benoit Daloze)
  2022-07-25 14:22 ` [ruby-core:109316] " chrisseaton (Chris Seaton)
  17 siblings, 0 replies; 18+ messages in thread
From: eregontp @ 2021-01-29 12:28 UTC (permalink / raw)
  To: ruby-core

Issue #12607 has been updated by Eregon (Benoit Daloze).


ko1 (Koichi Sasada) wrote in #note-36:
> But (I didn't measured yet) increment method call on VM needs method invocation overhead and it is relatively higher than `TVar#increment` overhead. Again, I didn't measure and it can be wrong.

Why would the invocation of AtomicInteger#increment be more expensive than the invocation of TVar#increment?
They are both method calls, and TVar doesn't doesn't use `Primitive` since it is a separate gem (currently at least).

In general, method calls have no cost when inlined with a JIT that can see through the core library, e.g. on TruffleRuby, or I think with MJIT and leaf annotated methods, so I think for best performance AtomicInteger#increment is a clear winner.

----------------------------------------
Feature #12607: Ruby needs an atomic integer
https://bugs.ruby-lang.org/issues/12607#change-90154

* Author: shyouhei (Shyouhei Urabe)
* Status: Feedback
* Priority: Normal
* Assignee: ko1 (Koichi Sasada)
----------------------------------------
(This one was derived from bug #12463)

Although I don't think += would become atomic, at the same time I understand Rodrigo's needs of _easier_ counter variable that resists inter-thread tampering.  I don't think ruby's Integer class can be used for that purpose for reasons (mainly because it is not designed with threads in mind).  Rather we should introduce a integer class which is carefully designed.

Why not import Concurrent::AtomicFixnum into core?



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [ruby-core:109315] [Ruby master Feature#12607] Ruby needs an atomic integer
       [not found] <redmine.issue-12607.20160721050407.10@ruby-lang.org>
                   ` (15 preceding siblings ...)
  2021-01-29 12:28 ` [ruby-core:102299] " eregontp
@ 2022-07-25 13:14 ` Eregon (Benoit Daloze)
  2022-07-25 14:22 ` [ruby-core:109316] " chrisseaton (Chris Seaton)
  17 siblings, 0 replies; 18+ messages in thread
From: Eregon (Benoit Daloze) @ 2022-07-25 13:14 UTC (permalink / raw)
  To: ruby-core

Issue #12607 has been updated by Eregon (Benoit Daloze).


It'd be good to revisit this (e.g. see https://twitter.com/_byroot/status/1550580128723476480).

Ractor has little need for this. But with Thread there is a clear need for this.
Also the STM work was not merged, so that's not a replacement either.
I think @ko1's concern of "too hard to use" should be no blocker: Rubyists frequently use Threads, almost all Ruby webservers and Rails use threads nowadays, there is no point to deny that.
And it is completely unrealistic to think Ractor will ever replace Threads, Ractor can only support a small subset of Ruby gems, and it will never be all or as powerful as threads.
For instance I don't see Rails being able to use Ractor for parallel requests anytime soon.

Regarding that example it's easy to fix, and such conditions are well understood by anyone knowing about compare-and-swap or this kind of concurrency tools.
It can also be documented on the `update` method.
```ruby
v = af.value
af.update{ |v| v + 5 }
```

So, let's add AtomicInteger or AtomicReference (since it's more general) because it's convenient and needed by existing gems?
Having it in concurrent-ruby works but it's obviously less practical, and less optimized than it could be.

Also there is a trap when using Mutex as a compare-and-swap way with `try_lock`, because that leaves the Mutex locked and when the thread dies it unlocks all Mutex it had, which can be pretty slow (I found that out when reimplementing the timeout gem).

----------------------------------------
Feature #12607: Ruby needs an atomic integer
https://bugs.ruby-lang.org/issues/12607#change-98453

* Author: shyouhei (Shyouhei Urabe)
* Status: Feedback
* Priority: Normal
* Assignee: ko1 (Koichi Sasada)
----------------------------------------
(This one was derived from bug #12463)

Although I don't think += would become atomic, at the same time I understand Rodrigo's needs of _easier_ counter variable that resists inter-thread tampering.  I don't think ruby's Integer class can be used for that purpose for reasons (mainly because it is not designed with threads in mind).  Rather we should introduce a integer class which is carefully designed.

Why not import Concurrent::AtomicFixnum into core?



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [ruby-core:109316] [Ruby master Feature#12607] Ruby needs an atomic integer
       [not found] <redmine.issue-12607.20160721050407.10@ruby-lang.org>
                   ` (16 preceding siblings ...)
  2022-07-25 13:14 ` [ruby-core:109315] " Eregon (Benoit Daloze)
@ 2022-07-25 14:22 ` chrisseaton (Chris Seaton)
  17 siblings, 0 replies; 18+ messages in thread
From: chrisseaton (Chris Seaton) @ 2022-07-25 14:22 UTC (permalink / raw)
  To: ruby-core

Issue #12607 has been updated by chrisseaton (Chris Seaton).


Yes, I think a few low-level concurrency primitives should move from Concurrent Ruby to core. As we add more concurrency to Ruby, and add JIT compilers, ideally the VM should understand these primitives, rather than being opaque extension code.

----------------------------------------
Feature #12607: Ruby needs an atomic integer
https://bugs.ruby-lang.org/issues/12607#change-98454

* Author: shyouhei (Shyouhei Urabe)
* Status: Feedback
* Priority: Normal
* Assignee: ko1 (Koichi Sasada)
----------------------------------------
(This one was derived from bug #12463)

Although I don't think += would become atomic, at the same time I understand Rodrigo's needs of _easier_ counter variable that resists inter-thread tampering.  I don't think ruby's Integer class can be used for that purpose for reasons (mainly because it is not designed with threads in mind).  Rather we should introduce a integer class which is carefully designed.

Why not import Concurrent::AtomicFixnum into core?



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2022-07-25 14:22 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <redmine.issue-12607.20160721050407.10@ruby-lang.org>
2021-01-06 12:06 ` [ruby-core:101956] [Ruby master Feature#12607] Ruby needs an atomic integer eregontp
2021-01-06 15:17 ` [ruby-core:101962] " dsisnero
2021-01-12  7:54 ` [ruby-core:102026] " ko1
2021-01-12 11:13 ` [ruby-core:102031] " eregontp
2021-01-13  7:32 ` [ruby-core:102056] " ko1
2021-01-13 18:05 ` [ruby-core:102070] " daniel
2021-01-13 21:45 ` [ruby-core:102074] " chris
2021-01-13 22:40 ` [ruby-core:102075] " marcandre-ruby-core
2021-01-13 23:45 ` [ruby-core:102076] " chris
2021-01-14  2:25 ` [ruby-core:102079] " daniel
2021-01-14  2:34 ` [ruby-core:102080] " chris
2021-01-14  3:41 ` [ruby-core:102082] " daniel
2021-01-14 13:06 ` [ruby-core:102091] " eregontp
2021-01-14 14:43 ` [ruby-core:102095] " daniel
2021-01-29  8:59 ` [ruby-core:102291] " ko1
2021-01-29 12:28 ` [ruby-core:102299] " eregontp
2022-07-25 13:14 ` [ruby-core:109315] " Eregon (Benoit Daloze)
2022-07-25 14:22 ` [ruby-core:109316] " chrisseaton (Chris Seaton)

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).