Material-ui: Les saisies peuvent-elles être simplifiées pour améliorer les performances ?

Créé le 7 janv. 2020  ·  70Commentaires  ·  Source: mui-org/material-ui

Comme suggéré par @eps1lon dans #18128, je crée ce numéro comme un endroit pour discuter des saisies Material-UI et si elles peuvent être simplifiées pour réduire le temps passé à les vérifier, en particulier pendant l'édition.

Il y a toujours une tension entre avoir les types les plus exacts (qui fournissent les meilleures erreurs et complétions d'éditeur) et avoir la vérification de type rapide (l'extrémité du spectre étant any ).
Des problèmes tels que https://github.com/microsoft/TypeScript/issues/34801 suggèrent que Material-UI pourrait bénéficier d'un assouplissement de l'exactitude afin de récupérer des performances.

D'après les reproductions que j'ai étudiées jusqu'à présent, une grande partie de la lenteur semble provenir du grand nombre de noms de propriétés CSS (voir https://github.com/mui-org/material-ui/blob/master/packages/ material-ui-styles/src/withStyles/withStyles.d.ts). N'étant pas moi-même un utilisateur CSS actif, j'ai quelques questions naïves :

1) Ai-je raison de supposer qu'avoir un nom et un type pour chaque propriété CSS bien connue est incroyablement précieux et n'est-il pas quelque chose que nous pourrions abandonner ?
2) Le type CSSProperties semble exister pour prendre en charge les "pseudo sélecteurs et requêtes multimédias", qui - selon ma lecture limitée - semblent être nommés sacs de propriétés CSS supplémentaires.
a) Ces sacs sont-ils eux-mêmes récursifs ou n'y a-t-il qu'une seule couche supplémentaire ? Autrement dit, passez-vous de width à foo.width ou à foo.bar.width , etc. ? S'il ne s'agit que d'un niveau, la simplification des types réduit ma reproduction locale de 4,6 secondes à 3,6 secondes (c'est-à-dire une grande victoire).
b) J'ai moi-même joué avec les types et je n'ai rien trouvé de mieux que BaseCSSProperties[keyof BaseCSSProperties] , mais - comme je suppose que vous le savez - ce n'est pas un type très utile. Il dit essentiellement que n'importe quelle propriété CSS peut avoir le type de n'importe quelle (autre) propriété CSS - ce n'est que légèrement mieux que any .
3) Dans StyleRules , s'il n'y a pas de propriétés, vous obtenez soit CSSProperties soit () => CSSProperties (que j'appellerai négligemment "Thunked CSSProperties"), ce qui est logique - le CSSProperties peut être paresseux. S'il y a des propriétés, vous obtenez soit CreateCSSProperties<Props> , ce qui est logique - le Props peut être nécessaire pour calculer le CSSProperties - ou (props: Props) => CreateCSSProperties<Props> , ce que j'ai fait Je ne comprends pas, car il s'agit en fait d'une double paresse - vous devez passer le Props une fois pour obtenir le CreateCSSProperties , puis à nouveau pour obtenir des propriétés individuelles. Pourquoi est-ce « double réflexion » ?

Séparément, je suppose, mais je n'ai pas encore démontré que IsEmptyInterface est trop cher pour les avantages qu'il procure. Cependant, il est tout à fait possible que je ne comprenne pas pleinement les avantages, il serait donc utile d'en savoir plus.

Pouvons-nous travailler ensemble pour trouver le bon équilibre entre précision et performance ? (Remarque : « juste rendre le compilateur plus rapide » est évidemment une stratégie viable, mais j'aimerais que les frappes soient bien placées avant de les optimiser.) Merci !

performance typescript

Commentaire le plus utile

J'ai commencé à ajouter Material UI ( 4.9.4 ) à mon projet aujourd'hui, et le ralentissement est vraiment si important que je ne pense même pas pouvoir l'utiliser dans mon projet. Je viens d'ajouter un simple composant <Slider/> , personnalisé à l'aide de withStyles() .

Nous parlons d'un retour instantané de TypeScript dans mon IDE à ce qui ressemble parfois à 5 à 10 secondes (pour des parties de mon code qui n'interagissent même pas avec Material UI maintenant - il s'agit simplement d'un ralentissement complet de TypeScript dans le fichier qui utilise le composant). Quelque chose ne va pas vraiment avec ces types (ou oui, trop complexe), il semble que @amcasey fasse de bonnes enquêtes - j'espère que vous pourrez aller au fond des choses !

J'essaie de trouver un moyen d'exclure au moins tous les éléments TypeScript pour @material-ui pour l'instant (faites essentiellement le module entier any ) - mais TypeScript ne semble pas rendre cela assez facile.

Tous les 70 commentaires

Je ne connais pas les types d'interface utilisateur matérielle, mais j'essaie de répondre à ces questions.

  1. Oui, la prise en charge complète de toutes les propriétés CSS déclarées dans les normes Web actuelles est utile.
  2. a) Dans notre cas nous n'utilisons jamais une profondeur supérieure à 2, mais des cas comme celui-ci sont tout à fait possibles
    ``` tapuscrit
    const styles = (thème : Thème) =>
    createStyles({
    une div : {
    '&:bouton de survol' : {
    visibilité : 'visible',
    opacité : 1,
                ':after': {
                    content: 'x',

                    [theme.breakpoints.up('lg')]: {
                        content: 'close',
                    },
                }
            },
        }
    });
```
b) I do not understand why `BaseCSSProperties[keyof BaseCSSProperties]` is needed there

  1. Je pense que (props: Props) => CreateCSSProperties<Props> n'est pas nécessaire, nous avons exclu ce type dans notre version des types material-ui, et rien de grave ne s'est produit.

