profile
viewpoint
Thierry Deo tdeo @pennylane-hq Lyon, France

startedducdat0507/towers

started time in 11 days

push eventtdeo/advent_of_code

Thierry Deo

commit sha f740a29d32063ea4387d46ff2d4743f2c3297eb1

Fixes after rubocop

view details

Thierry Deo

commit sha dfd307f3ba3cb62a2bf7ba40723bf902dff09222

Simpler PriorityQueue

view details

push time in a month

push eventpennylane-hq/jean_test_front

Thierry Deo

commit sha 65317ed570a7191e77b26c3a8c184ea492237db5

Provide CustomerAutocomplete, ProductAutocomplete and router

view details

push time in a month

push eventpennylane-hq/jean_test_front

Thierry Deo

commit sha 584c26ac182594f54f099a161c9b6006baca081f

Provide CustomerAutocomplete, ProductAutocomplete and router

view details

push time in a month

issue openedfohte/rubocop-daemon

Restart server automatically on config change

Hello,

I noticed some inconsistencies when using rubocop-daemon and changing rubocop's config file, the changes aren't reloaded until I restart the server.

I looked a bit around Rubocop, and there doesn't seem to be an API to reload the whole config. I'm quite willing to look into making a PR for that - I believe it could be implement in ClientCommand::Base#ensure_server! by appending a first line like ClientCommand::Stop.new([]).run if Daemon.configuration_obsolete? and having a configuration_checksum of some sort handled by Cache.

Do you think that is the right direction ? Would you have any other suggestions for implementing that behavior?

created time in a month

fork tdeo/rubocop-daemon

Makes RuboCop faster

fork in a month

push eventtdeo/dotfiles

Thierry Deo

commit sha 688bfb4948f2164822de4c6cee918e1b5d8e67ca

Add screenshot script

view details

push time in a month

fork tdeo/super_diff

A more helpful way to view differences between complex data structures in RSpec.

fork in a month

push eventpennylane-hq/jean_test_api

Thierry Deo

commit sha c5c72a15d5f6ee18109b3c874e7c88df3bbe84e2

Update seeds.rb

view details

push time in a month

push eventtdeo/sublime_config

Thierry Deo

commit sha 9fc1cb117d0b679040a485f62a61e1c39d97823d

Bump config

view details

push time in a month

pull request commentrails/rails

Fix `thread_mattr_accessor` `default` option behavior

Could you add a test that shows how defaults interact with subclasses (maybe in test_should_not_affect_superclass_if_subclass_set_value)?

Not sure if this got caught but I amended the commit to add this test

tdeo

comment created time in 2 months

push eventpennylane-hq/.github

Thierry Deo

commit sha 1c65228a2fe8f833262e4ea264056d9de0d5eda7

Update README.md

view details

push time in 2 months

push eventpennylane-hq/.github

Thierry Deo

commit sha 1f7c761cfb4eabdb96c385183d35c984a7bb0ebc

Create README.md

view details

push time in 2 months

create barnchpennylane-hq/.github

branch : main

created branch time in 2 months

created repositorypennylane-hq/.github

created time in 2 months

push eventtdeo/rails

Thierry Deo

commit sha 53801477b2b75431089dfaae4bfc662af0799496

Fix `thread_mattr_accessor` `default` option behavior This makes the value supplier to the `default` option of `thread_mattr_accessor` to be set in descendant classes as well as in any new Thread that starts. Previously, the `default` value provided was set only at the moment of defining the attribute writer, which would cause the attribute to be uninitialized in descendants and in other threads. For instance: class Processor thread_mattr_accessor :mode, default: :smart end class SubProcessor < Processor end SubProcessor.mode # => :smart Thread.new do Processor.mode # => :smart end.join when in the past, those two calls would have returned `nil`. This logic comes with a performance impact on the reader, here is the benchmark: Warming up -------------------------------------- original 238.780k i/100ms patched_default 162.765k i/100ms Calculating ------------------------------------- original 2.376M (± 9.4%) i/s - 11.939M in 5.078355s patched_default 1.635M (±16.4%) i/s - 7.813M in 5.008433s Comparison: original: 2375953.1 i/s patched_default: 1634668.2 i/s - 1.45x (± 0.00) slower Fixes #43312.

