From d7224acc90f0810a491c46ad4ea9196d73e05185 Mon Sep 17 00:00:00 2001 From: William Wong Date: Wed, 1 May 2024 00:15:15 +0000 Subject: [PATCH 01/12] Early investigations --- .../performance.manyMessages.allAtOnce.html | 40 +++++++++++++++++ .../performance.manyMessages.oneByOne.html | 44 +++++++++++++++++++ .../testHelpers/createDirectLineEmulator.js | 19 ++++---- 3 files changed, 94 insertions(+), 9 deletions(-) create mode 100644 __tests__/html/performance.manyMessages.allAtOnce.html create mode 100644 __tests__/html/performance.manyMessages.oneByOne.html diff --git a/__tests__/html/performance.manyMessages.allAtOnce.html b/__tests__/html/performance.manyMessages.allAtOnce.html new file mode 100644 index 0000000000..85e8248e35 --- /dev/null +++ b/__tests__/html/performance.manyMessages.allAtOnce.html @@ -0,0 +1,40 @@ + + + + + + + + + +
+ + + diff --git a/__tests__/html/performance.manyMessages.oneByOne.html b/__tests__/html/performance.manyMessages.oneByOne.html new file mode 100644 index 0000000000..a1fcf90a09 --- /dev/null +++ b/__tests__/html/performance.manyMessages.oneByOne.html @@ -0,0 +1,44 @@ + + + + + + + + + +
+ + + diff --git a/packages/test/page-object/src/globals/testHelpers/createDirectLineEmulator.js b/packages/test/page-object/src/globals/testHelpers/createDirectLineEmulator.js index cbbcf098d6..6e00de3e51 100644 --- a/packages/test/page-object/src/globals/testHelpers/createDirectLineEmulator.js +++ b/packages/test/page-object/src/globals/testHelpers/createDirectLineEmulator.js @@ -1,11 +1,11 @@ -import createDeferred from 'p-defer'; import Observable from 'core-js/features/observable'; import random from 'math-random'; +import createDeferred from 'p-defer'; import updateIn from 'simple-update-in'; -import { createStoreWithOptions } from './createStore'; -import became from '../pageConditions/became'; import createDeferredObservable from '../../utils/createDeferredObservable'; +import became from '../pageConditions/became'; +import { createStoreWithOptions } from './createStore'; import shareObservable from './shareObservable'; function isNativeClock() { @@ -119,7 +119,7 @@ export default function createDirectLineEmulator({ autoConnect = true, ponyfill }; }, emulateConnected: connectedDeferred.resolve, - emulateIncomingActivity: async activity => { + emulateIncomingActivity: async (activity, { skipWait } = {}) => { if (typeof activity === 'string') { activity = { from: { id: 'bot', role: 'bot' }, @@ -145,11 +145,12 @@ export default function createDirectLineEmulator({ autoConnect = true, ponyfill activityDeferredObservable.next(activity); - await became( - 'incoming activity appears in the store', - () => store.getState().activities.find(activity => activity.id === id), - 1000 - ); + skipWait || + (await became( + 'incoming activity appears in the store', + () => store.getState().activities.find(activity => activity.id === id), + 1000 + )); }, emulateOutgoingActivity: (activity, options) => { if (typeof activity === 'string') { From d396fbf5b273cbe408f192c25f040fd5244839f2 Mon Sep 17 00:00:00 2001 From: William Wong Date: Wed, 1 May 2024 00:34:26 +0000 Subject: [PATCH 02/12] Add skipCheckAccessibility locally --- packages/test/harness/src/host/dev/hostOverrides/done.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/test/harness/src/host/dev/hostOverrides/done.js b/packages/test/harness/src/host/dev/hostOverrides/done.js index eb9aa4646b..2fdf0ac3ea 100644 --- a/packages/test/harness/src/host/dev/hostOverrides/done.js +++ b/packages/test/harness/src/host/dev/hostOverrides/done.js @@ -6,8 +6,8 @@ const override = require('../utils/override'); // Send the completion back to the browser console. module.exports = (webDriver, done) => - override(done, undefined, async () => { - await checkAccessibility(webDriver)(); + override(done, undefined, async ({ skipCheckAccessibility }) => { + skipCheckAccessibility || (await checkAccessibility(webDriver)()); /* istanbul ignore next */ await webDriver.executeScript(() => { From 97c14d71f6b29c6590af74cd047d8fb8fc573949 Mon Sep 17 00:00:00 2001 From: William Wong Date: Wed, 1 May 2024 00:37:52 +0000 Subject: [PATCH 03/12] Fix destructuring --- packages/test/harness/src/host/dev/hostOverrides/done.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/test/harness/src/host/dev/hostOverrides/done.js b/packages/test/harness/src/host/dev/hostOverrides/done.js index 2fdf0ac3ea..d1b1cd5a57 100644 --- a/packages/test/harness/src/host/dev/hostOverrides/done.js +++ b/packages/test/harness/src/host/dev/hostOverrides/done.js @@ -6,7 +6,7 @@ const override = require('../utils/override'); // Send the completion back to the browser console. module.exports = (webDriver, done) => - override(done, undefined, async ({ skipCheckAccessibility }) => { + override(done, undefined, async ({ skipCheckAccessibility } = {}) => { skipCheckAccessibility || (await checkAccessibility(webDriver)()); /* istanbul ignore next */ From d9d12eeee80b894d76c2c9177a97595bd4b0ae27 Mon Sep 17 00:00:00 2001 From: William Wong Date: Wed, 1 May 2024 00:44:17 +0000 Subject: [PATCH 04/12] Remove unnecessary accessibility check --- packages/test/harness/src/host/dev/hostOverrides/done.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/test/harness/src/host/dev/hostOverrides/done.js b/packages/test/harness/src/host/dev/hostOverrides/done.js index d1b1cd5a57..7751cf3384 100644 --- a/packages/test/harness/src/host/dev/hostOverrides/done.js +++ b/packages/test/harness/src/host/dev/hostOverrides/done.js @@ -1,14 +1,11 @@ // In dev mode, draw a green tick when test succeeded. -const checkAccessibility = require('../../common/host/checkAccessibility'); const dumpLogs = require('../../common/dumpLogs'); const override = require('../utils/override'); // Send the completion back to the browser console. module.exports = (webDriver, done) => - override(done, undefined, async ({ skipCheckAccessibility } = {}) => { - skipCheckAccessibility || (await checkAccessibility(webDriver)()); - + override(done, undefined, async () => { /* istanbul ignore next */ await webDriver.executeScript(() => { console.log( From 82be6dbd38064a46216407e781c27095a87df363 Mon Sep 17 00:00:00 2001 From: William Wong Date: Wed, 1 May 2024 00:54:20 +0000 Subject: [PATCH 05/12] Add performance test --- .../performance.manyMessages.allAtOnce.html | 40 ----------- .../performance/manyMessages.allAtOnce.html | 71 +++++++++++++++++++ .../performance/manyMessages.allAtOnce.js | 6 ++ .../manyMessages.oneByOne.html} | 2 + 4 files changed, 79 insertions(+), 40 deletions(-) delete mode 100644 __tests__/html/performance.manyMessages.allAtOnce.html create mode 100644 __tests__/html/performance/manyMessages.allAtOnce.html create mode 100644 __tests__/html/performance/manyMessages.allAtOnce.js rename __tests__/html/{performance.manyMessages.oneByOne.html => performance/manyMessages.oneByOne.html} (94%) diff --git a/__tests__/html/performance.manyMessages.allAtOnce.html b/__tests__/html/performance.manyMessages.allAtOnce.html deleted file mode 100644 index 85e8248e35..0000000000 --- a/__tests__/html/performance.manyMessages.allAtOnce.html +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - -
- - - diff --git a/__tests__/html/performance/manyMessages.allAtOnce.html b/__tests__/html/performance/manyMessages.allAtOnce.html new file mode 100644 index 0000000000..e286f98a14 --- /dev/null +++ b/__tests__/html/performance/manyMessages.allAtOnce.html @@ -0,0 +1,71 @@ + + + + + + + + + +
+ + + diff --git a/__tests__/html/performance/manyMessages.allAtOnce.js b/__tests__/html/performance/manyMessages.allAtOnce.js new file mode 100644 index 0000000000..d5a61ff681 --- /dev/null +++ b/__tests__/html/performance/manyMessages.allAtOnce.js @@ -0,0 +1,6 @@ +/** @jest-environment ./packages/test/harness/src/host/jest/WebDriverEnvironment.js */ + +describe('time taken to render 200 activities at batch of 20', () => { + test('should have similar performance for first half and second half', () => + runHTML('performnace/manyMessages.allAtOnce.html')); +}); diff --git a/__tests__/html/performance.manyMessages.oneByOne.html b/__tests__/html/performance/manyMessages.oneByOne.html similarity index 94% rename from __tests__/html/performance.manyMessages.oneByOne.html rename to __tests__/html/performance/manyMessages.oneByOne.html index a1fcf90a09..707a7f458f 100644 --- a/__tests__/html/performance.manyMessages.oneByOne.html +++ b/__tests__/html/performance/manyMessages.oneByOne.html @@ -38,6 +38,8 @@ console.log(`Took ${Date.now() - now} milliseconds.`); console.log(timeForEachMessage.join(',')); + + // TODO: How do we consider performance don't exponentially increase? }); From 9ef22abbb5c0309fd235e1643689ab1c5f5c1476 Mon Sep 17 00:00:00 2001 From: William Wong Date: Wed, 1 May 2024 00:57:12 +0000 Subject: [PATCH 06/12] Rename --- .../{manyMessages.allAtOnce.html => manyMessages.batched.html} | 2 ++ .../{manyMessages.allAtOnce.js => manyMessages.batched.js} | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) rename __tests__/html/performance/{manyMessages.allAtOnce.html => manyMessages.batched.html} (95%) rename __tests__/html/performance/{manyMessages.allAtOnce.js => manyMessages.batched.js} (80%) diff --git a/__tests__/html/performance/manyMessages.allAtOnce.html b/__tests__/html/performance/manyMessages.batched.html similarity index 95% rename from __tests__/html/performance/manyMessages.allAtOnce.html rename to __tests__/html/performance/manyMessages.batched.html index e286f98a14..e99b02f470 100644 --- a/__tests__/html/performance/manyMessages.allAtOnce.html +++ b/__tests__/html/performance/manyMessages.batched.html @@ -61,6 +61,8 @@ const averageOfFirstHalf = sumOfFirstHalf / firstHalf.length; const averageOfSecondHalf = sumOfSecondHalf / timeForEachQuorum.length; + console.log({ firstHalf, secondHalf: timeForEachQuorum, averageOfFirstHalf, averageOfSecondHalf }); + // Time taken to render the first half of the chat history, should be 80% similar to the time taken to render the second half of the chat history. expect(averageOfFirstHalf / averageOfSecondHalf).toBeGreaterThan(0.8); }, diff --git a/__tests__/html/performance/manyMessages.allAtOnce.js b/__tests__/html/performance/manyMessages.batched.js similarity index 80% rename from __tests__/html/performance/manyMessages.allAtOnce.js rename to __tests__/html/performance/manyMessages.batched.js index d5a61ff681..df3864b8b1 100644 --- a/__tests__/html/performance/manyMessages.allAtOnce.js +++ b/__tests__/html/performance/manyMessages.batched.js @@ -2,5 +2,5 @@ describe('time taken to render 200 activities at batch of 20', () => { test('should have similar performance for first half and second half', () => - runHTML('performnace/manyMessages.allAtOnce.html')); + runHTML('performnace/manyMessages.batched.html')); }); From 394024513d4fee1087fa936a9ec36741832a3fd3 Mon Sep 17 00:00:00 2001 From: William Wong Date: Thu, 2 May 2024 22:16:42 +0000 Subject: [PATCH 07/12] Use Map.get instead of [].find --- .../private/useActivityTreeWithRenderer.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/component/src/providers/ActivityTree/private/useActivityTreeWithRenderer.ts b/packages/component/src/providers/ActivityTree/private/useActivityTreeWithRenderer.ts index e2fc09d5ac..db0f8c2a02 100644 --- a/packages/component/src/providers/ActivityTree/private/useActivityTreeWithRenderer.ts +++ b/packages/component/src/providers/ActivityTree/private/useActivityTreeWithRenderer.ts @@ -1,6 +1,7 @@ import { hooks } from 'botframework-webchat-api'; import { useMemo } from 'react'; +import type { WebChatActivity } from 'botframework-webchat-core'; import intersectionOf from '../../../Utils/intersectionOf'; import removeInline from '../../../Utils/removeInline'; import type { ActivityWithRenderer, ReadonlyActivityTree } from './types'; @@ -35,6 +36,10 @@ function validateAllEntriesTagged(entries: readonly T[], bins: readonly (read function useActivityTreeWithRenderer(entries: readonly ActivityWithRenderer[]): ReadonlyActivityTree { const groupActivities = useGroupActivities(); + const entryMap: Map = useMemo( + () => new Map(entries.map(entry => [entry.activity, entry])), + [entries] + ); // We bin activities in 2 different ways: // - `activitiesBySender` is a 2D array containing activities with same sender @@ -45,7 +50,7 @@ function useActivityTreeWithRenderer(entries: readonly ActivityWithRenderer[]): entriesBySender: readonly (readonly ActivityWithRenderer[])[]; entriesByStatus: readonly (readonly ActivityWithRenderer[])[]; }>(() => { - const visibleActivities = entries.map(({ activity }) => activity); + const visibleActivities = [...entryMap.keys()]; const groupActivitiesResult = groupActivities({ activities: visibleActivities }); @@ -53,7 +58,7 @@ function useActivityTreeWithRenderer(entries: readonly ActivityWithRenderer[]): const activitiesByStatus = groupActivitiesResult?.status || []; const [entriesBySender, entriesByStatus] = [activitiesBySender, activitiesByStatus].map(bins => - bins.map(bin => bin.map(activity => entries.find(entry => entry.activity === activity))) + bins.map(bin => bin.map(activity => entryMap.get(activity))) ); if (!validateAllEntriesTagged(visibleActivities, activitiesBySender)) { @@ -72,7 +77,7 @@ function useActivityTreeWithRenderer(entries: readonly ActivityWithRenderer[]): entriesBySender, entriesByStatus }; - }, [entries, groupActivities]); + }, [entryMap, groupActivities]); // Create a tree of activities with 2 dimensions: sender, followed by status. From 6ab69192a6c8b5125a9e7db9f404f9e60933755b Mon Sep 17 00:00:00 2001 From: William Wong Date: Fri, 3 May 2024 18:19:23 +0000 Subject: [PATCH 08/12] Clean up tests --- __tests__/html/performance/README.md | 1 + .../performance/manyMessages.batched.html | 19 +++++++++++++++++-- .../html/performance/manyMessages.batched.js | 6 ------ 3 files changed, 18 insertions(+), 8 deletions(-) create mode 100644 __tests__/html/performance/README.md delete mode 100644 __tests__/html/performance/manyMessages.batched.js diff --git a/__tests__/html/performance/README.md b/__tests__/html/performance/README.md new file mode 100644 index 0000000000..d01855da90 --- /dev/null +++ b/__tests__/html/performance/README.md @@ -0,0 +1 @@ +Tests in this folder may not have its corresponding `.js` file as we are still exploring how to write tests for tracking performance issues. diff --git a/__tests__/html/performance/manyMessages.batched.html b/__tests__/html/performance/manyMessages.batched.html index e99b02f470..0c60fc9602 100644 --- a/__tests__/html/performance/manyMessages.batched.html +++ b/__tests__/html/performance/manyMessages.batched.html @@ -30,7 +30,13 @@ let lastFlushAt = Date.now(); for (let index = 0; index < NUM_MESSAGE; index++) { - promises.push(directLine.emulateIncomingActivity(`Message ${index}.`, { skipWait: true })); + promises.push( + // Plain text message isolate dependencies on Markdown. + directLine.emulateIncomingActivity( + { text: `Message ${index}.`, textFormat: 'plain', type: 'message' }, + { skipWait: true } + ) + ); if (promises.length >= QUORUM_SIZE) { await Promise.all(promises.splice(0)); @@ -53,6 +59,10 @@ await pageConditions.numActivitiesShown(NUM_MESSAGE); + // Remove outliers. + timeForEachQuorum.shift(); + timeForEachQuorum.shift(); + const firstHalf = timeForEachQuorum.splice(0, timeForEachQuorum.length >> 1); const sumOfFirstHalf = firstHalf.reduce((sum, time) => sum + time, 0); @@ -61,7 +71,12 @@ const averageOfFirstHalf = sumOfFirstHalf / firstHalf.length; const averageOfSecondHalf = sumOfSecondHalf / timeForEachQuorum.length; - console.log({ firstHalf, secondHalf: timeForEachQuorum, averageOfFirstHalf, averageOfSecondHalf }); + console.log(`Took ${Date.now() - startAt} ms.`, { + firstHalf, + secondHalf: timeForEachQuorum, + averageOfFirstHalf, + averageOfSecondHalf + }); // Time taken to render the first half of the chat history, should be 80% similar to the time taken to render the second half of the chat history. expect(averageOfFirstHalf / averageOfSecondHalf).toBeGreaterThan(0.8); diff --git a/__tests__/html/performance/manyMessages.batched.js b/__tests__/html/performance/manyMessages.batched.js deleted file mode 100644 index df3864b8b1..0000000000 --- a/__tests__/html/performance/manyMessages.batched.js +++ /dev/null @@ -1,6 +0,0 @@ -/** @jest-environment ./packages/test/harness/src/host/jest/WebDriverEnvironment.js */ - -describe('time taken to render 200 activities at batch of 20', () => { - test('should have similar performance for first half and second half', () => - runHTML('performnace/manyMessages.batched.html')); -}); From c1870bfd7540c1b930c1ad51c0737921906e7d0d Mon Sep 17 00:00:00 2001 From: William Wong Date: Fri, 3 May 2024 18:57:39 +0000 Subject: [PATCH 09/12] Add entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cc7dfaf41d..6c31358246 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -78,6 +78,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Fixes missing exports of `useNotifications`, in PR [#5148](https://github.com/microsoft/BotFramework-WebChat/pull/5148), by [@compulim](https://github.com/compulim) - Fixes suggested actions keyboard navigation skips actions after suggested actions got updated, in PR [#5150](https://github.com/microsoft/BotFramework-WebChat/pull/5150), by [@OEvgeny](https://github.com/OEvgeny) - Fixes [#5155](https://github.com/microsoft/BotFramework-WebChat/issues/5155). Fixed "Super constructor null of anonymous class is not a constructor" error in CDN bundle by bumping to [`webpack@5.91.0`](https://www.npmjs.com/package/webpack/v/5.91.0), in PR [#5156](https://github.com/microsoft/BotFramework-WebChat/pull/5156), by [@compulim](https://github.com/compulim) +- Fixes [#5162](https://github.com/microsoft/BotFramework-WebChat/issues/5162). Improved performance for `useActivityTreeWithRenderer`, in PR [#XXX}(https://github.com/microsoft/BotFramework-WebChat/pull/XXX), by [@compulim](https://github.com/compulim) ### Changed From 1fac1b2e4ba567695daefc077df289f05695c2c8 Mon Sep 17 00:00:00 2001 From: William Wong Date: Fri, 3 May 2024 18:58:18 +0000 Subject: [PATCH 10/12] Update PR number --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c31358246..f67abcc1cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -78,7 +78,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Fixes missing exports of `useNotifications`, in PR [#5148](https://github.com/microsoft/BotFramework-WebChat/pull/5148), by [@compulim](https://github.com/compulim) - Fixes suggested actions keyboard navigation skips actions after suggested actions got updated, in PR [#5150](https://github.com/microsoft/BotFramework-WebChat/pull/5150), by [@OEvgeny](https://github.com/OEvgeny) - Fixes [#5155](https://github.com/microsoft/BotFramework-WebChat/issues/5155). Fixed "Super constructor null of anonymous class is not a constructor" error in CDN bundle by bumping to [`webpack@5.91.0`](https://www.npmjs.com/package/webpack/v/5.91.0), in PR [#5156](https://github.com/microsoft/BotFramework-WebChat/pull/5156), by [@compulim](https://github.com/compulim) -- Fixes [#5162](https://github.com/microsoft/BotFramework-WebChat/issues/5162). Improved performance for `useActivityTreeWithRenderer`, in PR [#XXX}(https://github.com/microsoft/BotFramework-WebChat/pull/XXX), by [@compulim](https://github.com/compulim) +- Fixes [#5162](https://github.com/microsoft/BotFramework-WebChat/issues/5162). Improved performance for `useActivityTreeWithRenderer`, in PR [#5163}(https://github.com/microsoft/BotFramework-WebChat/pull/5163), by [@compulim](https://github.com/compulim) ### Changed From e05c3e53e3c6e51c5cc9825e9f2f6e8c7d413041 Mon Sep 17 00:00:00 2001 From: William Wong Date: Fri, 3 May 2024 18:58:31 +0000 Subject: [PATCH 11/12] Typo --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f67abcc1cc..09f4b72210 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -78,7 +78,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Fixes missing exports of `useNotifications`, in PR [#5148](https://github.com/microsoft/BotFramework-WebChat/pull/5148), by [@compulim](https://github.com/compulim) - Fixes suggested actions keyboard navigation skips actions after suggested actions got updated, in PR [#5150](https://github.com/microsoft/BotFramework-WebChat/pull/5150), by [@OEvgeny](https://github.com/OEvgeny) - Fixes [#5155](https://github.com/microsoft/BotFramework-WebChat/issues/5155). Fixed "Super constructor null of anonymous class is not a constructor" error in CDN bundle by bumping to [`webpack@5.91.0`](https://www.npmjs.com/package/webpack/v/5.91.0), in PR [#5156](https://github.com/microsoft/BotFramework-WebChat/pull/5156), by [@compulim](https://github.com/compulim) -- Fixes [#5162](https://github.com/microsoft/BotFramework-WebChat/issues/5162). Improved performance for `useActivityTreeWithRenderer`, in PR [#5163}(https://github.com/microsoft/BotFramework-WebChat/pull/5163), by [@compulim](https://github.com/compulim) +- Fixes [#5162](https://github.com/microsoft/BotFramework-WebChat/issues/5162). Improved performance for `useActivityTreeWithRenderer`, in PR [#5163](https://github.com/microsoft/BotFramework-WebChat/pull/5163), by [@compulim](https://github.com/compulim) ### Changed From 549bb937f90eca149e88b329783e52e1b2a180f3 Mon Sep 17 00:00:00 2001 From: William Wong Date: Wed, 8 May 2024 15:12:50 -0700 Subject: [PATCH 12/12] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 52da7dde58..e903c43847 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,8 +24,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Fixed -- Fixes [#5162](https://github.com/microsoft/BotFramework-WebChat/issues/5162). Improved performance for `useActivityTreeWithRenderer`, in PR [#5163](https://github.com/microsoft/BotFramework-WebChat/pull/5163), by [@compulim](https://github.com/compulim) - Improved performance for `useActivityWithRenderer`, in PR [#5172](https://github.com/microsoft/BotFramework-WebChat/pull/5172), by [@OEvgeny](https://github.com/OEvgeny) +- Fixes [#5162](https://github.com/microsoft/BotFramework-WebChat/issues/5162). Improved performance for `useActivityTreeWithRenderer`, in PR [#5163](https://github.com/microsoft/BotFramework-WebChat/pull/5163), by [@compulim](https://github.com/compulim) ### Changed