Cela pourrait valoir la peine d'examiner l'implémentation des types dans la version 3.9.3, car dans cette version, la vérification des types était assez rapide et la saisie était bonne.

Tout d'abord, je tiens à vous remercier d'avoir contacté et examiné cette question. Il est incroyablement utile d'avoir quelqu'un pour évaluer quelles parties des types sont lentes ou non.

  1. Ai-je raison de supposer qu'avoir un nom et un type pour chaque propriété CSS bien connue est incroyablement précieux et n'est-il pas quelque chose que nous pourrions abandonner ?

Il est impossible d'être impartial ici. Je ne pense pas que nous puissions y renoncer en regardant l'écosystème au sens large. Les devtools Chrome ont cette fonctionnalité, réagissent eux-mêmes en tapant le prop style avec CSSProperties etc. Je ne me vois pas passer de l'IDE au navigateur et vérifier s'il s'agissait d'une décoration de texte ou de police ou transformation de texte.

  1. [...]
    Ces sacs sont-ils eux-mêmes récursifs ou n'y a-t-il qu'une seule couche supplémentaire ?

Je devrais vérifier la solution CSS-in-JS que nous utilisons. Techniquement, les requêtes média en CSS peuvent être récursives. Je serais prêt à couper cette récursivité et voir si nous obtenons des rapports. Les requêtes multimédias techniquement imbriquées peuvent être aplaties avec l'opérateur and . Nous devrions cependant le limiter à deux niveaux : un pour les requêtes média et un pour les pseudo sélecteurs. Cela devrait toujours être vérifié par type IMO :

const styles = {
  root: {
    '<strong i="18">@media</strong> (max-width: 12cm)': {
      ':hover': {}
    }    
  }
}

Est-ce quelque chose que vous vous voyez écrire @oliviertassinari ?

  1. [...]
    CSSProperties - ou (props : Props) => CreateCSSProperties, ce que je n'ai pas compris car il est en fait doublement paresseux - vous devez passer une fois dans les Props pour obtenir les CreateCSSProperties, puis à nouveau pour obtenir des propriétés individuelles. Pourquoi est-ce « double réflexion » ?

Si l'argument lui-même n'est pas un sac de propriétés mais une fonction, alors il nécessite un thème. Les styles peuvent dépendre de deux types de sacs de propriétés différents : le thème (disponible via l'API contextuel de React) ou les accessoires (directement transmis au composant) :

makeStyles({ root: { color: 'blue' }}); // A
makeStyles(theme => ({ root: { color: theme.color } })); // B
makeStyles({ root: props => ({ color: props.color})}); // C
makeStyles({ root: { color: props => props.color } }); // D: same as C, only exists for dev ergonomics
makeStyles(theme => ({ root: props => ({ color: props.color || theme.color }) })); // E: what you called "double-lazy"

Il s'agit moins d'une évaluation paresseuse pour améliorer les performances que d'avoir à attendre que le contexte et les accessoires soient disponibles.

Séparément, je suppose, mais je n'ai pas encore démontré que IsEmptyInterface est trop cher pour les avantages qu'il procure. Cependant, il est tout à fait possible que je ne comprenne pas pleinement les avantages, il serait donc utile d'en savoir plus.

Il y a un cas où cela est utilisé :

Envisager

const useStaticStyles = makeStyles({ root: { color: 'blue' } });
const useDynamicStyles= makeStyles({ root: { color: props =>  props.color } })
function Component() {
  const staticClasses = useStaticStyles(); // No error
  const throwingClasses = useDynamicStyles(); // $ExpectError
  const dynamicClasses = useDynamicStyles({ color: 'blue' });
}

Pour déduire la signature d'appel de la fonction renvoyée par makeStyles (c'est-à-dire le crochet nommé quelque chose comme useSomeStyles ). Nous devons vérifier quel type de sac de style est transmis à makeStyles . Nous avons déjà une aide pour déduire les types d'accessoires utilisés dans le sac de style . Si le sac de style est statique, c'est-à-dire que TS en déduit le type {} . Ensuite, nous vérifions le type inféré des props avec IsEmptyInterface et pour une branche, nous utilisons une signature d'appel avec 0 paramètres et pour l'autre branche, nous utilisons une signature d'appel avec 1 paramètre qui est égal au type de props inféré ( voir StylesRequireProps et StylesHook .

En bref : On évite d'avoir à écrire useStaticStyles({}) ou useStaticStyles(null as any) . Il a été introduit dans https://github.com/mui-org/material-ui/pull/14019 pour fermer https://github.com/mui-org/material-ui/issues/14018. Je suppose que nous pouvons court-circuiter la détermination de la signature de l'appel. Peut-être surcharger la signature d'appel au lieu d'utiliser des types conditionnels ?

Le problème avec cette "fonctionnalité" est que les utilisateurs avancés n'ont aucun problème à utiliser null as any s'ils comprennent pourquoi. Peut-être que même passer un objet vide est ok même s'il n'est pas nécessaire. Cependant, c'est très déroutant/frustrant lorsqu'il n'est pas utilisé avec Material-UI ou TypeScript. D'autant plus que la plupart des styles ne sont pas basés sur des accessoires de toute façon.

Il semble que la plupart du temps, le vérificateur de type soit occupé par la solution de style ? Je me serais attendu à la signature d'appel pour nos composants, c'est-à-dire quels accessoires sont possibles la plupart du temps.

Je peux explorer plus de référentiels pour examiner spécifiquement l'utilisation de withStyles ou makeStyles . Jusqu'à présent, je n'ai regardé que l'utilisation des accessoires.

Est-ce quelque chose que vous vous voyez écrire @oliviertassinari ?