view details

push time in 2 months

pull request commentpre-commit/pre-commit-hooks

Do not rewrite file unless necessary

it's way worse for large files

What would be an acceptable performance for this hook ? I think it's valuable in general to have development tools interact nicely with other development tools.

I tried on a folder having 1k files of 100k lines (3.2M) each, for a total of 3.1G of data, and I get this result:

$ pre-commit run --verbose --files *
Fix End of Files.........................................................Passed
- hook id: end-of-file-fixer
- duration: 0.09s
Fix End of Files.........................................................Passed
- hook id: end-of-file-fixer
- duration: 0.73s

Which indeeds shows degraded performance, but still relatively fast to process 3.1G of data

If you give some baseline of what acceptable performance would be, I can also take a look at other strategies (maybe keeping something in the spirit of the current implementation, but with a first read-only pass to detect if changes are necessary)

tdeo

comment created time in 2 months

pull request commentpre-commit/pre-commit-hooks

Do not rewrite file unless necessary

Hello @asottile ,

Could you maybe point me out to a repo that would be a reasonable benchmark ?

I tried on the rails repo, which has 4373 files for 308k total LOC, and with the following pre-commit config file:

repos:
-   repo: git://github.com/tdeo/pre-commit-hooks
    rev: end_of_file_fixer_does_not_write
    hooks:
      -   id: end-of-file-fixer
-   repo: git://github.com/pre-commit/pre-commit-hooks
    rev: v4.0.1
    hooks:
      -   id: end-of-file-fixer

That gives me the following output:

$ time pre-commit run  --verbose --all-files
Fix End of Files.........................................................Passed
- hook id: end-of-file-fixer
- duration: 0.11s
Fix End of Files.........................................................Passed
- hook id: end-of-file-fixer
- duration: 0.12s

which doesn't seem to make my solution so bad.

From the inotify events perspective, here's the difference when running pre-commit on a file (less events overall, and avoids the CLOSE_WRITE):

Before:

CODE_OF_CONDUCT.md OPEN 
CODE_OF_CONDUCT.md ACCESS 
CODE_OF_CONDUCT.md CLOSE_NOWRITE,CLOSE 
CODE_OF_CONDUCT.md OPEN 
CODE_OF_CONDUCT.md CLOSE_NOWRITE,CLOSE 
CODE_OF_CONDUCT.md OPEN 
CODE_OF_CONDUCT.md ACCESS 
CODE_OF_CONDUCT.md ACCESS 
CODE_OF_CONDUCT.md CLOSE_WRITE,CLOSE 
CODE_OF_CONDUCT.md OPEN 
CODE_OF_CONDUCT.md ACCESS 
CODE_OF_CONDUCT.md CLOSE_NOWRITE,CLOSE 
CODE_OF_CONDUCT.md OPEN 
CODE_OF_CONDUCT.md CLOSE_NOWRITE,CLOSE

After:

CODE_OF_CONDUCT.md OPEN 
CODE_OF_CONDUCT.md ACCESS 
CODE_OF_CONDUCT.md CLOSE_NOWRITE,CLOSE 
CODE_OF_CONDUCT.md OPEN 
CODE_OF_CONDUCT.md CLOSE_NOWRITE,CLOSE 
CODE_OF_CONDUCT.md OPEN 
CODE_OF_CONDUCT.md ACCESS 
CODE_OF_CONDUCT.md CLOSE_NOWRITE,CLOSE 
CODE_OF_CONDUCT.md OPEN 
CODE_OF_CONDUCT.md ACCESS 
CODE_OF_CONDUCT.md CLOSE_NOWRITE,CLOSE 
CODE_OF_CONDUCT.md OPEN 
CODE_OF_CONDUCT.md CLOSE_NOWRITE,CLOSE 
tdeo

comment created time in 2 months

PR opened rails/rails

Fix `thread_mattr_accessor` `default` option behavior

