#time is 0

19 messages · Page 1 of 1 (latest)

loud axleBOT
#

Hi @pine raft. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:

#

The code you've shared is a Convex internal mutation function that updates a project in the database and measures the execution time. This is a good practice for performance monitoring in Convex applications.

Let me explain what this code does:

  1. It defines an internal mutation (only callable from other Convex functions, not directly from clients) The Zen of Convex

  2. It measures execution time using Date.now() at the start and end of the function, then logs the total time taken

  3. It looks up a project by its projectId using an index called by_project_id

  4. If the project exists, it updates it with the provided elements after removing undefined keys

  5. It returns a boolean indicating success or failure

The timing logs are particularly useful for performance debugging. In Convex, mutations should ideally complete quickly (under 100ms) for optimal application responsiveness, as mentioned in the The Zen of Convex documentation:

Keep sync engine functions light & fast. In general, your mutations and queries should be working with less than a few hundred records and should aim to finish in less than 100ms.

If you're seeing performance issues with this mutation, you might want to:

  1. Check if the index lookup is efficient
  2. Examine what's in the removeUndefinedKeys function (not shown in your code)
  3. Consider if the patch operation is updating too many fields at once

For more complex operations that might take longer, you could consider using an action instead of a mutation, especially if you're integrating with external services.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@pine raft Kapa.ai is still learning and improving, please let me know how I did by reacting below.

pine raft
#

@loud axle the start and end are both the same value, like the mutation took 0ms to execute... it's strange

loud axleBOT
#

Let me check the knowledge base for you again. One moment! :books:

#

You're right, it is strange that the start and end timestamps are showing the same value, making it appear like the mutation took 0ms to execute. This behavior is actually explained by how Convex handles time in mutations.

According to the Convex documentation, the system time during Convex function execution is "frozen" when the function begins:

To ensure the logic within your function is reproducible, the system time used globally (outside of any function) is "frozen" at deploy time, while the system time during Convex function execution is "frozen" when the function begins. Date.now() will return the same result for the entirety of your function's execution.

Convex Runtimes Documentation explains this behavior:

export const updateSomething = mutation({  
  args: {},  
  handler: () => {  
    const now1 = Date.now(); // `now1` is the time when the function execution started.  
    // implementation  
    const now2 = Date.now(); // `now2` === `now1`  
  },  
});  

This is a deliberate design choice to ensure determinism in Convex mutations and queries. Since Convex uses optimistic concurrency control and may need to retry mutations, having deterministic behavior (including time functions) is essential.

If you want to measure execution time within your Convex functions, you could use:

  1. console.time() and console.timeEnd() which are supported in the Convex runtime
  2. A counter or other mechanism that doesn't rely on system time

For example:

export const _internal = internalMutation({
  args,
  handler: async (ctx, args): Promise<boolean> => {
    console.time("updateProject");
    
    // Your function logic here
    
    console.timeEnd("updateProject");
    return true;
  },
})
#

This will give you an accurate measurement of execution time in your logs.

Hope this helps explain the behavior you're seeing!

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@pine raft Kapa.ai is still learning and improving, please let me know how I did by reacting below.

pine raft
#

It looks like the problem comes from useMutation in the client. It takes around 2600s to run it, when the mutation only took 50ms to run on the server, why that

#

@loud axle It looks like the problem comes from useMutation in the client. It takes around 2600s to run it, when the mutation only took 50ms to run on the server, why that

loud axleBOT
#

Let me check the knowledge base for you again. One moment! :books:

#

Based on the information in the knowledge sources, there are several reasons why a mutation might take significantly longer to complete from the client perspective (2600ms) compared to the server execution time (50ms).

Network Latency and Cold Starts

One major factor could be network latency between your client and the Convex backend. As mentioned in one of the Discord support threads:

The network latency is negligible, but AWS Lambda cold starts are not.

Discord support thread shows that if you're using Node.js actions, there can be significant cold start times that add to the overall latency.

Mutation Execution Process

When you call a mutation from the client using useMutation, there's a complete round-trip process that happens:

  1. The client sends a message over WebSocket to the Convex sync worker
  2. The sync worker passes this to the function runner
  3. The function runner executes the mutation
  4. The transaction is forwarded to the committer
  5. The committer appends writes to the transaction log
  6. The result is sent back to the client