@eps1lon Nous avons quelques occurrences de cette imbrication dans la base de code (par exemple avec <strong i="8">@media</strong> (hover: none) ). Mais ce n'est pas très fréquent pour les composants de base. J'imagine que c'est le même userland. Cela pourrait certainement faire partie du compromis.

@beholderrk

  1. J'ai pensé autant, mais j'ai pensé que je pourrais aussi bien demander.
  2. a) La profondeur deux doit être exprimable - il y aura juste un peu plus de duplication que la profondeur un.
    b) Il m'a fallu un certain temps pour comprendre cela et j'aimerais pouvoir l'expliquer en personne plutôt que par texte. Fondamentalement, la signature d'index indique que toutes les propriétés ont le même type. Cela ne peut fonctionner que s'il spécifie un type qui fonctionne pour tous. Une façon de le faire est de construire l'union de tous les types de propriété, BaseCSSProperties[keyof BaseCSSProperties] - alors il sera vrai que chaque propriété a un type compatible. Par exemple, supposons que les seules propriétés que vous puissiez avoir dans CSS soient name: string et width: number . Une façon de spécifier une signature d'index qui fonctionne avec les deux propriétés serait de dire que chaque propriété est un string | number . Ce n'est pas génial - name ne sera jamais un number et width ne sera jamais un string - mais ça marche. Le vrai problème est que la chose que vous voulez ne peut pas être exprimée (du moins, pour autant que nous ayons pu le déterminer - il pourrait y avoir un hack "intelligent" qui le fait). Vous voulez en fait dire que votre type contient name: string , width: number ou x: CSSProperties , où x est tout sauf name ou width - c'est le "tout sauf" qui manque. J'espère que c'est un peu plus clair.
  3. Il semblait que @eps1lon avait quelque chose à dire à ce sujet, mais

Une base de référence connue serait très utile. As-tu un lien par hasard ?
Edit : trouvé.

@eps1lon Heureux de faire partie de la conversation. Les types rapides et corrects sont bons pour tout le monde. ??

  1. Aucun argument ici - j'ai juste pensé que je demanderais tôt car cela aurait court-circuité toute la conversation.
  2. Deux couches semblent faisables (avec la mise en garde notable que les types seront toujours largement inutiles). Je vais voir si je peux rédiger quelque chose.
  3. Avec mon manque de contexte, il n'était pas clair que les thèmes et les accessoires étaient différents. S'ils le sont, alors la structure a du sens. Merci de clarifier.

En ce qui concerne isEmptyInterface , pourriez-vous simplement rendre le paramètre de propriétés (par exemple) useStaticStyles facultatif ? Ce serait moins correct, dans le sens où les appelants pourraient les omettre quand ils sont attendus, mais il serait beaucoup moins cher de taper check. Comme je l'ai dit, je n'ai pas de chiffres ou quoi que ce soit pour vous - ce ne sont que des spéculations de ma part.

Que pensez-vous de 2(b) ? Il semble que ce type ne fournisse pas beaucoup de valeur, car il indique essentiellement que tout nom de propriété sera accepté et que le type de retour peut être l'un d'un grand nombre de choses.

En ce qui concerne isEmptyInterface, pourriez-vous simplement rendre le paramètre properties pour (par exemple) useStaticStyles facultatif ?

J'aimerais d'abord expérimenter la surcharge de la signature d'appel et voir si cela a un impact. Ensuite, nous essaierons de le rendre moins sonore en le rendant toujours facultatif. Il semble plus sûr que d'habitude de le rendre moins solide, car presque tous les cas d'utilisation ne l'appellent qu'une seule fois, vous ne ferez donc probablement l'erreur qu'une seule fois et cela fait surface assez rapidement. Cela va être difficile à vendre si cela ne nous apporte pas beaucoup de performances. J'utiliserai le référentiel créé pour le problème d'origine (https://github.com/microsoft/TypeScript/issues/34801#issue-514055289).

Que pensez-vous de 2(b) ? Il semble que ce type ne fournisse pas beaucoup de valeur, car il indique essentiellement que tout nom de propriété sera accepté et que le type de retour peut être l'un d'un grand nombre de choses.

Ignoré ça par accident. Je le regarderai après l'expérience IsEmptyInterface.

@eps1lon Tout à fait d'accord - gardez isEmptyInterface si l'éliminer n'est pas un gain substantiel.

Avec #19320, nous nous sommes débarrassés de certains types conditionnels complexes où la surcharge de fonction obtenait la même chose (suppression de IsEmptyInterface et de tout type de logique booléenne). Bien qu'il semble que cela ne nous a pas beaucoup gagné en plus d'avoir moins de code.

Je tiens à ajouter que je bascule actuellement entre TS 3.2.4 et 3.7.4. Notre suite de tests de type s'exécute 50 % plus lentement dans 3.7.4 par rapport à 3.2.4 (~ 90s contre 50s).

Je vais continuer à chercher si nous pouvons limiter la profondeur de CSSProperties et supprimer complètement la prise en charge des requêtes multimédias et des pseudo-sélecteurs. Les avoir non tapés n'est pas vraiment une option cependant. Le vérificateur de type doit pouvoir les vérifier dans un délai raisonnable.

Il se peut que le vérificateur de type soit le véritable goulot d'étranglement. Peut-être pouvons-nous rechercher dans quelle version les performances ont été atteintes.

Si vous m'envoyez les commandes que vous exécutez dans 3.2.4 et 3.7.4, je peux profiler localement. Cependant, l'expérience suggère que la cause s'avérera probablement être une vérification supplémentaire souhaitable ajoutée depuis 3.2.4. (Et je suppose que "0s" est une faute de frappe - probablement "40s" ou "50s" ?)

En ce qui concerne CSSProperties, je suis d'accord pour dire que conserver les noms et les types de propriétés est extrêmement précieux. Cependant, je pense qu'il y a plus que de les vérifier dans un laps de temps raisonnable - le premier problème est que le système de types ne peut pas réellement exprimer la forme que vous voulez. Je pense que nous allons probablement passer du temps à travailler sur une solution générale au problème - puis-je supposer que vous seriez intéressé à participer à cette discussion ?

Nous avons des scripts pour comparer plusieurs versions du compilateur, donc, si vous pouvez identifier un test assez stable que vous voudriez que nous exécutions, nous pouvons représenter graphiquement le ralentissement au fil du temps.

(Et je suppose que "0s" est une faute de frappe - probablement "40s" ou "50s" ?)

Désolé, c'est 50 ans.

Si vous m'envoyez les commandes que vous exécutez dans 3.2.4 et 3.7.4, je peux profiler localement.

C'est juste yarn typescript à la racine qui exécute la même commande dans chaque espace de travail qui l'implémente. Par exemple, yarn workspace @material-ui/styles run typescript teste nos types avec les tslint et les dtslint de $ExpectError . En 3.7.4 nous avons rencontré quelques échecs et avons dû ajuster nos tests (voir #19242)

le premier problème est que le système de types ne peut pas réellement exprimer la forme que vous voulez.

Je m'en doutais. Il semble que la façon dont nous mélangeons une forme "concrète" avec un objet avec une signature d'index ne soit qu'une solution de contournement.

puis-je supposer que vous seriez intéressé à participer à cette discussion?

Définitivement. Je vais passer un peu plus de temps avec les CSSProperties non récursives, puis écrire un peu plus de tests pour illustrer ce que nous recherchons dans ces types. Je soupçonne que d'autres solutions de style css-in-js rencontrent des goulots d'étranglement de performances similaires.

J'essaierai ces commandes demain (je suppose que je devrais mentionner que je suis à l'heure du Pacifique et que je respecte les jours fériés aux États-Unis).

Il semble que la façon dont nous mélangeons une forme "concrète" avec un objet avec une signature d'index ne soit qu'une solution de contournement.

Merci, j'ai eu du mal avec la meilleure façon d'exprimer cela. Oui, vous avez raison de dire que la signature d'index ne fait pas ce que vous voulez. Nous avons quelques réflexions sur une variante qui pourrait le faire, mais nous devons explorer les implications en termes de performances.

Je soupçonne que d'autres solutions de style css-in-js rencontrent des goulots d'étranglement de performances similaires.

Tout à fait. Nous espérons que tout ce que nous faisons pour vous pourra être généralisé pour améliorer l'ensemble de l'écosystème.

J'ai l'impression qu'il me manque quelque chose d'évident, mais je suis actuellement bloqué. Tout d'abord, j'ai abandonné Windows - les choses semblent mieux fonctionner sous Linux. Faites-moi savoir si vous souhaitez creuser cela. Deuxièmement, je peux faire fonctionner yarn typescript - proprement, pour autant que je sache - mais il semble exécuter tslint, plutôt que pur tsc. Lorsque j'exécute tsc sur le même tsconfig.json (je teste spécifiquement avec des styles), j'obtiens environ 40 erreurs. Qu'est-ce que je fais mal? À des fins de profilage, réduire la reproduction à une seule invocation tsc serait très utile.

@amcasey yarn typescript ne concerne pas la compilation mais le test de nos types. Nous utilisons une configuration similaire à celle utilisée dans le référentiel DefinitelyTyped. Les fichiers TypeScript dans packages/* sont presque toujours qu'un tas d'instructions qui devraient soit réussir, soit échouer, que nous attrapons avec $ExpectError .

Je pense que le meilleur cas de test "réel" utilise tsc sur nos documents via yarn workspace docs run tsc -p tsconfig.json après avoir ajouté skipLibCheck: true et noEmit: true à ./docs/tsconfig.json :

--- a/docs/tsconfig.json
+++ b/docs/tsconfig.json
@@ -3,6 +3,8 @@
   "include": ["types", "src/pages/**/*"],
   "compilerOptions": {
     "allowJs": false,
-    "noUnusedLocals": true
+    "noUnusedLocals": true,
+    "noEmit": true,
+    "skipLibCheck": true
   }
 }

@eps1lon Merci d'avoir clarifié. Je ne suis pas ravi que tslint soit devenu plus lent, mais j'aimerais me concentrer sur une variable à la fois. Je vais exécuter la version de documentation que vous avez suggérée avec différentes versions de tapuscrit et voir si quelque chose saute. Merci!

Cette configuration est parfaite. Je vois le temps de contrôle doubler entre 3,3 et 3,4.

| Versions | Vérifier l'heure |
|-|-|
| 3.2 | 16.71s |
| 3.3 | 16.79s |
| 3.4 | 35.25s |
| 3.5 | 21h40 |
| 3.6 | 23.10s |
| 3.7 | 27.39s |

Je vais creuser un peu plus, mais on me dit que l'implémentation 3.3 des types conditionnels était incomplète, l'implémentation 3.4 était lente et l'implémentation 3.5 est bonne. Donc, malheureusement, cela est probablement prévu.

Plus précisément, je soupçonne que ce changement a introduit le ralentissement décrit dans ce bogue .

Je trouve préoccupant qu'entre 3,5 et 3,7, il y ait eu une augmentation de 6 secondes du temps nécessaire pour exécuter le contrôle. Cela a l'air assez substantiel.

@embeddedt Ces chiffres proviennent d'exécutions uniques avec chaque version, il y a donc probablement pas mal de bruit. Cependant, je vais creuser et voir si je peux trouver quelque chose.

Je l'ai refait sur une machine virtuelle Linux et 3.7 était systématiquement 20-25% plus lent que 3.5.

Cela s'est avéré assez difficile à diviser car les exécutions consécutives de la même construction varient d'environ 5 % et la différence entre 3,5 et 3,6 ou entre 3,6 et 3,7 n'est que d'environ 10 %.

Une chose suspecte que j'ai remarquée est que styled-components fournit des fichiers .d.ts séparés pour TS >= 3.7, donc la comparaison peut ne pas être des pommes avec des pommes.

À ma grande surprise, les nouveaux types styled-components semblent être plus rapides. Comparer des pommes avec des pommes facilitera néanmoins l'enquête.

Je ne pouvais pas penser à une solution intelligente, je vais donc tracer le temps de compilation fusion par fusion et rechercher des pics. J'espère avoir des chiffres demain.

@amcasey Merci pour vos efforts dans cette recherche ! Vraiment chouette de voir les membres de l'équipe TS et Material UI travailler ensemble. Je suis tombé sur ce problème Github en essayant de comprendre pourquoi notre expérience d'éditeur avec Material UI est si lente (nous l'utilisons dans deux projets au travail). Je peux certainement confirmer que nous constatons un impact assez important sur l'intellisense et la convivialité à l'intérieur de VsCode.

À ce stade, nous serions heureux d'échanger un peu de sécurité de type dans notre JSS contre un retour rapide pour le reste de la bibliothèque. Parfois, il faut 8 à 10 secondes d'attente avant que le serveur Typescript ne rattrape les changements de code

Même avec des moyennes sur trois passages, les données sont très bruyantes. Cependant, il semble y avoir une baisse notable du temps d'exécution à https://github.com/microsoft/TypeScript/commit/ad322a561a301ae357da051b9221b2222c13be36 une augmentation notable (retour à peu près au niveau précédent) à https://github.com/microsoft/TypeScript /commit/480b73915fdd805952fd355e4cf3e1bc803e0878 et une tendance générale à la hausse après cela (bien que cela me semble trop uniforme et que je soupçonne des facteurs environnementaux), y compris un pic particulier à https://github.com/microsoft/TypeScript/commit/c5e6d95e930048a033868d72440a9296904a33ec. Je vais me concentrer sur les deux premiers jusqu'à ce que j'exécute d'autres tests pour confirmer la tendance générale à la hausse (comment cela pourrait-il empirer uniformément à chaque commit ?).

La tendance à la hausse résiste à un examen minutieux et je n'ai aucune idée de ce qui pourrait en être la cause. Peut-être que les ralentissements discrets sont si proches les uns des autres que le bruit les fait ressembler à une seule courbe.

J'ai augmenté jusqu'à 10 courses par commit et il y a maintenant quatre régressions distinctes dans la zone inclinée. :le sourire:

https://github.com/microsoft/TypeScript/commit/26caa3793e310e271ddee8adc1804486e5b0749f (~700ms)
https://github.com/microsoft/TypeScript/commit/250d5a8229e17342f36fe52545bb68140db96a2e (~500ms)
https://github.com/microsoft/TypeScript/commit/7ce793c5b8c621af5ce50af0ca3958c7bd6541bf (~1300ms)
https://github.com/microsoft/TypeScript/commit/28050d5c47c6cd7627555f12cf13b1062f80322a (~400ms)

(Le temps total avant le début des régressions était d'environ 33 s.)

Juste pour tempérer un peu les attentes : il est fort probable que plusieurs de ces régressions se révèlent être de précieux chèques supplémentaires et, même si nous parvenions à obtenir tous ces chèques gratuitement, nous n'économiserions encore que 20 % « beaucoup trop long ".

Edit : j'ai mis à jour les liens. Parce que je reculais dans le temps, j'étais confus et j'ai signalé la fusion _avant_ chaque régression.

@eps1lon Quelqu'un de ce côté a suggéré que la suppression de @ts-ignore pourrait aider. Fondamentalement, lorsqu'une erreur est détectée, on suppose que la priorité absolue de l'utilisateur est d'obtenir de bonnes informations sur l'erreur, il est donc possible qu'un tas de travail supplémentaire soit effectué. Si cette information est supprimée par la suite (à cause de @ts-ignore ), alors ce temps est simplement perdu. (Malheureusement, il n'est pas simple de détecter qu'une erreur n'a pas besoin d'être détectée.) Une stratégie alternative consiste à ajouter des assertions de type explicites (y compris à any ) jusqu'à ce que le compilateur cesse de se plaindre.

@eps1lon Quelqu'un de ce côté a suggéré que la suppression de @ts-ignore pourrait aider.

Nous n'avons eu qu'une seule utilisation en docs/ . Je l'ai quand même enlevé au cas où : #19504

Pour être honnête, il semble que @ts-ignore soit un anti-modèle dans ce cas. Non seulement cela ne vous donne pas d'informations utiles, c'est-à-dire quel type d'erreur avons-nous, mais c'est aussi un goulot d'étranglement des performances.

Pour autant que je sache, @ts-ignore n'est utile que dans les fichiers .js cours de vérification de type.

Hmm, cela n'explique presque certainement pas pourquoi les messages d'erreur d'amélioration du PR ont régressé les performances. Cela ressemble certainement à une amélioration. ??

Je suis assez nouveau dans le monde de TypeScript, en particulier en ce qui concerne les solutions de style en JS, mais j'ai suivi tranquillement ce fil le mois dernier et j'étais curieux d'entendre les réflexions des gens sur une solution de contournement potentielle, à moins à court terme.

Je suppose que certains utilisateurs (moi-même en étant un) n'utilisent pas beaucoup le système de style intégré, ou l'évitent complètement. Je le fais principalement parce que je suis beaucoup plus familier avec CSS ou Sass et je n'ai pas vraiment eu le temps de creuser comment utiliser efficacement le système de style JS. Je préfère simplement créer mes propres noms de classe, écrire un fichier de feuille de style séparé, utiliser les noms de classe dans mes composants React et continuer. Essentiellement, je stylise comme si j'écrivais du HTML simple.

Cela étant dit, est-il possible/pratique d'ajouter un indicateur qui désactive la vérification de type pour les parties coûteuses du système de style (éventuellement en faisant des choses comme type CSSProperties = any ) ? Je ne connais pas les statistiques sur le nombre de personnes utilisant le système de style par rapport à ne pas l'utiliser, mais je pense que cela ne peut pas vraiment faire beaucoup de mal (à condition qu'une vérification ait été ajoutée pour tester les frappes avec ce drapeau défini) , et ce serait un moyen rapide d'améliorer les performances d'au moins un segment d'utilisateurs.

Je voulais juste mentionner l'idée générale; n'hésitez pas à l'abattre. :slightly_smileing_face:

@embeddedt De manière générale, marquer explicitement quelque chose comme any est un bon moyen de désactiver la vérification de type pour ce symbole. Cela dit, je ne me souviens pas si vous pouvez simplement écraser une déclaration précédente ou plutôt, comme vous le suggérez, vous auriez besoin du support du compilateur pour éviter les problèmes de déclaration en double.

Nouveaux nombres (machine différente, métrique de temps différente) :

| Versions | Temps total |
|-|-|
| 3.5.3 | 32,5 s |
| 3.7.5 | 35.9s |
| maître | 29.9s |

Certains des problèmes que j'ai postés ci-dessus sont toujours ouverts, mais nous sommes fondamentalement revenus à 3,5 perf (pour ce benchmark). Évidemment, c'est encore beaucoup plus lent que nous le souhaiterions, mais le prochain lot de changements sera probablement du côté de l'interface utilisateur matérielle.

Testé 3.8.1 sur notre suite de tests et il semble qu'ils soient aussi rapides que les précédents en utilisant 3.2.4 (3.7 était nettement plus lent).

Franchement, je ne peux pas croire combien de performances nous avons pu récupérer sans abandonner la nouvelle fonctionnalité. :smile: Je pense qu'il pourrait y avoir un peu plus de mou (par exemple https://github.com/microsoft/TypeScript/pull/36754), mais je pense toujours que le changement le plus impactant serait une simplification des types CSSProperties. Avez-vous eu l'occasion de jouer avec ceux-ci? Il semble qu'au moins un sous-ensemble d'utilisateurs (par exemple @embeddedt) serait heureux de renoncer à une vérification de type en échange d'un gain de performance.

Il semble qu'au moins un sous-ensemble d'utilisateurs (par exemple @embeddedt) serait heureux d'abandonner une vérification de type en échange d'un gain de performance

Quelqu'un de l'équipe TS n'a-t-il pas récemment tweeté que pour chaque utilisateur qui veut des types plus stricts, il y en a un qui veut des types plus lâches ? :le sourire:

Pour moi, il ne s'agit pas vraiment de vérifier le type (les outils de développement du navigateur ont de bien meilleures capacités de vérification de votre CSS). Il s'agit davantage d'avoir la saisie semi-automatique disponible.

Je vais jouer avec différentes "versions" et voir comment elles fonctionnent.

@amcasey Je ne pense pas que la nature récursive de CSSProperties (appelée CSSObject dans styled-components) soit le problème principal. Sinon leur perf serait aussi mauvaise que la nôtre. Voir https://github.com/eps1lon/mui-types-perf/pull/6 et les journaux de référence .

Cela pourrait être plus un problème avec la quantité de "surcharge" que nous faisons. styled-components n'autorise qu'un objet statique alors que nous autorisons une version thunk ainsi que chaque propriété étant un thunk. Je ne suis pas sûr cependant.

J'aimerais simplifier la signature de type (puisqu'il s'agit de l'IMO également plus facile à comprendre pour les développeurs), mais on m'a explicitement demandé de faire correspondre l'implémentation JSS. Maintenant que nous le soutenons, nous ne pouvons pas facilement revenir en arrière. Surtout si le gain est de l'ordre de 20%. Je ne pense pas que cela justifie la casse.

Les types peuvent-ils être rendus moins précis (en fonction d'un paramètre utilisateur) ? Cela ne devrait casser aucun code existant (car le paramètre peut être désactivé par défaut) et permettrait aux utilisateurs comme moi qui n'ont pas besoin des types complexes de voir rapidement une augmentation des performances.

permettrait aux utilisateurs comme moi qui n'ont pas besoin des types complexes de voir rapidement une augmentation des performances.

Il n'est même pas confirmé que vous gagneriez une différence notable. J'ai vu des gains de 15% de perf, mais on peut se demander si cela est reconnaissable.

Le "paramètre utilisateur" que j'ai pu voir corrige le package lors de l'installation. Nous n'avons pas la bande passante pour maintenir plusieurs versions des frappes.

@eps1lon Désolé, je pense que ma question n'était peut-être pas claire. Je pense que CSSProperties est bien (bien que, évidemment, si ce serait plus rapide s'il était plus petit) - j'espérais en fait qu'il pourrait y avoir de la place pour simplifier les sous-types dans https://github.com/mui-org /material-ui/blob/master/packages/material-ui-styles/src/withStyles/withStyles.d.ts. Par exemple, obtiendriez-vous moins de complétions si vous changeiez ce type en any ?

Edit : sur ma box, cela rend la compilation du projet docs 15% plus rapide (29,7s à 25,5s), mais je ne connais pas l'effet sur l'expérience de montage.
Edit 2: En fait, une fois que vous avez renoncé à plier la partie récursive du type, vous pouvez simplement utiliser BaseCreateCSSProperties et toute autre propriété aura le type any (c'est-à-dire que vous gardez les types réels des propriétés CSS).
Edit 3: Edit 2 ne fonctionne pas en raison d'une vérification excessive des propriétés (c'est-à-dire que les noms de propriétés arbitraires ne sont pas autorisés dans les littéraux d'objet).

Votre point sur les complétions par rapport à la vérification de type était super intéressant parce que j'avais l'hypothèse que certains auteurs de type pourraient ressentir cela. @DanielRosenwasser Je pense que nous avons envisagé de faire quelque chose comme ça pour s'adapter au modèle "a" | "b" | string - est-ce que ça va quelque part ?

Notez également que styled-components (nous pensons) des problèmes de performances de vérificateur étroitement liés.

En ce qui concerne la possibilité de spécifier le type plus précisément, j'ai déposé https://github.com/microsoft/TypeScript/issues/36782.

On dirait que emotion pourrait être dans le même bateau.

J'ai commencé à ajouter Material UI ( 4.9.4 ) à mon projet aujourd'hui, et le ralentissement est vraiment si important que je ne pense même pas pouvoir l'utiliser dans mon projet. Je viens d'ajouter un simple composant <Slider/> , personnalisé à l'aide de withStyles() .

Nous parlons d'un retour instantané de TypeScript dans mon IDE à ce qui ressemble parfois à 5 à 10 secondes (pour des parties de mon code qui n'interagissent même pas avec Material UI maintenant - il s'agit simplement d'un ralentissement complet de TypeScript dans le fichier qui utilise le composant). Quelque chose ne va pas vraiment avec ces types (ou oui, trop complexe), il semble que @amcasey fasse de bonnes enquêtes - j'espère que vous pourrez aller au fond des choses !

J'essaie de trouver un moyen d'exclure au moins tous les éléments TypeScript pour @material-ui pour l'instant (faites essentiellement le module entier any ) - mais TypeScript ne semble pas rendre cela assez facile.

@lostpebble Est-ce que la même chose se produit en utilisant autre chose que withStyles pour personnaliser le curseur, disons des modules CSS ?

@lostpebble Nous n'avons actuellement pas de moyen pris en charge pour exclure un ensemble particulier de types. Si vous le voulez vraiment, vraiment, la chose à expérimenter serait les mappages de chemin. Vous pouvez essayer un mappage de chemin comme "@material-ui/*": ["simplemui"] , puis créer un simplemui.d.ts contenant

declare const x: any;
export = x;

Cela rendrait effectivement tous les types de matériel-ui any . C'est certainement un hack et pas quelque chose que je peux recommander, mais cela pourrait débloquer votre expérience d'édition.

Je pense que nous avons fait de bonnes améliorations (quelque part dans la zone des 30%) mais il semble que tout ce que nous pourrions faire pour le moment est de rendre les frappes plus lâches.

Cela nécessite absolument des propositions concrètes, par exemple avec quel code erroné seriez-vous d'accord pour être accepté par le vérificateur de type. Ensuite, nous aurions besoin de comparer et de voir si cela fait une brèche significative.

Vous devez comprendre que les régressions introduites à dessein ajoutent beaucoup de travail aux responsables, car nous devons expliquer cela aux utilisateurs de bibliothèques et sont globalement assez stressants.

Ce n'est donc pas une priorité pour moi pour le moment, à moins que quelqu'un n'ait des informations exploitables. Sinon, je dois consacrer trop de temps à très peu de retour.

Dans mon cas pour makeStyles(theme => createStyles(...)) , retournant Record<ClassKey, any> de createStyles(...) presque ~moitiés~ (dans mon code et mon ordinateur, environ ~1200ms -> 750ms~ 1400ms → 1100ms) encodedSemanticClassifications-full: elapsed time affiché dans le journal tsserver (cela ne semble pas être un travail coûteux, mais attend peut-être que la vérification du type soit terminée).

export default function createStyles<ClassKey extends string, Props extends {}>(
  styles: StyleRules<Props, ClassKey>,
): Record<ClassKey, any>;

createStyles(...) vérifie la structure du style afin que nous puissions ignorer la vérification du type pour l'argument-type-of-massive-union de makeStyles vs return-type-of-massive-union de createStyles.

~(Et commenter l'intégralité du code makeStyles : 650ms)~

@ypresto createStyles n'est nécessaire que pour les versions dactylographiées sans les assertions const . Si vous pouvez utiliser { display: 'block' as const } dans votre base de code (ts >= 3.4), utilisez-le sur createStyles .

@eps1lon Nous l'avons remarqué et avons essayé de changer en docs mais les résultats n'ont pas été impressionnants.

@eps1lon avec const et sans createStyles , IntelliSense n'affiche plus les candidats contextuels :cry:

@ypresto Il devrait. Avez-vous un exemple d'extrait de code ?

@amcasey

L'ajout de as const à l'objet extérieur ou à la propriété le tue effectivement. Je ne veux pas le placer sur chaque propriété.

const useStyles = makeStyles(theme => ({
  root: {
    // no IntelliSense
  }
} as const))

De plus, sans createStyles, il a une petite limitation pour l'achèvement de la chaîne.

const useStyles = makeStyles(theme => ({
  root: {
    direction: '|', // no IntelliSense at | (works with createStyles)
    direction: | // IntelliSense works at |
  }
}))

@ypresto Par "le tue", voulez-vous dire "le fait fonctionner de la même manière que createStyles " ?

C'est un frein de le mettre partout, mais pas plus que de mettre createStyles partout.

@amacleay Je voulais dire kills IntelliSense : priez :.

Désolé, j'ai raté vos commentaires. Je vais tenter le coup.

Je ne sais pas pourquoi mais c'est 1100ms → 750ms, fait intéressant :

 export const DropArea: React.FC<CardProps & {
   active?: boolean
   description: string
   icon?: React.ReactNode
-}> = ({ active, description, icon, children, ...props }) => {
+}> = ({ children, ...props }) => {
   const classes = useStyles()
+  const active = false
+  const icon: React.ReactNode = null
+  const description = ''
   return (
     <Card {...props} className={clsx(classes.root)} variant="outlined">

Supprimer CardProps & de FC est presque le même résultat. C'est peut-être parce que CardProps étend PaperProps, qui étend les grands HTMLAttributes.

MISE À JOUR ET HTMLAttributes<HTMLDivElement> réduisait également le temps (non mesuré).

Finalement, j'ai trouvé le plus gros, 750ms → 130ms :

Suppression de style={...} de deux typographies.

-<Typography variant="subtitle2" component="div" noWrap style={{ width: '26ch' }}>...</Typography>
+<Typography variant="subtitle2" component="div" noWrap>...</Typography>
-<Typography variant="caption" component="div" noWrap style={{ width: '20ch' }}>...</Typography>
+<Typography variant="caption" component="div" noWrap>...</Typography>

Mais pourquoi? L'ajout du même style à <div> n'affecte pas les performances. Peut-être que OverridableComponent est trop compliqué..?

(J'utilise TypeScript 3.8.3, @material-ui/core 4.9.1)

AFAIK, la façon dont Material-UI gère les styles locaux sur les composants est différente de la façon dont React le gère pour les éléments HTML.

@embeddedt Au niveau du type, il se résout en React.CSSProperties qui est le même que la prop de style de div.

@ypresto, je suis corrigé. Pardon.

Salut les gars, je ne sais pas si cela vaut la peine d'ouvrir un nouveau problème pour cela, donc je le posterai ici car il est lié à l'exactitude/la performance des types. Faites-moi savoir si je dois ouvrir un problème à la place.
En suivant la documentation pour ajouter une police personnalisée , je me retrouve avec l'erreur de frappe suivante :
Type 'string' is not assignable to type 'FontFaceFontDisplayProperty'

C'est bizarre, car les frappes csstype 2.6.9 semblent valides et les autres attributs sont corrects (en utilisant MUI 4.9.5).

const sourceSansPro = {
  fontFamily: "'Source Sans Pro'",
  fontStyle: "normal",
  fontDisplay: "swap", // won't work
  fontWeight: 400,
  src: `
    url('/static/fonts/Source_Sans_Pro/SourceSansPro-Regular.ttf') format("truetype")
  `
};

Propriété du thème :

  overrides: {
    MuiCssBaseline: {
      "@global": {
        "@font-face": [sourceSansPro]
      }
    }

Le type est type FontFaceFontDisplayProperty = "auto" | "block" | "fallback" | "optional" | "swap";

@eric-burel Il s'agit d'un problème avec l'élargissement automatique des types de scripts. Essayer

- fontDisplay: "swap", // won't work
+ fontDisplay: "swap" as "swap",

Merci ça marche, et j'ai appris un nouveau concept "élargissement de type" :) C'est bizarre que fontStyle ne soit pas affecté par exemple, ce n'est pas la seule propriété CSS définie comme une énumération mais la première fois que j'appuie dessus .

Edit : ok mon mal c'est bien documenté : https://material-ui.com/guides/typescript/#using -createstyles-to-defeat-type-widening

Finalement, j'ai trouvé le plus gros, 750ms → 130ms :

Suppression de style={...} de deux typographies.

-<Typography variant="subtitle2" component="div" noWrap style={{ width: '26ch' }}>...</Typography>
+<Typography variant="subtitle2" component="div" noWrap>...</Typography>
-<Typography variant="caption" component="div" noWrap style={{ width: '20ch' }}>...</Typography>
+<Typography variant="caption" component="div" noWrap>...</Typography>

Mais pourquoi? L'ajout du même style à <div> n'affecte pas les performances. Peut-être que OverridableComponent est trop compliqué..?

(J'utilise TypeScript 3.8.3, @material-ui/core 4.9.1)

Avez-vous trouvé que cela affectait le temps de construction, ou juste le temps qu'il faut pour qu'intellisense soit utile ? Je reçois le problème de construction (manque de mémoire) et certains de nos codes TS ont une tonne de style={someStyle} définis sur les composants. Je me demande si cela fait partie de notre problème.

@yatrix7 , de manière générale, je m'attendrais à ce que ces longs délais de vérification affectent à la fois les temps de réponse de la construction et de l'éditeur.

Est-ce que quelqu'un étudie actuellement cela? Je sais qu'il y a eu quelques améliorations en ce qui concerne le temps de vérification du type de script dans les mises à niveau de versions précédentes. Cependant, il est encore lent.
Cela ne me dérangerait pas d'examiner cela moi-même.

Cela ne me dérangerait pas d'examiner cela moi-même.

Ce serait génial. Nous ne sommes actuellement pas au courant d'éléments sur lesquels nous pouvons travailler. Ainsi, tout pointeur sur les goulots d'étranglement serait apprécié.

Ajout de quelques analyses comparatives pour l'instant, pour aider à enquêter : https://github.com/mui-org/material-ui/pull/22110

@FabianKielmann Du côté TS, j'ai travaillé sur des outils d'investigation des performances qui, j'espère, seront bientôt suffisamment matures pour s'appliquer à material-ui.

Si vous avez du temps à consacrer à cela, vous pouvez également essayer quelque chose comme https://github.com/microsoft/TypeScript/issues/38583.

Cette page vous a été utile?
0 / 5 - 0 notes