Summary

This makes the value supplier to the default option of thread_mattr_accessor to be set in descendant classes as well as in any new Thread that starts.

Previously, the default value provided was set only at the moment of defining the attribute writer, which would cause the attribute to be uninitialized in descendants and in other threads.

For instance:

class Processor
  thread_mattr_accessor :mode, default: :smart
end

class SubProcessor < Processor
end

SubProcessor.mode # => :smart
Thread.new do
  Processor.mode # => :smart
end.join

when in the past, those two calls would have returned nil.

Fixes #43312

Other Information

This logic comes with a performance impact on the reader, here is the benchmark:

Warming up --------------------------------------
        original   238.780k i/100ms
         patched   162.765k i/100ms
Calculating -------------------------------------
        original    2.376M (± 9.4%) i/s -  11.939M in 5.078355s
         patched    1.635M (±16.4%) i/s -   7.813M in 5.008433s

Comparison:
        original:  2375953.1 i/s
         patched:  1634668.2 i/s - 1.45x  (± 0.00) slower

<!-- If there's anything else that's important and relevant to your pull request, mention that information here. This could include benchmarks, or other information.

If you are updating any of the CHANGELOG files or are asked to update the CHANGELOG files by reviewers, please add the CHANGELOG entry at the top of the file.

Finally, if your pull request affects documentation or any non-code changes, guidelines for those changes are available here

Thanks for contributing to Rails! -->

<!-- Note: Please avoid making Draft pull requests, as they still send notifications to everyone watching the Rails repo. Create a pull request when it is ready for review and feedback from the Rails team :). -->

+47 -7

0 comment

3 changed files

pr created time in 2 months

push eventtdeo/rails

Thierry Deo

commit sha 89d922166971145d238fbe86af78d950fd08a944

Fix `thread_mattr_accessor` `default` option behavior This makes the value supplier to the `default` option of `thread_mattr_accessor` to be set in descendant classes as well as in any new Thread that starts. Previously, the `default` value provided was set only at the moment of defining the attribute writer, which would cause the attribute to be uninitialized in descendants and in other threads. For instance: class Processor thread_mattr_accessor :mode, default: :smart end class SubProcessor < Processor end SubProcessor.mode # => :smart Thread.new do Processor.mode # => :smart end.join when in the past, those two calls would have returned `nil`. This logic comes with a performance impact on the reader, here is the benchmark: Warming up -------------------------------------- original 238.780k i/100ms patched_default 162.765k i/100ms Calculating ------------------------------------- original 2.376M (± 9.4%) i/s - 11.939M in 5.078355s patched_default 1.635M (±16.4%) i/s - 7.813M in 5.008433s Comparison: original: 2375953.1 i/s patched_default: 1634668.2 i/s - 1.45x (± 0.00) slower Fixes #43312.

view details

push time in 2 months

push eventtdeo/rails

Thierry Deo

commit sha a080bf0b5a5dd9a21c6cd67516d97bbf81ddde10

Fix `thread_mattr_accessor` `default` option behavior This makes the value supplier to the `default` option of `thread_mattr_accessor` to be set in descendant classes as well as in any new Thread that starts. Previously, the `default` value provided was set only at the moment of defining the attribute writer, which would cause the attribute to be uninitialized in descendants and in other threads. For instance: class Processor thread_mattr_accessor :mode, default: :smart end class SubProcessor < Processor end SubProcessor.mode # => :smart Thread.new do Processor.mode # => :smart end.join when in the past, those two calls would have returned `nil`. This logic comes with a performance impact on the reader, here is the benchmark: Warming up -------------------------------------- original 238.780k i/100ms patched_default 162.765k i/100ms Calculating ------------------------------------- original 2.376M (± 9.4%) i/s - 11.939M in 5.078355s patched_default 1.635M (±16.4%) i/s - 7.813M in 5.008433s Comparison: original: 2375953.1 i/s patched_default: 1634668.2 i/s - 1.45x (± 0.00) slower

view details

push time in 2 months

push eventtdeo/rails

Thierry Deo