As described in How Convex Works, this entire process involves multiple steps beyond just the function execution time.

Potential Solutions

1. Optimistic Updates

If UI responsiveness is a concern, consider implementing optimistic updates:

const myMutation = useMutation(api.myModule.myMutation).withOptimisticUpdate(
  (localStore, args) => {
    const existingData = localStore.getQuery(api.myModule.myQuery, queryArgs);
    if (existingData !== undefined) {
      localStore.setQuery(api.myModule.myQuery, queryArgs, updatedData);
    }
  }
);
#

This will make your UI feel more responsive while the actual mutation completes in the background, as explained in Optimistic Updates.

2. Performance Debugging

You can add timing logs on the client side to identify where the bottleneck is occurring:

const handleAction = async () => {
  const startTime = performance.now();
  await myMutation(args);
  console.log(`Total time: ${performance.now() - startTime}ms`);
};

3. Check for Heavy Indexes

As mentioned in one of the Discord threads, queries with large indexes can cause performance issues. If your mutation is calling queries internally, this could be a factor.

4. Deployment Tier

One Discord thread mentioned:

this is on a convex starter instance; wondering if pro helps significantly

If you're on a starter instance, upgrading to a Pro tier might improve performance for production workloads.

If you continue to experience high latency, I'd recommend adding more detailed timing logs both on the client and server to pinpoint exactly where the delay is occurring in the request lifecycle.

Would you like more specific guidance on implementing any of these solutions?

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@pine raft Kapa.ai is still learning and improving, please let me know how I did by reacting below.

pine raft
#

@loud axle the server is correctly running my mutation in under a few ms.
But the client takes 2.6s to make it run

loud axleBOT
#

Let me check the knowledge base for you again. One moment! :books:

#

Based on the knowledge sources, there are several potential reasons why your client is taking 2.6s to run a mutation that only takes a few milliseconds on the server.

Schema Validation Overhead

One of the most common causes of client-side latency in Convex is schema validation:

At the moment, queries do parse schemas, yes

Discord support thread shows that large schemas (especially with nested discriminated unions) can significantly impact performance. Some users experienced similar issues with queries taking 1.6+ seconds despite fast server execution.

The Convex team mentioned they're working on optimizing this:

the good news is there are some paths like this that we're working on optimizing that are not intrinsic--they happen to be O(project size) instead of O(function call), but there's no fundamental reason for this

Request Lifecycle Overhead

When a mutation is called from the client, it goes through several steps:

  1. Client sends request via WebSocket
  2. Sync worker processes request
  3. Function runner executes the mutation
  4. Committer handles transaction
  5. Result is sent back to client

This entire process is described in How Convex Works and can add overhead beyond just the function execution time.

Potential Solutions

1. Optimistic Updates

Implement optimistic updates to make your UI feel more responsive while the actual mutation completes:

#
const myMutation = useMutation(api.myModule.myMutation).withOptimisticUpdate(
  (localStore, args) => {
    // Update local state immediately
    const currentData = localStore.getQuery(api.myModule.myQuery, queryParams);
    if (currentData !== undefined) {
      localStore.setQuery(api.myModule.myQuery, queryParams, updatedData);
    }
  }
);

As explained in Optimistic Updates, this approach can significantly improve perceived performance.

2. Single-Flighting for Frequent Updates

If you're making frequent mutation calls, consider implementing single-flighting to batch updates:

const myMutation = useMutation(api.my.mutation);
const tryUpdate = useSingleFlight(withLocalStore);
const withLocalStore = useCallback((data) => {
  setLocalState(data);
  return tryUpdate(data);
}, [setLocalState, updatePresence]);

This pattern is described in Throttling Requests by Single-Flighting and can help reduce the number of mutation calls.

3. Check with Convex Support

The Convex team has been actively working on performance improvements for users with similar issues. You might want to reach out to their support with details about your schema size and deployment, as they've been able to help other users:

Seems like as of now, our dev and staging deployments have been sped up by 5-10x but our production deployment still has pretty high latency.

I recommend implementing optimistic updates as an immediate solution while also considering reaching out to Convex support if the issue persists.

#

Would you like more specific guidance on implementing any of these solutions?

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: