[RUBY] J'ai essayé de pouvoir passer plusieurs objets avec Ractor

Conclusion

J'ai essayé de faire fonctionner le code suivant avec Ractor.

r = Ractor.new do
    v1, v2 = Ractor.recv
    puts v1
    puts v2
    puts v1.class
    puts v2.class
end

r.send(1, 2)

r.take
# => 1
# => 2
# => Integer
# => Integer

Qu'est-ce que Ractor?

C'est un mécanisme pour fournir des fonctions parallèles / parallèles introduit dans Ruby3. Initialement nommée Guild, elle est discutée depuis plusieurs années.

Pour plus de détails, veuillez vous référer à la vidéo ci-dessous.

[JA] Ractor report / Koichi Sasada @ko1

Passez l'objet à Ractor

Vous pouvez transmettre un objet à Ractor en utilisant la méthode send.

r = Ractor.new do
    v = Ractor.recv
    puts v
    puts v.class
end

r.send(1)

r.take
# => 1
# => Integer

Cependant, vous ne pouvez pas transmettre plusieurs objets comme indiqué ci-dessous.

r = Ractor.new do
    v1, v2 = Ractor.recv
    puts v1
    puts v2
    puts v1.class
    puts v2.class
end

r.send(1, 2)

r.take
# =>wrong number of arguments (given 2, expected 1) (ArgumentError)

Cependant, il semble correct de le transmettre en tant que tableau.

r = Ractor.new do
    v1, v2 = Ractor.recv
    puts v1
    puts v2
    puts v1.class
    puts v2.class
end

r.send([1, 2])

r.take
# => 1
# => 2
# => Integer
# => Integer

En regardant l'implémentation, cela ressemble à ceci (dans ractor.rb dans le code source de CRuby) La méthode send actuelle ne prend qu'un seul objet comme argument. Vous pouvez également spécifier si vous souhaitez déplacer ou non avec l'argument de mot-clé move.

  def send obj, move: false
    __builtin_cexpr! %q{
      ractor_send(ec, RACTOR_PTR(self), obj, move)
    }
  end

La fonction C est appelée avec __builtin_cexpr!, Et l'argument reçu par la méthode est passé à la fonction C tel quel. En passant, CRuby récent vous permet d'écrire du code qui transmet des variables Ruby aux fonctions C en tant qu'implémentation interne.

Ce que j'ai fait

J'ai réécrit la méthode «send» de Ractor comme suit.

  def send obj, *arg, move: false
    obj = arg.unshift obj unless arg.empty?
    __builtin_cexpr! %q{
      ractor_send(ec, RACTOR_PTR(self), obj, move)
    }
  end

Premièrement, la méthode send prend toujours un objet comme argument. Les arguments sont réécrits comme «obj, * arg, move: false» pour maintenir ce comportement. Si plusieurs objets sont passés comme send (1, 2), l'argument est passé sous forme de tableau à * arg.

Si ʻarg n'est pas un tableau vide, alors plusieurs objets sont passés, convertissant ʻobj, qui est finalement passé à la fonction C, en une fusion du premier et des arguments de longueur variable. Je vais.

Tout ce que vous avez à faire est de créer le code source CRuby modifié.

Vous pouvez désormais transmettre plusieurs objets à Ractor comme suit:

r = Ractor.new do
    v1, v2 = Ractor.recv
    puts v1
    puts v2
    puts v1.class
    puts v2.class
end

r.send(1, 2)

r.take
# => 1
# => 2
# => Integer
# => Integer

référence

ref: Guild → Ractor ref: https://github.com/ko1/ruby/blob/ractor/ractor.ja.md ref: [[JA Ractor report / Koichi Sasada @ko1

Postscript

En passant, si vous voulez un patch monkey, vous pouvez créer une méthode encapsulée comme suit.

class Ractor
    def multi_send(obj, *args, move: true)
        obj = args.unshift obj unless args.empty?
        send(obj, move: move)
    end 
end

r = Ractor.new do
    v1, v2 = Ractor.recv
    puts v1
    puts v2
    puts v1.class
    puts v2.class
end

r.multi_send(1, 2)

r.take

Puisque la gamme de patchs de singe est large, il peut être préférable d'utiliser des raffinements car ils ont moins d'effet si vous les utilisez en pratique.

module RefineRactor
    refine Ractor do
        def multi_send(obj, *args, move: true)
            obj = args.unshift obj unless args.empty?
            send(obj, move: move)
        end 
    end
end

using RefineRactor

r = Ractor.new do
    v1, v2 = Ractor.recv
    puts v1
    puts v2
    puts v1.class
    puts v2.class
end

r.multi_send(1, 2)

r.take

Recommended Posts

J'ai essayé de pouvoir passer plusieurs objets avec Ractor
J'ai essayé d'interagir avec Java
J'ai essayé de démarrer avec Web Assembly
J'ai essayé de vérifier AdoptOpenJDK 11 (11.0.2) avec l'image Docker
J'ai essayé de faire une authentification de base avec Java
J'ai essayé de gérer la configuration des jambes de force avec Coggle
J'ai essayé de gérer les informations de connexion avec JMX
J'ai essayé de casser le bloc avec java (1)
Je souhaite pouvoir lire des fichiers en utilisant refile avec administrate [rails6]
J'ai essayé ce que je voulais essayer avec Stream doucement.
J'ai essayé d'implémenter le téléchargement de fichiers avec Spring MVC
J'ai essayé de lire et de sortir CSV avec Outsystems
J'ai essayé d'implémenter TCP / IP + BIO avec JAVA
[Java 11] J'ai essayé d'exécuter Java sans compiler avec javac
J'ai démarré MySQL 5.7 avec docker-compose et j'ai essayé de me connecter
J'ai essayé de démarrer avec Spring Data JPA
J'ai essayé de dessiner une animation avec l'API Blazor + canvas
J'ai essayé d'implémenter Sterling Sort avec Java Collector
J'ai essayé de moderniser une application Java EE avec OpenShift.
J'ai essayé DI avec Ruby
J'ai essayé d'augmenter la vitesse de traitement avec l'ingénierie spirituelle
Je veux pouvoir transmettre des éléments qui ont été validés avec des expressions régulières même s'ils sont laissés vides
[Rails] J'ai essayé d'implémenter le traitement par lots avec la tâche Rake
J'ai essayé UPSERT avec PostgreSQL.
J'ai essayé BIND avec Docker
J'ai essayé de vérifier yum-cron
J'ai essayé de créer un environnement de développement padrino avec Docker
Je veux passer la commande de démarrage à postgres avec docker-compose.
J'ai essayé de résoudre le problème de la "sélection multi-étapes" avec Ruby
Je veux pouvoir penser et écrire moi-même des expressions régulières. ..
J'ai essayé de me connecter à MySQL en utilisant le modèle JDBC avec Spring MVC
J'ai essayé d'implémenter la fonction de prévisualisation d'image avec Rails / jQuery
J'ai essayé de créer un environnement de développement http2 avec Eclipse + Tomcat
J'ai essayé d'implémenter un mappage OU flexible avec MyBatis Dynamic SQL
J'ai essayé de réimplémenter Ruby's Float (arg, exception: true) avec builtin
J'ai essayé de créer une application Android avec MVC maintenant (Java)
J'ai essayé de vérifier le fonctionnement du serveur gRPC avec grpcurl
J'ai essayé de créer une fonction de groupe (babillard) avec Rails
J'ai essayé de mâcher C # (indexeur)
J'ai essayé d'utiliser JOOQ avec Gradle
J'ai essayé l'analyse morphologique avec MeCab
J'ai essayé de résumer le support d'iOS 14
J'ai essayé la communication UDP avec Java
J'ai essayé d'expliquer la méthode
J'ai essayé GraphQL avec Spring Boot
J'ai essayé de résumer l'apprentissage Java (1)
J'ai essayé de résumer Java 8 maintenant
C # (polymorphisme: polymorphisme)
J'ai essayé de personnaliser Slim avec Scaffold
J'ai essayé d'expliquer Active Hash
J'ai essayé de résoudre les 10 dernières questions qui devraient être résolues après m'être inscrit auprès d'AtCoder en Java
Correction de la possibilité de sauvegarder une colonne spécifique vide avec l'enregistrement actif
[Java] On a dit que Java pouvait concaténer des chaînes avec +, alors j'ai vérifié