commit sha c02c28c097de6c8f04064169ded2d744b85af829

Fix `thread_mattr_accessor` `default` option behavior This makes the value supplier to the `default` option of `thread_mattr_accessor` to be set in descendant classes as well as in any new Thread that starts. Previously, the `default` value provided was set only at the moment of defining the attribute writer, which would cause the attribute to be uninitialized in descendants and in other threads. For instance: class Processor thread_mattr_accessor :mode, default: :smart end class SubProcessor < Processor end SubProcessor.mode # => :smart Thread.new do Processor.mode # => :smart end.join when in the past, those two calls would have returned `nil`. This logic comes with a performance impact on the reader, here is the benchmark: Warming up -------------------------------------- original 238.780k i/100ms patched_default 162.765k i/100ms Calculating ------------------------------------- original 2.376M (± 9.4%) i/s - 11.939M in 5.078355s patched_default 1.635M (±16.4%) i/s - 7.813M in 5.008433s Comparison: original: 2375953.1 i/s patched_default: 1634668.2 i/s - 1.45x (± 0.00) slower

view details

push time in 2 months

push eventtdeo/rails

Thierry Deo

commit sha d1f762cd8c546421061f864b48871dfea0c2c347

Fix `thread_mattr_accessor` `default` option behavior This makes the value supplier to the `default` option of `thread_mattr_accessor` to be set in descendant classes as well as in any new Thread that starts. Previously, the `default` value provided was set only at the moment of defining the attribute writer, which would cause the attribute to be uninitialized in descendants and in other threads. For instance: class Processor thread_mattr_accessor :mode, default: :smart end class SubProcessor < Processor end SubProcessor.mode # => :smart Thread.new do Processor.mode # => :smart end.join when in the past, those two calls would have returned `nil`. This logic comes with a performance impact on the reader, here is the benchmark: Warming up -------------------------------------- original 238.780k i/100ms patched_default 162.765k i/100ms Calculating ------------------------------------- original 2.376M (± 9.4%) i/s - 11.939M in 5.078355s patched_default 1.635M (±16.4%) i/s - 7.813M in 5.008433s Comparison: original: 2375953.1 i/s patched_default: 1634668.2 i/s - 1.45x (± 0.00) slower

view details

push time in 2 months

create barnchtdeo/rails

branch : fix_thread_mattr_default

created branch time in 2 months

fork tdeo/rails

Ruby on Rails

https://rubyonrails.org

fork in 2 months

issue commentrails/rails

`thread_mattr_accessor` default value does not apply to threads

Hello @ghiculescu,

From the top of my mind, here is the patched version I would come up with:

# frozen_string_literal: true

require "bundler/inline"

gemfile(true) do
  source "https://rubygems.org"

  git_source(:github) { |repo| "https://github.com/#{repo}.git" }

  gem "rails", github: "rails/rails", branch: "main"
  gem "benchmark-ips"
end

require "active_support"
require "active_support/core_ext/module/attribute_accessors_per_thread"
require "minitest/autorun"

# Your patch goes here.
class Module
  def thread_mattr_reader_default(*syms, instance_reader: true, instance_accessor: true, default: nil)
    syms.each do |sym|
      raise NameError.new("invalid attribute name: #{sym}") unless /^[_A-Za-z]\w*$/.match?(sym)
      class_eval(<<-EOS, __FILE__, __LINE__ + 1)
        def self.#{sym}
          if Thread.current["attr_defined_" + name + "_#{sym}"].nil?
            Thread.current["attr_defined_" + name + "_#{sym}"] = true
            Thread.current["attr_" + name + "_#{sym}"] = #{default.inspect}
          end
          Thread.current["attr_" + name + "_#{sym}"]
        end
      EOS

      if instance_reader && instance_accessor
        class_eval(<<-EOS, __FILE__, __LINE__ + 1)
          def #{sym}
            self.class.#{sym}
          end
        EOS
      end
    end
  end

  def thread_mattr_writer_default(*syms, instance_writer: true, instance_accessor: true, default: nil) # :nodoc:
    syms.each do |sym|
      raise NameError.new("invalid attribute name: #{sym}") unless /^[_A-Za-z]\w*$/.match?(sym)

      # The following generated method concatenates `name` because we want it
      # to work with inheritance via polymorphism.
      class_eval(<<-EOS, __FILE__, __LINE__ + 1)
        def self.#{sym}=(obj)
          if Thread.current["attr_defined_" + name + "_#{sym}"].nil?
            Thread.current["attr_defined_" + name + "_#{sym}"] = true
          end
          Thread.current["attr_" + name + "_#{sym}"] = obj
        end
      EOS

      if instance_writer && instance_accessor
        class_eval(<<-EOS, __FILE__, __LINE__ + 1)
          def #{sym}=(obj)
            self.class.#{sym} = obj
          end
        EOS
      end

      public_send("#{sym}=", default) unless default.nil?
    end
  end

  def thread_mattr_accessor_default(*syms, instance_reader: true, instance_writer: true, instance_accessor: true, default: nil)
    thread_mattr_reader_default(*syms, instance_reader: instance_reader, instance_accessor: instance_accessor, default: default)
    thread_mattr_writer_default(*syms, instance_writer: instance_writer, instance_accessor: instance_accessor)
  end
end

module A
  thread_mattr_accessor_default :attribute_with_default, default: 42
  thread_mattr_accessor :attribute, default: 42
end

Benchmark.ips do |x|
  x.report("original")      { A.attribute }
  x.report("patched_default") { A.attribute_with_default }
  x.compare!
end

class BugTest < Minitest::Test
  def test_stuff
    assert(A.attribute_with_default == 42)
    Thread.new do
      assert(A.attribute_with_default == 42)
    end.join
    A.attribute_with_default = nil
    assert(A.attribute_with_default.nil?)
  end
end

Output of this script:

Warming up --------------------------------------
            original   170.500k i/100ms
     patched_default    66.095k i/100ms
Calculating -------------------------------------
            original      2.105M (± 5.4%) i/s -     10.571M in   5.036874s
     patched_default    914.367k (± 7.5%) i/s -      4.561M in   5.018758s

Comparison:
            original:  2104980.9 i/s
     patched_default:   914367.3 i/s - 2.30x  (± 0.00) slower

Run options: --seed 65131

# Running:

.

Finished in 0.002085s, 479.6453 runs/s, 1438.9359 assertions/s.
1 runs, 3 assertions, 0 failures, 0 errors, 0 skips

The performance hit is indeed pretty nasty (x2.3), however, that's still ~1M ips, which I'm not sure if that would be acceptable for such a feature, let me know what you think.

Unfortunately, I can't think of a way to do it without a second thread variable as the following occurs when explicitly setting it to nil:

Thread.current[:var] = 1
Thread.current.key?(:var) # => true 
Thread.current[:var] = nil
Thread.current.key?(:var) # => false 
tdeo

comment created time in 2 months

push eventtdeo/pre-commit-hooks

Thierry Deo

commit sha 92a8607b4ba760761eaf960d0423174268f155a2

Fix coverage

view details

push time in 2 months

PR opened pre-commit/pre-commit-hooks

Do not rewrite file unless necessary

I came accross the following: the end-of-file hook always opens the file in write mode, hence triggering the inotify event close_write on all files even when there are no changes to perform.

In a project, I'm listening to inotify changes to files to automatically regenerate typescript files from rubby, and this has the side-effect of triggering this regeneration, which in turns leads pre-commit to believe that files have changed.

This rewrites that hook in a similar fashion to trim-trailing-spaces, which generates the fixed version in memory and rewrites the original file only if there are actual changes

+39 -53

0 comment

2 changed files

pr created time in 2 months

push eventtdeo/pre-commit-hooks

Thierry Deo

commit sha 5c0618dc824540f78698b60dd6410d8e333bebb0

Do not rewrite file unless necessary

view details

push time in 2 months

create barnchtdeo/pre-commit-hooks

branch : end_of_file_fixer_does_not_write

created branch time in 2 months

more